Merge branch 'krh/master'
authorJames Bowes <jbowes@redhat.com>
Fri Jun 20 19:04:47 2008 -0400 (2008-06-20)
changeset 25829d5002bd17f
parent 229 cae6308aa5b1
parent 248 057933050c42
child 259 5b0601d184ed
Merge branch 'krh/master'

Conflicts:

librazor/razor.h
librazor/rpm.c
razor.c
src/main.c
DEPSOLVE.txt
Makefile
REPO.txt
bash-completion.sh
data/bash-completion.sh
librazor/importer.c
librazor/razor-internal.h
librazor/razor.c
librazor/razor.h
librazor/root.c
librazor/rpm.c
main.c
razor-internal.h
razor.c
razor.h
rpm-razor.c
rpm.c
src/import-rpmdb.c
src/import-yum.c
src/main.c
src/test-driver.c
test-driver.c
test.xml
types.c
types.h
util.c
yum.c
     1.1 --- a/.gitignore	Sun Jun 15 18:16:20 2008 -0400
     1.2 +++ b/.gitignore	Fri Jun 20 19:04:47 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	Fri Jun 20 19:04:47 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 18:16:20 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 18:16:20 2008 -0400
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,23 +0,0 @@
     4.4 -CFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes -g
     4.5 -LDLIBS = -lexpat -lz -g -lrpm -lcurl
     4.6 -
     4.7 -all : razor test-driver rpm-razor
     4.8 -
     4.9 -razor : razor.o yum.o main.o rpm.o types.o util.o
    4.10 -
    4.11 -*.o : razor.h razor-internal.h
    4.12 -razor.o : types.h
    4.13 -
    4.14 -test-driver : razor.o types.o util.o test-driver.o
    4.15 -
    4.16 -rpm-razor : rpm-razor.o razor.o types.o util.o rpm.o
    4.17 -
    4.18 -test : test-driver
    4.19 -	./test-driver test.xml
    4.20 -
    4.21 -reset : ./razor
    4.22 -	sudo rm -rf install
    4.23 -	./razor init
    4.24 -
    4.25 -clean :
    4.26 -	rm -f *.o razor
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/Makefile.am	Fri Jun 20 19:04:47 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 18:16:20 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	Fri Jun 20 19:04:47 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 18:16:20 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 "info: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 -	    info|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	Fri Jun 20 19:04:47 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/contrib/razor.spec	Fri Jun 20 19:04:47 2008 -0400
    10.3 @@ -0,0 +1,100 @@
    10.4 +Summary:   Razor is a package management system replacing rpm and yum
    10.5 +Name:      razor
    10.6 +Version:   0.1
    10.7 +Release:   0.1%{?dist}
    10.8 +License:   GPLv2+
    10.9 +Group:     System Environment/Libraries
   10.10 +URL:       http://github.com/krh/razor/wikis
   10.11 +Source0:   http://people.freedesktop.org/~krh/releases/%{name}-%{version}.tar.gz
   10.12 +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
   10.13 +
   10.14 +Requires: expat
   10.15 +Requires: rpm-libs
   10.16 +
   10.17 +BuildRequires: expat-devel
   10.18 +BuildRequires: libtool
   10.19 +BuildRequires: gettext
   10.20 +BuildRequires: libcurl-devel
   10.21 +BuildRequires: rpm-devel
   10.22 +BuildRequires: zlib-devel
   10.23 +BuildRequires: perl(XML::Parser)
   10.24 +
   10.25 +%description
   10.26 +Razor is a package management system replacing rpm and yum.
   10.27 +Razor implements management of packages installed on the system,
   10.28 +dependency solving, and upgrading in a small compact code base with
   10.29 +minimal dependencies.
   10.30 +
   10.31 +%package libs
   10.32 +Summary: Libraries for accessing razor
   10.33 +Group: Development/Libraries
   10.34 +Requires: expat >= %{dbus_version}
   10.35 +Requires: %{name} = %{version}-%{release}
   10.36 +
   10.37 +%description libs
   10.38 +Libraries for accessing razor.
   10.39 +
   10.40 +%package devel
   10.41 +Summary: Libraries and headers for razor
   10.42 +Group: Development/Libraries
   10.43 +Requires: %{name} = %{version}-%{release}
   10.44 +Requires: pkgconfig
   10.45 +Requires: libcurl-devel
   10.46 +Requires: rpm-devel
   10.47 +Requires: zlib-devel
   10.48 +
   10.49 +%description devel
   10.50 +Headers and libraries for razor.
   10.51 +
   10.52 +%prep
   10.53 +%setup -q
   10.54 +
   10.55 +%build
   10.56 +%configure
   10.57 +
   10.58 +make %{?_smp_mflags}
   10.59 +
   10.60 +%install
   10.61 +rm -rf $RPM_BUILD_ROOT
   10.62 +make install DESTDIR=$RPM_BUILD_ROOT
   10.63 +
   10.64 +rm -f $RPM_BUILD_ROOT%{_libdir}/librazor*.a
   10.65 +rm -f $RPM_BUILD_ROOT%{_libdir}/librazor*.la
   10.66 +mv $RPM_BUILD_ROOT%{_bindir}/rpm $RPM_BUILD_ROOT%{_bindir}/rpm-razor
   10.67 +
   10.68 +#%find_lang %name
   10.69 +
   10.70 +%clean
   10.71 +rm -rf $RPM_BUILD_ROOT
   10.72 +
   10.73 +%post libs -p /sbin/ldconfig
   10.74 +
   10.75 +%postun libs -p /sbin/ldconfig
   10.76 +
   10.77 +%files
   10.78 +# -f %{name}.lang
   10.79 +%defattr(-,root,root,-)
   10.80 +%doc README AUTHORS NEWS COPYING
   10.81 +%dir %{_datadir}/doc/razor
   10.82 +%doc %{_datadir}/doc/razor/*.txt
   10.83 +%config %{_sysconfdir}/bash_completion.d/*.sh
   10.84 +%{_bindir}/razor
   10.85 +%{_bindir}/rpm-razor
   10.86 +%exclude %{_libdir}/librazor*.so.*
   10.87 +
   10.88 +%files libs
   10.89 +%defattr(-,root,root,-)
   10.90 +%doc README AUTHORS NEWS COPYING
   10.91 +%{_libdir}/*razor*.so.*
   10.92 +
   10.93 +%files devel
   10.94 +%defattr(-,root,root,-)
   10.95 +
   10.96 +%{_libdir}/lib*.so
   10.97 +%{_libdir}/pkgconfig/*
   10.98 +%{_includedir}/*
   10.99 +
  10.100 +%changelog
  10.101 +* Mon Jun 16 2008 Richard Hughes <richard@hughsie.com> 0.1-0.1
  10.102 +- Initial version
  10.103 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/data/.gitignore	Fri Jun 20 19:04:47 2008 -0400
    11.3 @@ -0,0 +1,2 @@
    11.4 +razor.pc
    11.5 +
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/data/Makefile.am	Fri Jun 20 19:04:47 2008 -0400
    12.3 @@ -0,0 +1,11 @@
    12.4 +## Process this file with automake to produce Makefile.in
    12.5 +
    12.6 +pkgconfigdir = $(libdir)/pkgconfig
    12.7 +pkgconfig_DATA = razor.pc
    12.8 +
    12.9 +bashcompletiondir = ${SYSCONFDIR}/bash_completion.d
   12.10 +dist_bashcompletion_DATA = bash-completion.sh
   12.11 +
   12.12 +clean-local :
   12.13 +	rm -f *~
   12.14 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/data/bash-completion.sh	Fri Jun 20 19:04:47 2008 -0400
    13.3 @@ -0,0 +1,47 @@
    13.4 +__razor_commands () {
    13.5 +    local IFS=$'\n'
    13.6 +    COMPREPLY=($(IFS=: compgen -S' ' -W "info: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))
    13.7 +}
    13.8 +
    13.9 +__razor_packages () {
   13.10 +    local IFS=$'\n'
   13.11 +
   13.12 +    COMPREPLY=($(./razor list --only-names "$1*" | while read p; do echo "$p "; done))
   13.13 +}
   13.14 +
   13.15 +__razor_upstream_packages () {
   13.16 +    local IFS=$'\n'
   13.17 +
   13.18 +    COMPREPLY=($(RAZOR_REPO=rawhide.repo ./razor list --only-names "$1*" | while read p; do echo "$p "; done))
   13.19 +}
   13.20 +
   13.21 +__razor_files() {
   13.22 +    COMPREPLY=($(./razor list-files "$1*"))
   13.23 +}
   13.24 +
   13.25 +__razor_requires() {
   13.26 +    COMPREPLY=($(compgen -W "$(./razor list-requires)" -- $1))
   13.27 +}
   13.28 +
   13.29 +__razor_provides() {
   13.30 +    COMPREPLY=($(compgen -W "$(./razor list-provides)" -- $1))
   13.31 +}
   13.32 +
   13.33 +__razor() {
   13.34 +    local cur="${COMP_WORDS[COMP_CWORD]}"
   13.35 +
   13.36 +    if [ $COMP_CWORD = 1 ]; then
   13.37 +	__razor_commands $cur
   13.38 +    else
   13.39 +	case "${COMP_WORDS[1]}" in
   13.40 +	    info|list-requires|list-provides|list-package-files)
   13.41 +		__razor_packages $cur ;;
   13.42 +	    list-files|list-file-packages) __razor_files $cur ;;
   13.43 +	    what-requires) __razor_requires $cur ;;
   13.44 +	    what-provides) __razor_provides $cur ;;
   13.45 +	    install|download) __razor_upstream_packages $cur ;;
   13.46 +	esac
   13.47 +    fi
   13.48 +}
   13.49 +
   13.50 +complete -o nospace -F __razor razor
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/data/razor.pc.in	Fri Jun 20 19:04:47 2008 -0400
    14.3 @@ -0,0 +1,12 @@
    14.4 +prefix=@prefix@
    14.5 +exec_prefix=@exec_prefix@
    14.6 +libdir=@libdir@
    14.7 +includedir=@includedir@
    14.8 +
    14.9 +Name: razor
   14.10 +Description: library for depsolving, installing and removing packages
   14.11 +Version: @VERSION@
   14.12 +Requires: expat curl
   14.13 +Libs: -L${libdir} -lexpat -lz -lcurl
   14.14 +Cflags: -I${includedir}/razor
   14.15 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/docs/DEPSOLVE.txt	Fri Jun 20 19:04:47 2008 -0400
    15.3 @@ -0,0 +1,364 @@
    15.4 +YUM vs RAZOR
    15.5 +------------
    15.6 +
    15.7 +At a very high level, yum's depsolver does something roughly
    15.8 +equivalent to:
    15.9 +
   15.10 +    - For each package being installed or removed
   15.11 +
   15.12 +	- For each relevant property (provides, requires, conflicts,
   15.13 +          obsoletes):
   15.14 +
   15.15 +	    - Figure out what additional packages need to be added to
   15.16 +	      or removed from the system to satisfy this property
   15.17 +
   15.18 +which ends up being roughly O(N^2 * M) where N is the total number of
   15.19 +properties and M is the number of packages being acted on.
   15.20 +
   15.21 +(I just figured that out off the top of my head, and I'm not totally
   15.22 +familiar with the yum code, so it may be wrong.)
   15.23 +
   15.24 +Razor's depsolver is something like:
   15.25 +
   15.26 +    - do {
   15.27 +
   15.28 +	- For each property to be added to or removed from the system:
   15.29 +
   15.30 +	    - Figure out what packages need to be added to or removed
   15.31 +	      from the system to satisfy this property
   15.32 +
   15.33 +    - } until we stop adding/remove more packages
   15.34 +
   15.35 +with the key being that it's very easy to find the PROVIDES
   15.36 +corresponding to a REQUIRES and vice versa, because the property
   15.37 +arrays are sorted, and so all properties with the same "name" will be
   15.38 +adjacent to one another in the array, allowing many dependencies to be
   15.39 +satisified in essentially constant time. (Actually... we've been
   15.40 +calling it constant, but it's really O(log N) for heavily-depended-on
   15.41 +packages, because the more packages you have, the more variations on
   15.42 +"requires foo", "requires foo = 1.1", "requires foo > 1.0", etc you're
   15.43 +going to have to scan through.)
   15.44 +
   15.45 +Ideally though, each iteration of the inner loop body happens in
   15.46 +constant time, and thus the inner loop as a whole is O(N), and thus
   15.47 +the depsolver as a whole is O(N * M) (or at least, less than
   15.48 +O(N * M * log N).
   15.49 +
   15.50 +
   15.51 +FILE DEPENDENCIES
   15.52 +-----------------
   15.53 +
   15.54 +Whenever we add a package with a file REQUIRES to a razor_set, we also
   15.55 +add a PROVIDES for that file to the package or packages which provide
   15.56 +that file. This means that if we later add another package that
   15.57 +requires the same file (eg, /bin/sh or /usr/bin/perl), we can resolve
   15.58 +its file requirement exactly like we would resolve a property
   15.59 +requirement, in nearly constant time.
   15.60 +
   15.61 +When adding a *new* file requirement (ie, a requirement on a file that
   15.62 +no existing package depends on), we still have to scan through the
   15.63 +file tree, which is O(log N) in the number of files.
   15.64 +
   15.65 +(AFAICT, there's no reason yum couldn't do the same optimization.
   15.66 +Also, AFAICT, yum currently sticks property dependencies and file
   15.67 +dependencies into the same hash table, so that if any package in the
   15.68 +transaction has a file dependency, it causes *property* dependencies
   15.69 +to become slower to resolve as well...)
   15.70 +
   15.71 +
   15.72 +THE RULES
   15.73 +---------
   15.74 +
   15.75 +This is what we have figured out for transaction-solving rules;
   15.76 +neither yum nor rpm's algorithm seems to be explained in full
   15.77 +anywhere...
   15.78 +
   15.79 +    1. Every requested install in the initial package set must be
   15.80 +       satisfied as either a new install or an update:
   15.81 +
   15.82 +	- if the requested package name is the name of an upstream
   15.83 +          package:
   15.84 +
   15.85 +	    - if there is not a corresponding already-installed
   15.86 +              package, then install the upstream package
   15.87 +
   15.88 +	    - else if the upstream package is newer than the
   15.89 +              already-installed package, then update the package
   15.90 +
   15.91 +	    - else it's an error (UP_TO_DATE)
   15.92 +
   15.93 +	- else if the requested package name is the name of an
   15.94 +          already-installed package:
   15.95 +
   15.96 +	    - if there is an upstream package that obsoletes the
   15.97 +              already-installed package, then behave as though the
   15.98 +              user had requested that that package be installed
   15.99 +              instead.
  15.100 +
  15.101 +	    - else it's an error (UP_TO_DATE or INSTALL_UNAVAILABLE?)
  15.102 +
  15.103 +	- else it's an error (INSTALL_UNAVAILABLE)
  15.104 +
  15.105 +    2. Every requested removal in the initial package set must be
  15.106 +       satisfied as a removal. If any requested package name is not
  15.107 +       the name of an installed package, it's an error
  15.108 +       (REMOVE_NOT_INSTALLED)
  15.109 +
  15.110 +    REQUIRES processing:
  15.111 +
  15.112 +    3. If a package being installed or updated-to REQUIRES a property
  15.113 +       that is not provided by any installed or to-be-installed
  15.114 +       package, we need to find an installable package that provides
  15.115 +       that property. If we find one, install/update it. If not, it's
  15.116 +       an error (UNSATISFIABLE). (If we find an upstream package
  15.117 +       providing the property that corresponds to a system package
  15.118 +       that's being removed, then it's a CONTRADICTION.)
  15.119 +
  15.120 +    4. If an already-installed package REQUIRES a property which is
  15.121 +       only provided by a package that is being removed, then that
  15.122 +       package needs to be removed as well.
  15.123 +
  15.124 +    5. If an already-installed package REQUIRES a property which is
  15.125 +       only provided by a package that is being upgraded or obsoleted
  15.126 +       (to a new package which does not provide that property), then:
  15.127 +
  15.128 +	- if there is an update for the installed package, then update
  15.129 +          the installed package
  15.130 +
  15.131 +	- else if there is another installable package that provides
  15.132 +          the required property, then install that.
  15.133 +
  15.134 +	- else it's an error (UNSATISFIABLE?)
  15.135 +
  15.136 +    CONFLICTS processing
  15.137 +
  15.138 +    6. If a package being installed or updated-to CONFLICTS with a
  15.139 +       property provided by an installed package:
  15.140 +
  15.141 +	- if there is an update for the installed package, which the
  15.142 +          new package does not conflict with, then update the
  15.143 +          installed package.
  15.144 +
  15.145 +	- else it's an error (NEW_CONFLICT)
  15.146 +
  15.147 +    7. If an already-installed package CONFLICTS with a property
  15.148 +       provided by a to-be-installed package:
  15.149 +
  15.150 +	- if there is an update for the installed package, which does
  15.151 +          not conflict with the new package, then update the installed
  15.152 +          package.
  15.153 +
  15.154 +	- else it's an error (NEW_CONFLICT)
  15.155 +
  15.156 +    8. If a package being installed or updated-to CONFLICTS with a
  15.157 +       property provided by a to-be-installed package, then it's an
  15.158 +       error (CONTRADICTION).
  15.159 +
  15.160 +    OBSOLETES processing. NOTE: OBSOLETES are only matched against
  15.161 +    package names, not against arbitrary provided properties
  15.162 +
  15.163 +    9. If a package being installed or updated-to OBSOLETES an
  15.164 +       installed package, then obsolete that package. (ie, remove it,
  15.165 +       but treat it as updated for purposes of dangling REQUIRES).
  15.166 +
  15.167 +   10. If an already-installed package OBSOLETES a to-be-installed
  15.168 +       package, then it's an error. (ALREADY_OBSOLETE)
  15.169 +
  15.170 +   11. If a package being installed or updated-to OBSOLETES another
  15.171 +       package being installed or updated-to, then it's an error
  15.172 +       (CONTRADICTION).
  15.173 +
  15.174 +
  15.175 +
  15.176 +THE DEPSOLVER
  15.177 +-------------
  15.178 +
  15.179 +We start with two razor_sets, system and upstream, and a list of
  15.180 +requested installations and removals.
  15.181 +
  15.182 +    FIXME: what about multiple upstream repos? Having to deal with
  15.183 +    arbitrary numbers of razor_sets is possible, but will probably be
  15.184 +    messy... It might be easier to either store all upstream repo data
  15.185 +    in a single .repo file, or else merge all upstream .repo files
  15.186 +    together into a single razor_set at startup. (Or some combination
  15.187 +    of those.)
  15.188 +
  15.189 +We create a bit array of the packages in each set, indicating which
  15.190 +ones are installed; the system bitarray starts out all 1s, and the
  15.191 +upstream bitarray all 0s. Each bit is only allowed to change state
  15.192 +once during the transaction; an installed package can be removed, or
  15.193 +an uninstalled package installed, but trying to reinstall a removed
  15.194 +package, or uninstall a newly-installed package is an error. This
  15.195 +means the packages break down into four categories:
  15.196 +
  15.197 +    - installed       (1 bit in the system bit array)
  15.198 +    - to-be-removed   (0 bit in the system bit array)
  15.199 +    - to-be-installed (1 bit in the upstream bit array)
  15.200 +    - installable     (0 bit in the upstream bit array)
  15.201 +
  15.202 +
  15.203 +Depsolver algorithm:
  15.204 +
  15.205 +    - Create new razor_transaction_packages ("rtp"s) for each
  15.206 +      requested install or remove. These will be "unresolved", because
  15.207 +      we haven't yet found the razor_packages that correspond to them.
  15.208 +
  15.209 +    - while there are new rtps:
  15.210 +
  15.211 +	- sort the new rtps
  15.212 +
  15.213 +	- Walk the system property list, upstream property list, and
  15.214 +          new rtp list in parallel, and:
  15.215 +
  15.216 +	    - For each uninstalled PROVIDES:
  15.217 +
  15.218 +		- If the property is a valid package name (that is,
  15.219 +                  either it's a package providing its own name, or it
  15.220 +                  has a matching OBSOLETES), and it matches the name
  15.221 +                  of a new rtp of type INSTALL or FORCED_UPDATE with
  15.222 +                  an unresolved new_package:
  15.223 +
  15.224 +		    - If the upstream package has the same version as
  15.225 +		      the system package, we have an UP_TO_DATE error
  15.226 +		      (FIXME: not quite right. This doesn't deal with
  15.227 +		      the case where we try to update an application
  15.228 +		      because of a library update, and it turns out
  15.229 +		      there's no new version of the application, but
  15.230 +		      there IS a compat package containing the old
  15.231 +		      version of the library.)
  15.232 +
  15.233 +		    - Otherwise, set the rtp's new_package to point to
  15.234 +		      the package providing this property and set the
  15.235 +		      appropriate bit in the upstream bit array.
  15.236 +
  15.237 +	    - For each to-be-installed non-file REQUIRES:
  15.238 +
  15.239 +		- See if there's an installed or to-be-installed
  15.240 +		  package that PROVIDES that property.
  15.241 +
  15.242 +		- If not, see if there's an installable package that
  15.243 +		  PROVIDES that property, and create a new INSTALL rtp
  15.244 +		  for it if so.
  15.245 +
  15.246 +		- If not, see if there's a to-be-removed package that
  15.247 +		  PROVIDES that property. (If we find such a package,
  15.248 +		  we have a CONTRADICTION error.)
  15.249 +
  15.250 +		- If none of the above, then we have an UNSATISFIABLE
  15.251 +                  error
  15.252 +
  15.253 +	    - For each to-be-installed file REQUIRES:
  15.254 +
  15.255 +		- (We create fake file PROVIDES to match file REQUIRES
  15.256 +                  when importing/merging razor sets, so if there is
  15.257 +                  already another installed package that REQUIRES this
  15.258 +                  file, there will be a PROVIDES listed for it as well.)
  15.259 +
  15.260 +		- See if there's an installed package that PROVIDES
  15.261 +                  that file.
  15.262 +
  15.263 +		- If not, do a binary search of the system file tree
  15.264 +                  looking to see if some installed package provides
  15.265 +                  that file but does not have a PROVIDES for it.
  15.266 +
  15.267 +		- If not, see if there's an installable package that
  15.268 +		  PROVIDES that property, and create a new INSTALL rtp
  15.269 +		  for it if so.
  15.270 +
  15.271 +		- (If we actually work with multiple upstream
  15.272 +                  razor_sets, then we will need to search the upstream
  15.273 +                  file trees at this point, because it's possible that
  15.274 +                  a package in one upstream repo would require a file
  15.275 +                  in another upstream repo. But if we merge the
  15.276 +                  multiple upstream repos into a single razor_set at
  15.277 +                  some point, then we would not need to do that,
  15.278 +                  because it would be guaranteed that we would have
  15.279 +                  already created a fake PROVIDES if any package
  15.280 +                  provides the file.)
  15.281 +
  15.282 +		- If no installed or installable package provides the
  15.283 +		  file, see if there's a to-be-removed package that
  15.284 +		  provides the file. (If we find such a package, we
  15.285 +		  have a CONTRADICTION error.)
  15.286 +
  15.287 +		- If none of the above, then we have an UNSATISFIABLE
  15.288 +                  error
  15.289 +
  15.290 +	    - For each to-be-installed PROVIDES:
  15.291 +
  15.292 +		- Check if the new PROVIDES conflicts with an
  15.293 +		  installed CONFLICTS. If so, create a new
  15.294 +		  FORCED_UPDATE rtp for the installed package, so we
  15.295 +		  can try to upgrade it to a non-conflicting version.
  15.296 +		  (If we can't, we'll have an OLD_CONFLICT error.)
  15.297 +
  15.298 +		- Check if the new PROVIDES conflicts with an
  15.299 +                  installed OBSOLETES *and* the PROVIDES property
  15.300 +                  corresponds to the name of its package. (That is,
  15.301 +                  OBSOLETES are only matched against package names,
  15.302 +                  not arbitrary provided properties.) If so, we have
  15.303 +                  an ALREADY_OBSOLETE error.
  15.304 +
  15.305 +		- Check if the new PROVIDES conflicts with a
  15.306 +		  to-be-installed CONFLICTS. If so, we have a
  15.307 +		  CONTRADICTION error.
  15.308 +
  15.309 +	    - For each to-be-installed CONFLICTS:
  15.310 +
  15.311 +		- Basically the reverse of the previous case: check if
  15.312 +		  the new CONFLICTS conflicts with an installed
  15.313 +		  PROVIDES. If so, create a new FORCED_UPDATE rtp for
  15.314 +		  the installed package, so we can try to upgrade it
  15.315 +		  to a non-conflicting version. (If we can't, we'll
  15.316 +		  have an NEW_CONFLICT error.)
  15.317 +
  15.318 +		- Check if the new CONFLICTS conflicts with a
  15.319 +		  to-be-installed PROVIDES. If so, we have a
  15.320 +		  CONTRADICTION error.
  15.321 +
  15.322 +	    - For each to-be-installed OBSOLETES:
  15.323 +
  15.324 +		- Check if there's an installed package that PROVIDES
  15.325 +		  that property. If so, create an OBSOLETED rtp for
  15.326 +		  the installed package.
  15.327 +
  15.328 +		- If not, check if there's a to-be-installed package
  15.329 +		  that PROVIDES that property. If so, we have a
  15.330 +		  CONTRADICTION error.
  15.331 +
  15.332 +
  15.333 +	    - For each installed PROVIDES:
  15.334 +
  15.335 +		- If the property is a valid package name (that is,
  15.336 +                  it's a package providing its own name), and it
  15.337 +                  matches the name of a new rtp with an unresolved
  15.338 +                  old_package, then set the rtp's old_package to point
  15.339 +                  to the package providing this property and clear the
  15.340 +                  appropriate bit in the system bit array.
  15.341 +
  15.342 +	    - For each to-be-removed PROVIDES:
  15.343 +
  15.344 +		- If there's also an identical to-be-installed
  15.345 +		  PROVIDES, we're ok and can skip this
  15.346 +
  15.347 +		- Otherwise, for each installed REQUIRES of this
  15.348 +                  property:
  15.349 +
  15.350 +		    - Look for some other installed or to-be-installed
  15.351 +		      property that satisfies the REQUIRES.
  15.352 +
  15.353 +		    - If there isn't one, then for each installed
  15.354 +		      package in this REQUIRES's package list:
  15.355 +
  15.356 +			- If the PROVIDES was lost because the old
  15.357 +			  package was REMOVEd (not FORCED_UPDATE or
  15.358 +			  OBSOLETED), then create a new REMOVE rtp for
  15.359 +			  this package.
  15.360 +
  15.361 +			- Otherwise, create a new FORCED_UPDATE rtp
  15.362 +                          for this package.
  15.363 +
  15.364 +		- (We don't need to look at to-be-installed REQUIRES
  15.365 +		  of this property, because if there are any, they
  15.366 +		  will cause a CONTRADICTION error when we try to
  15.367 +		  re-satisfy them the next time through.)
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/docs/Makefile.am	Fri Jun 20 19:04:47 2008 -0400
    16.3 @@ -0,0 +1,6 @@
    16.4 +
    16.5 +docsdir = $(datadir)/doc/razor
    16.6 +dist_docs_DATA = 		\
    16.7 +	DEPSOLVE.txt 		\
    16.8 +	REPO.txt
    16.9 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/docs/REPO.txt	Fri Jun 20 19:04:47 2008 -0400
    17.3 @@ -0,0 +1,172 @@
    17.4 +The repo file format / razor_set data structure
    17.5 +-----------------------------------------------
    17.6 +
    17.7 +The repo starts with a header, containing some number of sections,
    17.8 +terminated by a section with type 0:
    17.9 +
   17.10 +	struct razor_set_header {
   17.11 +		uint32_t magic;
   17.12 +		uint32_t version;
   17.13 +		struct razor_set_section sections[0];
   17.14 +	};
   17.15 +
   17.16 +	struct razor_set_section {
   17.17 +		uint32_t type;
   17.18 +		uint32_t offset;
   17.19 +		uint32_t size;
   17.20 +	};
   17.21 +
   17.22 +razor_set_open() mmaps the repo file, and creates a struct razor_set:
   17.23 +
   17.24 +	struct razor_set {
   17.25 +		struct array string_pool;
   17.26 +	 	struct array packages;
   17.27 +	 	struct array properties;
   17.28 +	 	struct array files;
   17.29 +		struct array package_pool;
   17.30 +	 	struct array property_pool;
   17.31 +	 	struct array file_pool;
   17.32 +		struct razor_set_header *header;
   17.33 +	};
   17.34 +
   17.35 +by finding the sections with those IDs and creating "struct array"s
   17.36 +pointing to the right places in the mmapped data. (This is the only
   17.37 +processing needed when reading in the file; everything else is used
   17.38 +exactly as-is.)
   17.39 +
   17.40 +
   17.41 +The sections
   17.42 +------------
   17.43 +
   17.44 +RAZOR_STRING_POOL
   17.45 +
   17.46 +	Stores one copy of each string that appears in the repo. (At
   17.47 +	the moment, this is: package names, package versions, property
   17.48 +	names, property versions, and (basenames of) filenames.) The
   17.49 +	strings are arbitrarily-sized, 0-terminated, and not in any
   17.50 +	particular order (although the empty string always ends up
   17.51 +	being at offset 0).
   17.52 +
   17.53 +RAZOR_PACKAGES
   17.54 +
   17.55 +	Array of struct razor_package; one for each package in the
   17.56 +	set, sorted by name.
   17.57 +
   17.58 +RAZOR_PROPERTIES
   17.59 +
   17.60 +	Array of struct razor_property; one for each unique property
   17.61 +	in the set, sorted by type, then name, then relation type (eg,
   17.62 +	"<" or ">="), then version. (Properties with no version have
   17.63 +	relation type RAZOR_VERSION_EQUAL, and version "".)
   17.64 +
   17.65 +RAZOR_FILES
   17.66 +
   17.67 +	Array of struct razor_entry; one for each file owned by any
   17.68 +	package in the set. The current sort order (which is subject
   17.69 +	to change) is breadth-first, sorted by basename. So eg: /, /bin,
   17.70 +	/dev, /etc, /bin/false, /bin/true, /dev/null, /etc/passwd.
   17.71 +
   17.72 +RAZOR_PACKAGE_POOL
   17.73 +
   17.74 +	Array of struct list, with each list item containing the index
   17.75 +	of a struct razor_package in the packages section. See the
   17.76 +	discussion of lists below.
   17.77 +
   17.78 +RAZOR_PROPERTY_POOL
   17.79 +
   17.80 +	Array of struct list, with each list item containing the index
   17.81 +	of a struct razor_property in the properties section. See the
   17.82 +	discussion of lists below.
   17.83 +
   17.84 +RAZOR_FILE_POOL
   17.85 +
   17.86 +	Array of struct list, with each list item containing the index
   17.87 +	of a struct razor_entry in the files section. See the
   17.88 +	discussion of lists below.
   17.89 +
   17.90 +
   17.91 +Data types
   17.92 +----------
   17.93 +Note that the exact layout of bits involves some historical accidents.
   17.94 +(Particularly the fact that the "name" field in most structs loses its
   17.95 +high bits to a flags field.)
   17.96 +
   17.97 +struct list_head
   17.98 +	uint list_ptr : 24;
   17.99 +	uint flags    : 8;
  17.100 +
  17.101 +struct list
  17.102 +	uint data  : 24;
  17.103 +	uint flags : 8;
  17.104 +
  17.105 +	Used to store lists of package, property, or file IDs. "struct
  17.106 +	list_head" stores the head of the list, which points to one or
  17.107 +	more "struct list"s in the appropriate "pool" section.
  17.108 +	("struct list" should probably be called "struct list_item".)
  17.109 +
  17.110 +	"list_first(&head, &pool)" returns a "struct list *" pointing
  17.111 +	to the first element of the list (or NULL for an empty list),
  17.112 +	and "list_next(list)" will return successive elements, until
  17.113 +	NULL is returned. Each "list->data" contains the index of a
  17.114 +	package, property, or file in the corresponding section of the
  17.115 +	set.
  17.116 +
  17.117 +	Peeking underneath the abstraction, a list_head's "flags" is
  17.118 +	0xff if the list is empty, 0x80 if it contains a single
  17.119 +	element, or 0x00 if it contains more than one element. In the
  17.120 +	single-element case, that element is actually stored in the
  17.121 +	list_head directly rather than being stored in a pool (and so
  17.122 +	list_first() just casts the list_head* to a list* and returns
  17.123 +	it). For multi-element lists, list_ptr is the index in the
  17.124 +	pool of the first element of this list; the list continues
  17.125 +	through successive elements of the pool until one with
  17.126 +	non-zero flags is reached, indicating the end of the list.
  17.127 +
  17.128 +struct razor_package
  17.129 +	uint name    : 24;
  17.130 +	uint flags   : 8;
  17.131 +	uint version : 32;
  17.132 +	struct list_head properties;
  17.133 +	struct list_head files;
  17.134 +
  17.135 +	name and version are indexes into string_pool. properties is a
  17.136 +	list of all of the package's properties, and files is a list
  17.137 +	of its files. flags is currently only used during razor_set
  17.138 +	merging, to keep track of which set a package came from.
  17.139 +
  17.140 +struct razor_property
  17.141 +	uint name     : 24;
  17.142 +	uint flags    : 6;
  17.143 +	uint type     : 2;
  17.144 +	uint relation : 32;
  17.145 +	uint version  : 32;
  17.146 +	struct list_head packages;
  17.147 +
  17.148 +	name and version are indexes into string_pool. type is an enum
  17.149 +	razor_property_type (eg, RAZOR_PROPERTY_REQUIRES), and
  17.150 +	relation is an enum razor_version_relation (eg,
  17.151 +	RAZOR_VERSION_GREATER_OR_EQUAL). packages is a list of the
  17.152 +	packages that have this property. flags is currently unused.
  17.153 +
  17.154 +struct razor_entry
  17.155 +	uint name  : 24;
  17.156 +	uint flags : 8;
  17.157 +	uint start : 32;
  17.158 +	struct list_head packages;
  17.159 +
  17.160 +	name is an index into string_pool, giving the basename of the
  17.161 +	file. start is either 0, or an index pointing to another
  17.162 +	razor_entry that is the first child of this entry (for a
  17.163 +	non-empty directory). (Entry 0 is always the root of the tree,
  17.164 +	so no entry could have entry 0 as a child.) flags is 0x80
  17.165 +	(RAZOR_ENTRY_LAST) if an entry is the last entry in its
  17.166 +	directory. Otherwise it is 0.
  17.167 +
  17.168 +	Note that given a pointer to a struct_razor_entry (eg, from a
  17.169 +	package's "files" list), there is no way to reconstruct its
  17.170 +	full name without walking the entire files array up to that
  17.171 +	point. Because of this and other problems (fix_file_map()), it
  17.172 +	seems like razor_entry should be modified to include a pointer
  17.173 +	to its parent. (Storing full paths instead of just basenames
  17.174 +	would also fix this problem, but that would use much more
  17.175 +	memory.)
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/librazor/.gitignore	Fri Jun 20 19:04:47 2008 -0400
    18.3 @@ -0,0 +1,5 @@
    18.4 +.deps
    18.5 +.libs
    18.6 +*.lo
    18.7 +*.la
    18.8 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/librazor/Makefile.am	Fri Jun 20 19:04:47 2008 -0400
    19.3 @@ -0,0 +1,37 @@
    19.4 +## Process this file with automake to produce Makefile.in
    19.5 +
    19.6 +INCLUDES = \
    19.7 +	-I$(top_builddir)/src -I$(top_srcdir)/src \
    19.8 +	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
    19.9 +	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
   19.10 +	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
   19.11 +	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
   19.12 +	-DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
   19.13 +	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
   19.14 +	-DPACKAGE_LIB_DIR=\""$(libdir)"\"
   19.15 +
   19.16 +lib_LTLIBRARIES = librazor.la
   19.17 +
   19.18 +librazorincludedir = $(includedir)/razor
   19.19 +
   19.20 +librazorinclude_HEADERS =              			\
   19.21 +	razor.h
   19.22 +
   19.23 +librazor_la_SOURCES =                                	\
   19.24 +	razor-internal.h				\
   19.25 +	razor.h						\
   19.26 +	razor.c						\
   19.27 +	root.c						\
   19.28 +	types.c						\
   19.29 +	util.c						\
   19.30 +	rpm.c						\
   19.31 +	iterator.c					\
   19.32 +	importer.c					\
   19.33 +	merger.c					\
   19.34 +	transaction.c
   19.35 +
   19.36 +librazor_la_LIBADD = $(ZLIB_LIBS)
   19.37 +
   19.38 +clean-local :
   19.39 +	rm -f *~
   19.40 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/librazor/importer.c	Fri Jun 20 19:04:47 2008 -0400
    20.3 @@ -0,0 +1,505 @@
    20.4 +/*
    20.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    20.6 + * Copyright (C) 2008  Red Hat, Inc
    20.7 + *
    20.8 + * This program is free software; you can redistribute it and/or modify
    20.9 + * it under the terms of the GNU General Public License as published by
   20.10 + * the Free Software Foundation; either version 2 of the License, or
   20.11 + * (at your option) any later version.
   20.12 + *
   20.13 + * This program is distributed in the hope that it will be useful,
   20.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.16 + * GNU General Public License for more details.
   20.17 + *
   20.18 + * You should have received a copy of the GNU General Public License along
   20.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   20.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   20.21 + */
   20.22 +
   20.23 +#define _GNU_SOURCE
   20.24 +
   20.25 +#include <string.h>
   20.26 +#include "razor-internal.h"
   20.27 +#include "razor.h"
   20.28 +
   20.29 +void
   20.30 +razor_importer_begin_package(struct razor_importer *importer,
   20.31 +			     const char *name,
   20.32 +			     const char *version,
   20.33 +			     const char *arch)
   20.34 +{
   20.35 +	struct razor_package *p;
   20.36 +
   20.37 +	p = array_add(&importer->set->packages, sizeof *p);
   20.38 +	p->name = hashtable_tokenize(&importer->table, name);
   20.39 +	p->flags = 0;
   20.40 +	p->version = hashtable_tokenize(&importer->table, version);
   20.41 +	p->arch = hashtable_tokenize(&importer->table, arch);
   20.42 +
   20.43 +	importer->package = p;
   20.44 +	array_init(&importer->properties);
   20.45 +}
   20.46 +
   20.47 +
   20.48 +void
   20.49 +razor_importer_finish_package(struct razor_importer *importer)
   20.50 +{
   20.51 +	list_set_array(&importer->package->properties,
   20.52 +		       &importer->set->property_pool,
   20.53 +		       &importer->properties,
   20.54 +		       1);
   20.55 +
   20.56 +	array_release(&importer->properties);
   20.57 +}
   20.58 +
   20.59 +void
   20.60 +razor_importer_add_details(struct razor_importer *importer,
   20.61 +			   const char *summary,
   20.62 +			   const char *description,
   20.63 +			   const char *url,
   20.64 +			   const char *license)
   20.65 +{
   20.66 +	importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
   20.67 +	importer->package->description = hashtable_tokenize(&importer->details_table, description);
   20.68 +	importer->package->url = hashtable_tokenize(&importer->details_table, url);
   20.69 +	importer->package->license = hashtable_tokenize(&importer->details_table, license);
   20.70 +}
   20.71 +
   20.72 +void
   20.73 +razor_importer_add_property(struct razor_importer *importer,
   20.74 +			    const char *name,
   20.75 +			    uint32_t flags,
   20.76 +			    const char *version)
   20.77 +{
   20.78 +	struct razor_property *p;
   20.79 +	uint32_t *r;
   20.80 +
   20.81 +	p = array_add(&importer->set->properties, sizeof *p);
   20.82 +	p->name = hashtable_tokenize(&importer->table, name);
   20.83 +	p->flags = flags;
   20.84 +	p->version = hashtable_tokenize(&importer->table, version);
   20.85 +	list_set_ptr(&p->packages, importer->package -
   20.86 +		     (struct razor_package *) importer->set->packages.data);
   20.87 +
   20.88 +	r = array_add(&importer->properties, sizeof *r);
   20.89 +	*r = p - (struct razor_property *) importer->set->properties.data;
   20.90 +
   20.91 +	if (((flags & RAZOR_PROPERTY_TYPE_MASK) == RAZOR_PROPERTY_REQUIRES) &&
   20.92 +	    *name == '/') {
   20.93 +		r = array_add(&importer->file_requires, sizeof *r);
   20.94 +		*r = p->name;
   20.95 +	}
   20.96 +}
   20.97 +
   20.98 +void
   20.99 +razor_importer_add_file(struct razor_importer *importer, const char *name)
  20.100 +{
  20.101 +	struct import_entry *e;
  20.102 +
  20.103 +	e = array_add(&importer->files, sizeof *e);
  20.104 +
  20.105 +	e->package = importer->package -
  20.106 +		(struct razor_package *) importer->set->packages.data;
  20.107 +	e->name = strdup(name);
  20.108 +}
  20.109 +
  20.110 +struct razor_importer *
  20.111 +razor_importer_new(void)
  20.112 +{
  20.113 +	struct razor_importer *importer;
  20.114 +
  20.115 +	importer = zalloc(sizeof *importer);
  20.116 +	importer->set = razor_set_create();
  20.117 +	hashtable_init(&importer->table, &importer->set->string_pool);
  20.118 +	hashtable_init(&importer->details_table,
  20.119 +		       &importer->set->details_string_pool);
  20.120 +	hashtable_init(&importer->file_table,
  20.121 +		       &importer->set->file_string_pool);
  20.122 +
  20.123 +	return importer;
  20.124 +}
  20.125 +
  20.126 +/* Destroy an importer without creating the set. */
  20.127 +void
  20.128 +razor_importer_destroy(struct razor_importer *importer)
  20.129 +{
  20.130 +	/* FIXME: write this */
  20.131 +}
  20.132 +
  20.133 +static int
  20.134 +compare_packages(const void *p1, const void *p2, void *data)
  20.135 +{
  20.136 +	const struct razor_package *pkg1 = p1, *pkg2 = p2;
  20.137 +	struct razor_set *set = data;
  20.138 +	char *pool = set->string_pool.data;
  20.139 +
  20.140 +	/* FIXME: what if the flags are different? */
  20.141 +	if (pkg1->name == pkg2->name)
  20.142 +		return razor_versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
  20.143 +	else
  20.144 +		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
  20.145 +}
  20.146 +
  20.147 +static int
  20.148 +compare_properties(const void *p1, const void *p2, void *data)
  20.149 +{
  20.150 +	const struct razor_property *prop1 = p1, *prop2 = p2;
  20.151 +	struct razor_set *set = data;
  20.152 +	char *pool = set->string_pool.data;
  20.153 +
  20.154 +	if (prop1->name != prop2->name)
  20.155 +		return strcmp(&pool[prop1->name], &pool[prop2->name]);
  20.156 +	else if (prop1->flags != prop2->flags)
  20.157 +		return prop1->flags - prop2->flags;
  20.158 +	else
  20.159 +		return razor_versioncmp(&pool[prop1->version], &pool[prop2->version]);
  20.160 +}
  20.161 +
  20.162 +static uint32_t *
  20.163 +uniqueify_properties(struct razor_set *set)
  20.164 +{
  20.165 +	struct razor_property *rp, *up, *rp_end;
  20.166 +	struct array *pkgs, *p;
  20.167 +	struct list_head *r;
  20.168 +	uint32_t *map, *rmap;
  20.169 +	int i, count, unique;
  20.170 +
  20.171 +	count = set->properties.size / sizeof(struct razor_property);
  20.172 +	map = razor_qsort_with_data(set->properties.data,
  20.173 +				    count,
  20.174 +				    sizeof(struct razor_property),
  20.175 +				    compare_properties,
  20.176 +				    set);
  20.177 +
  20.178 +	rp_end = set->properties.data + set->properties.size;
  20.179 +	rmap = malloc(count * sizeof *map);
  20.180 +	pkgs = zalloc(count * sizeof *pkgs);
  20.181 +	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
  20.182 +		if (rp->name != up->name ||
  20.183 +		    rp->flags != up->flags ||
  20.184 +		    rp->version != up->version) {
  20.185 +			up++;
  20.186 +			up->name = rp->name;
  20.187 +			up->flags = rp->flags;
  20.188 +			up->version = rp->version;
  20.189 +		}
  20.190 +
  20.191 +		unique = up - (struct razor_property *) set->properties.data;
  20.192 +		rmap[map[i]] = unique;
  20.193 +		r = array_add(&pkgs[unique], sizeof *r);
  20.194 +		*r = rp->packages;
  20.195 +	}
  20.196 +	free(map);
  20.197 +
  20.198 +	if (up != rp)
  20.199 +		up++;
  20.200 +	set->properties.size = (void *) up - set->properties.data;
  20.201 +	rp_end = up;
  20.202 +	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
  20.203 +		list_set_array(&rp->packages, &set->package_pool, p, 0);
  20.204 +		array_release(p);
  20.205 +	}
  20.206 +
  20.207 +	free(pkgs);
  20.208 +
  20.209 +	return rmap;
  20.210 +}
  20.211 +
  20.212 +static int
  20.213 +compare_filenames(const void *p1, const void *p2, void *data)
  20.214 +{
  20.215 +	const struct import_entry *e1 = p1;
  20.216 +	const struct import_entry *e2 = p2;
  20.217 +	const char *n1 = e1->name;
  20.218 +	const char *n2 = e2->name;
  20.219 +
  20.220 +	/* Need to make sure that the contents of a directory
  20.221 +	 * are sorted immediately after it. So "foo/bar" has to
  20.222 +	 * sort before "foo.conf"
  20.223 +	 *
  20.224 +	 * FIXME: this is about 60% slower than strcmp
  20.225 +	 */
  20.226 +	while (*n1 && *n2) {
  20.227 +		if (*n1 < *n2)
  20.228 +			return *n2 == '/' ? 1 : -1;
  20.229 +		else if (*n1 > *n2)
  20.230 +			return *n1 == '/' ? -1 : 1;
  20.231 +		n1++;
  20.232 +		n2++;
  20.233 +	}
  20.234 +	if (*n1)
  20.235 +		return 1;
  20.236 +	else if (*n2)
  20.237 +		return -1;
  20.238 +	else
  20.239 +		return 0;
  20.240 +}
  20.241 +
  20.242 +static void
  20.243 +count_entries(struct import_directory *d)
  20.244 +{
  20.245 +	struct import_directory *p, *end;
  20.246 +
  20.247 +	p = d->files.data;
  20.248 +	end = d->files.data + d->files.size;
  20.249 +	d->count = 0;
  20.250 +	while (p < end) {
  20.251 +		count_entries(p);
  20.252 +		d->count += p->count + 1;
  20.253 +		p++;
  20.254 +	}
  20.255 +}
  20.256 +
  20.257 +static void
  20.258 +serialize_files(struct razor_set *set,
  20.259 +		struct import_directory *d, struct array *array)
  20.260 +{
  20.261 +	struct import_directory *p, *end;
  20.262 +	struct razor_entry *e = NULL;
  20.263 +	uint32_t s;
  20.264 +
  20.265 +	p = d->files.data;
  20.266 +	end = d->files.data + d->files.size;
  20.267 +	s = array->size / sizeof *e + d->files.size / sizeof *p;
  20.268 +	while (p < end) {
  20.269 +		e = array_add(array, sizeof *e);
  20.270 +		e->name = p->name;
  20.271 +		e->flags = 0;
  20.272 +		e->start = p->count > 0 ? s : 0;
  20.273 +		s += p->count;
  20.274 +
  20.275 +		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
  20.276 +		array_release(&p->packages);
  20.277 +		p++;
  20.278 +	}
  20.279 +	if (e != NULL)
  20.280 +		e->flags |= RAZOR_ENTRY_LAST;
  20.281 +
  20.282 +	p = d->files.data;
  20.283 +	end = d->files.data + d->files.size;
  20.284 +	while (p < end) {
  20.285 +		serialize_files(set, p, array);
  20.286 +		p++;
  20.287 +	}
  20.288 +}
  20.289 +
  20.290 +static void
  20.291 +remap_property_package_links(struct array *properties, uint32_t *rmap)
  20.292 +{
  20.293 +	struct razor_property *p, *end;
  20.294 +
  20.295 +	end = properties->data + properties->size;
  20.296 +	for (p = properties->data; p < end; p++)
  20.297 +		list_remap_head(&p->packages, rmap);
  20.298 +}
  20.299 +
  20.300 +static void
  20.301 +build_file_tree(struct razor_importer *importer)
  20.302 +{
  20.303 +	int count, i, length;
  20.304 +	struct import_entry *filenames;
  20.305 +	char *f, *end;
  20.306 +	uint32_t name, *r;
  20.307 +	char dirname[256];
  20.308 +	struct import_directory *d, root;
  20.309 +	struct razor_entry *e;
  20.310 +
  20.311 +	count = importer->files.size / sizeof (struct import_entry);
  20.312 +	razor_qsort_with_data(importer->files.data,
  20.313 +			      count,
  20.314 +			      sizeof (struct import_entry),
  20.315 +			      compare_filenames,
  20.316 +			      NULL);
  20.317 +
  20.318 +	root.name = hashtable_tokenize(&importer->table, "");
  20.319 +	array_init(&root.files);
  20.320 +	array_init(&root.packages);
  20.321 +	root.last = NULL;
  20.322 +
  20.323 +	filenames = importer->files.data;
  20.324 +	for (i = 0; i < count; i++) {
  20.325 +		f = filenames[i].name;
  20.326 +		if (*f != '/')
  20.327 +			continue;
  20.328 +		f++;
  20.329 +
  20.330 +		d = &root;
  20.331 +		while (*f) {
  20.332 +			end = strchr(f, '/');
  20.333 +			if (end == NULL)
  20.334 +				end = f + strlen(f);
  20.335 +			length = end - f;
  20.336 +			memcpy(dirname, f, length);
  20.337 +			dirname[length] ='\0';
  20.338 +			name = hashtable_tokenize(&importer->table, dirname);
  20.339 +			if (d->last == NULL || d->last->name != name) {
  20.340 +				d->last = array_add(&d->files, sizeof *d);
  20.341 +				d->last->name = name;
  20.342 +				d->last->last = NULL;
  20.343 +				array_init(&d->last->files);
  20.344 +				array_init(&d->last->packages);
  20.345 +			}
  20.346 +			d = d->last;
  20.347 +			f = end + 1;
  20.348 +			if (*end == '\0')
  20.349 +				break;
  20.350 +		}
  20.351 +
  20.352 +		r = array_add(&d->packages, sizeof *r);
  20.353 +		*r = filenames[i].package;
  20.354 +		free(filenames[i].name);
  20.355 +	}
  20.356 +
  20.357 +	count_entries(&root);
  20.358 +	e = importer->set->files.data;
  20.359 +	e->name = root.name;
  20.360 +	e->flags = RAZOR_ENTRY_LAST;
  20.361 +	e->start = importer->files.size ? 1 : 0;
  20.362 +	list_set_empty(&e->packages);
  20.363 +
  20.364 +	serialize_files(importer->set, &root, &importer->set->files);
  20.365 +
  20.366 +	array_release(&importer->files);
  20.367 +}
  20.368 +
  20.369 +static void
  20.370 +list_to_array(struct list *list, struct array *array)
  20.371 +{
  20.372 +	uint32_t *item;
  20.373 +
  20.374 +	while (list) {
  20.375 +		 item = array_add(array, sizeof *item);
  20.376 +		 *item = list->data;
  20.377 +		 list = list_next(list);
  20.378 +	}
  20.379 +}
  20.380 +
  20.381 +static int
  20.382 +compare_file_requires(const void *p1, const void *p2, void *data)
  20.383 +{
  20.384 +	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
  20.385 +	const char *pool = data;
  20.386 +
  20.387 +	return strcmp(&pool[*f1], &pool[*f2]);
  20.388 +}
  20.389 +
  20.390 +static void
  20.391 +find_file_provides(struct razor_importer *importer)
  20.392 +{
  20.393 +	struct razor_property *prop;
  20.394 +	struct razor_entry *top, *entry;
  20.395 +	struct razor_package *packages;
  20.396 +	struct array pkgprops;
  20.397 +	struct list *pkg;
  20.398 +	uint32_t *req, *req_start, *req_end;
  20.399 +	uint32_t *map, *newprop;
  20.400 +	char *pool;
  20.401 +
  20.402 +	pool = importer->set->string_pool.data;
  20.403 +	packages = importer->set->packages.data;
  20.404 +	top = importer->set->files.data;
  20.405 +
  20.406 +	req = req_start = importer->file_requires.data;
  20.407 +	req_end = importer->file_requires.data + importer->file_requires.size;
  20.408 +	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
  20.409 +				    compare_file_requires, pool);
  20.410 +	free(map);
  20.411 +
  20.412 +	for (req = req_start; req < req_end; req++) {
  20.413 +		if (req > req_start && req[0] == req[-1])
  20.414 +			continue;
  20.415 +		entry = razor_set_find_entry(importer->set, top, &pool[*req]);
  20.416 +		if (!entry)
  20.417 +			continue;
  20.418 +
  20.419 +		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
  20.420 +			prop = array_add(&importer->set->properties, sizeof *prop);
  20.421 +			prop->name = *req;
  20.422 +			prop->flags =
  20.423 +				RAZOR_PROPERTY_PROVIDES | RAZOR_PROPERTY_EQUAL;
  20.424 +			prop->version = hashtable_tokenize(&importer->table, "");
  20.425 +			list_set_ptr(&prop->packages, pkg->data);
  20.426 +
  20.427 +			/* Update property list of pkg */
  20.428 +			array_init(&pkgprops);
  20.429 +			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
  20.430 +			newprop = array_add(&pkgprops, sizeof *newprop);
  20.431 +			*newprop = prop - (struct razor_property *)importer->set->properties.data;
  20.432 +			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
  20.433 +			array_release(&pkgprops);
  20.434 +		}
  20.435 +	}
  20.436 +
  20.437 +	array_release(&importer->file_requires);
  20.438 +}
  20.439 +
  20.440 +static void
  20.441 +build_package_file_lists(struct razor_set *set, uint32_t *rmap)
  20.442 +{
  20.443 +	struct razor_package *p, *packages;
  20.444 +	struct array *pkgs;
  20.445 +	struct razor_entry *e, *end;
  20.446 +	struct list *r;
  20.447 +	uint32_t *q;
  20.448 +	int i, count;
  20.449 +
  20.450 +	count = set->packages.size / sizeof *p;
  20.451 +	pkgs = zalloc(count * sizeof *pkgs);
  20.452 +
  20.453 +	end = set->files.data + set->files.size;
  20.454 +	for (e = set->files.data; e < end; e++) {
  20.455 +		list_remap_head(&e->packages, rmap);
  20.456 +		r = list_first(&e->packages, &set->package_pool);
  20.457 +		while (r) {
  20.458 +			q = array_add(&pkgs[r->data], sizeof *q);
  20.459 +			*q = e - (struct razor_entry *) set->files.data;
  20.460 +			r = list_next(r);
  20.461 +		}
  20.462 +	}
  20.463 +
  20.464 +	packages = set->packages.data;
  20.465 +	for (i = 0; i < count; i++) {
  20.466 +		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
  20.467 +		array_release(&pkgs[i]);
  20.468 +	}
  20.469 +	free(pkgs);
  20.470 +}
  20.471 +
  20.472 +struct razor_set *
  20.473 +razor_importer_finish(struct razor_importer *importer)
  20.474 +{
  20.475 +	struct razor_set *set;
  20.476 +	uint32_t *map, *rmap;
  20.477 +	int i, count;
  20.478 +
  20.479 +	build_file_tree(importer);
  20.480 +	find_file_provides(importer);
  20.481 +
  20.482 +	map = uniqueify_properties(importer->set);
  20.483 +	list_remap_pool(&importer->set->property_pool, map);
  20.484 +	free(map);
  20.485 +
  20.486 +	count = importer->set->packages.size / sizeof(struct razor_package);
  20.487 +	map = razor_qsort_with_data(importer->set->packages.data,
  20.488 +				    count,
  20.489 +				    sizeof(struct razor_package),
  20.490 +				    compare_packages,
  20.491 +				    importer->set);
  20.492 +
  20.493 +	rmap = malloc(count * sizeof *rmap);
  20.494 +	for (i = 0; i < count; i++)
  20.495 +		rmap[map[i]] = i;
  20.496 +	free(map);
  20.497 +
  20.498 +	list_remap_pool(&importer->set->package_pool, rmap);
  20.499 +	build_package_file_lists(importer->set, rmap);
  20.500 +	remap_property_package_links(&importer->set->properties, rmap);
  20.501 +	free(rmap);
  20.502 +
  20.503 +	set = importer->set;
  20.504 +	hashtable_release(&importer->table);
  20.505 +	free(importer);
  20.506 +
  20.507 +	return set;
  20.508 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/librazor/iterator.c	Fri Jun 20 19:04:47 2008 -0400
    21.3 @@ -0,0 +1,265 @@
    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 <string.h>
   21.26 +#include "razor-internal.h"
   21.27 +#include "razor.h"
   21.28 +
   21.29 +static struct razor_package_iterator *
   21.30 +razor_package_iterator_create_with_index(struct razor_set *set,
   21.31 +					 struct list *index)
   21.32 +{
   21.33 +	struct razor_package_iterator *pi;
   21.34 +
   21.35 +	pi = zalloc(sizeof *pi);
   21.36 +	pi->set = set;
   21.37 +	pi->index = index;
   21.38 +
   21.39 +	return pi;
   21.40 +}
   21.41 +
   21.42 +struct razor_package_iterator *
   21.43 +razor_package_iterator_create(struct razor_set *set)
   21.44 +{
   21.45 +	struct razor_package_iterator *pi;
   21.46 +
   21.47 +	pi = zalloc(sizeof *pi);
   21.48 +	pi->set = set;
   21.49 +	pi->end = set->packages.data + set->packages.size;
   21.50 +	pi->package = set->packages.data;
   21.51 +
   21.52 +	return pi;
   21.53 +}
   21.54 +
   21.55 +void
   21.56 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
   21.57 +					 struct razor_set *set,
   21.58 +					 struct razor_property *property)
   21.59 +{
   21.60 +	memset(pi, 0, sizeof *pi);
   21.61 +	pi->set = set;
   21.62 +	pi->index = list_first(&property->packages, &set->package_pool);
   21.63 +}
   21.64 +
   21.65 +struct razor_package_iterator *
   21.66 +razor_package_iterator_create_for_property(struct razor_set *set,
   21.67 +					   struct razor_property *property)
   21.68 +{
   21.69 +	struct list *index;
   21.70 +
   21.71 +	index = list_first(&property->packages, &set->package_pool);
   21.72 +	return razor_package_iterator_create_with_index(set, index);
   21.73 +}
   21.74 +
   21.75 +struct razor_package_iterator *
   21.76 +razor_package_iterator_create_for_file(struct razor_set *set,
   21.77 +				       const char *filename)
   21.78 +{
   21.79 +	struct razor_entry *entry;
   21.80 +	struct list *index;
   21.81 +
   21.82 +	entry = razor_set_find_entry(set, set->files.data, filename);
   21.83 +	if (entry == NULL)
   21.84 +		return NULL;
   21.85 +
   21.86 +	index = list_first(&entry->packages, &set->package_pool);
   21.87 +	return razor_package_iterator_create_with_index(set, index);
   21.88 +}
   21.89 +
   21.90 +int
   21.91 +razor_package_iterator_next(struct razor_package_iterator *pi,
   21.92 +			    struct razor_package **package,
   21.93 +			    const char **name,
   21.94 +			    const char **version,
   21.95 +			    const char **arch)
   21.96 +{
   21.97 +	char *pool;
   21.98 +	int valid;
   21.99 +	struct razor_package *p, *packages;
  21.100 +
  21.101 +	if (pi->package) {
  21.102 +		p = pi->package++;
  21.103 +		valid = p < pi->end;
  21.104 +	} else if (pi->index) {
  21.105 +		packages = pi->set->packages.data;
  21.106 +		p = &packages[pi->index->data];
  21.107 +		pi->index = list_next(pi->index);
  21.108 +		valid = 1;
  21.109 +	} else
  21.110 +		valid = 0;
  21.111 +
  21.112 +	if (valid) {
  21.113 +		pool = pi->set->string_pool.data;
  21.114 +		*package = p;
  21.115 +		*name = &pool[p->name];
  21.116 +		*version = &pool[p->version];
  21.117 +		*arch = &pool[p->arch];
  21.118 +	} else {
  21.119 +		*package = NULL;
  21.120 +	}
  21.121 +
  21.122 +	return valid;
  21.123 +}
  21.124 +
  21.125 +void
  21.126 +razor_package_iterator_destroy(struct razor_package_iterator *pi)
  21.127 +{
  21.128 +	if (pi->free_index)
  21.129 +		free(pi->index);
  21.130 +
  21.131 +	free(pi);
  21.132 +}
  21.133 +
  21.134 +struct razor_property_iterator *
  21.135 +razor_property_iterator_create(struct razor_set *set,
  21.136 +			       struct razor_package *package)
  21.137 +{
  21.138 +	struct razor_property_iterator *pi;
  21.139 +
  21.140 +	pi = zalloc(sizeof *pi);
  21.141 +	pi->set = set;
  21.142 +
  21.143 +	if (package) {
  21.144 +		pi->index = list_first(&package->properties,
  21.145 +				       &set->property_pool);
  21.146 +	} else {
  21.147 +		pi->property = set->properties.data;
  21.148 +		pi->end = set->properties.data + set->properties.size;
  21.149 +	}
  21.150 +
  21.151 +	return pi;
  21.152 +}
  21.153 +
  21.154 +int
  21.155 +razor_property_iterator_next(struct razor_property_iterator *pi,
  21.156 +			     struct razor_property **property,
  21.157 +			     const char **name,
  21.158 +			     uint32_t *flags,
  21.159 +			     const char **version)
  21.160 +{
  21.161 +	char *pool;
  21.162 +	int valid;
  21.163 +	struct razor_property *p, *properties;
  21.164 +
  21.165 +	if (pi->property) {
  21.166 +		p = pi->property++;
  21.167 +		valid = p < pi->end;
  21.168 +	} else if (pi->index) {
  21.169 +		properties = pi->set->properties.data;
  21.170 +		p = &properties[pi->index->data];
  21.171 +		pi->index = list_next(pi->index);
  21.172 +		valid = 1;
  21.173 +	} else
  21.174 +		valid = 0;
  21.175 +
  21.176 +	if (valid) {
  21.177 +		pool = pi->set->string_pool.data;
  21.178 +		*property = p;
  21.179 +		*name = &pool[p->name];
  21.180 +		*flags = p->flags;
  21.181 +		*version = &pool[p->version];
  21.182 +	} else {
  21.183 +		*property = NULL;
  21.184 +	}
  21.185 +
  21.186 +	return valid;
  21.187 +}
  21.188 +
  21.189 +void
  21.190 +razor_property_iterator_destroy(struct razor_property_iterator *pi)
  21.191 +{
  21.192 +	free(pi);
  21.193 +}
  21.194 +
  21.195 +struct razor_package_query {
  21.196 +	struct razor_set *set;
  21.197 +	char *vector;
  21.198 +	int count;
  21.199 +};
  21.200 +
  21.201 +struct razor_package_query *
  21.202 +razor_package_query_create(struct razor_set *set)
  21.203 +{
  21.204 +	struct razor_package_query *pq;
  21.205 +	int count;
  21.206 +
  21.207 +	pq = zalloc(sizeof *pq);
  21.208 +	pq->set = set;
  21.209 +	count = set->packages.size / sizeof(struct razor_package);
  21.210 +	pq->vector = zalloc(count * sizeof(char));
  21.211 +
  21.212 +	return pq;
  21.213 +}
  21.214 +
  21.215 +void
  21.216 +razor_package_query_add_package(struct razor_package_query *pq,
  21.217 +				struct razor_package *p)
  21.218 +{
  21.219 +	struct razor_package *packages;
  21.220 +
  21.221 +	packages = pq->set->packages.data;
  21.222 +	pq->count += pq->vector[p - packages] ^ 1;
  21.223 +	pq->vector[p - packages] = 1;
  21.224 +}
  21.225 +
  21.226 +void
  21.227 +razor_package_query_add_iterator(struct razor_package_query *pq,
  21.228 +				 struct razor_package_iterator *pi)
  21.229 +{
  21.230 +	struct razor_package *packages, *p;
  21.231 +	const char *name, *version, *arch;
  21.232 +
  21.233 +	packages = pq->set->packages.data;
  21.234 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  21.235 +		pq->count += pq->vector[p - packages] ^ 1;
  21.236 +		pq->vector[p - packages] = 1;
  21.237 +	}
  21.238 +}
  21.239 +
  21.240 +struct razor_package_iterator *
  21.241 +razor_package_query_finish(struct razor_package_query *pq)
  21.242 +{
  21.243 +	struct razor_package_iterator *pi;
  21.244 +	struct razor_set *set;
  21.245 +	struct list *index;
  21.246 +	int i, j, count;
  21.247 +
  21.248 +	set = pq->set;
  21.249 +	count = set->packages.size / sizeof(struct razor_package);
  21.250 +	index = zalloc(pq->count * sizeof *index);
  21.251 +
  21.252 +	for (i = 0, j = 0; i < count; i++) {
  21.253 +		if (!pq->vector[i])
  21.254 +			continue;
  21.255 +
  21.256 +		index[j].data = i;
  21.257 +		if (j == pq->count - 1)
  21.258 +			index[j].flags = 0x80;
  21.259 +		j++;
  21.260 +	}
  21.261 +
  21.262 +	free(pq);
  21.263 +
  21.264 +	pi = razor_package_iterator_create_with_index(set, index);
  21.265 +	pi->free_index = 1;
  21.266 +
  21.267 +	return pi;
  21.268 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/librazor/merger.c	Fri Jun 20 19:04:47 2008 -0400
    22.3 @@ -0,0 +1,525 @@
    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 +#include <string.h>
   22.24 +#include "razor-internal.h"
   22.25 +#include "razor.h"
   22.26 +
   22.27 +#define UPSTREAM_SOURCE 0x80
   22.28 +
   22.29 +struct source {
   22.30 +	struct razor_set *set;
   22.31 +	uint32_t *property_map;
   22.32 +	uint32_t *file_map;
   22.33 +};
   22.34 +
   22.35 +struct razor_merger {
   22.36 +	struct razor_set *set;
   22.37 +	struct hashtable table;
   22.38 +	struct source source1;
   22.39 +	struct source source2;
   22.40 +};
   22.41 +
   22.42 +struct razor_merger *
   22.43 +razor_merger_create(struct razor_set *set1, struct razor_set *set2)
   22.44 +{
   22.45 +	struct razor_merger *merger;
   22.46 +	int count;
   22.47 +	size_t size;
   22.48 +
   22.49 +	merger = zalloc(sizeof *merger);
   22.50 +	merger->set = razor_set_create();
   22.51 +	hashtable_init(&merger->table, &merger->set->string_pool);
   22.52 +
   22.53 +	merger->source1.set = set1;
   22.54 +	count = set1->properties.size / sizeof (struct razor_property);
   22.55 +	size = count * sizeof merger->source1.property_map[0];
   22.56 +	merger->source1.property_map = zalloc(size);
   22.57 +	count = set1->files.size / sizeof (struct razor_entry);
   22.58 +	size = count * sizeof merger->source1.file_map[0];
   22.59 +	merger->source1.file_map = zalloc(size);
   22.60 +
   22.61 +	merger->source2.set = set2;
   22.62 +	count = set2->properties.size / sizeof (struct razor_property);
   22.63 +	size = count * sizeof merger->source2.property_map[0];
   22.64 +	merger->source2.property_map = zalloc(size);
   22.65 +	count = set2->files.size / sizeof (struct razor_entry);
   22.66 +	size = count * sizeof merger->source2.file_map[0];
   22.67 +	merger->source2.file_map = zalloc(size);
   22.68 +
   22.69 +	return merger;
   22.70 +}
   22.71 +
   22.72 +void
   22.73 +razor_merger_add_package(struct razor_merger *merger,
   22.74 +			 struct razor_package *package)
   22.75 +{
   22.76 +	char *pool;
   22.77 +	struct list *r;
   22.78 +	struct razor_package *p;
   22.79 +	struct razor_set *set1;
   22.80 +	struct source *source;
   22.81 +	uint32_t flags;
   22.82 +
   22.83 +	set1 = merger->source1.set;
   22.84 +	if (set1->packages.data <= (void *) package &&
   22.85 +	    (void *) package < set1->packages.data + set1->packages.size) {
   22.86 +		source = &merger->source1;
   22.87 +		flags = 0;
   22.88 +	} else {
   22.89 +		source = &merger->source2;
   22.90 +		flags = UPSTREAM_SOURCE;
   22.91 +	}
   22.92 +
   22.93 +	pool = source->set->string_pool.data;
   22.94 +	p = array_add(&merger->set->packages, sizeof *p);
   22.95 +	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
   22.96 +	p->flags = flags;
   22.97 +	p->version = hashtable_tokenize(&merger->table,
   22.98 +					&pool[package->version]);
   22.99 +	p->arch = hashtable_tokenize(&merger->table,
  22.100 +				     &pool[package->arch]);
  22.101 +
  22.102 +	p->properties = package->properties;
  22.103 +	r = list_first(&package->properties, &source->set->property_pool);
  22.104 +	while (r) {
  22.105 +		source->property_map[r->data] = 1;
  22.106 +		r = list_next(r);
  22.107 +	}
  22.108 +
  22.109 +	p->files = package->files;
  22.110 +	r = list_first(&package->files, &source->set->file_pool);
  22.111 +	while (r) {
  22.112 +		source->file_map[r->data] = 1;
  22.113 +		r = list_next(r);
  22.114 +	}
  22.115 +}
  22.116 +
  22.117 +static uint32_t
  22.118 +add_property(struct razor_merger *merger,
  22.119 +	     const char *name, uint32_t flags, const char *version)
  22.120 +{
  22.121 +	struct razor_property *p;
  22.122 +
  22.123 +	p = array_add(&merger->set->properties, sizeof *p);
  22.124 +	p->name = hashtable_tokenize(&merger->table, name);
  22.125 +	p->flags = flags;
  22.126 +	p->version = hashtable_tokenize(&merger->table, version);
  22.127 +
  22.128 +	return p - (struct razor_property *) merger->set->properties.data;
  22.129 +}
  22.130 +
  22.131 +static void
  22.132 +merge_properties(struct razor_merger *merger)
  22.133 +{
  22.134 +	struct razor_property *p1, *p2;
  22.135 +	struct razor_set *set1, *set2;
  22.136 +	uint32_t *map1, *map2;
  22.137 +	int i, j, cmp, count1, count2;
  22.138 +	char *pool1, *pool2;
  22.139 +
  22.140 +	set1 = merger->source1.set;
  22.141 +	set2 = merger->source2.set;
  22.142 +	map1 = merger->source1.property_map;
  22.143 +	map2 = merger->source2.property_map;
  22.144 +
  22.145 +	i = 0;
  22.146 +	j = 0;
  22.147 +	pool1 = set1->string_pool.data;
  22.148 +	pool2 = set2->string_pool.data;
  22.149 +
  22.150 +	count1 = set1->properties.size / sizeof *p1;
  22.151 +	count2 = set2->properties.size / sizeof *p2;
  22.152 +	while (i < count1 || j < count2) {
  22.153 +		if (i < count1 && map1[i] == 0) {
  22.154 +			i++;
  22.155 +			continue;
  22.156 +		}
  22.157 +		if (j < count2 && map2[j] == 0) {
  22.158 +			j++;
  22.159 +			continue;
  22.160 +		}
  22.161 +		p1 = (struct razor_property *) set1->properties.data + i;
  22.162 +		p2 = (struct razor_property *) set2->properties.data + j;
  22.163 +		if (i < count1 && j < count2)
  22.164 +			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
  22.165 +		else if (i < count1)
  22.166 +			cmp = -1;
  22.167 +		else
  22.168 +			cmp = 1;
  22.169 +		if (cmp == 0)
  22.170 +			cmp = p1->flags - p2->flags;
  22.171 +		if (cmp == 0)
  22.172 +			cmp = razor_versioncmp(&pool1[p1->version],
  22.173 +					       &pool2[p2->version]);
  22.174 +		if (cmp < 0) {
  22.175 +			map1[i++] = add_property(merger,
  22.176 +						 &pool1[p1->name],
  22.177 +						 p1->flags,
  22.178 +						 &pool1[p1->version]);
  22.179 +		} else if (cmp > 0) {
  22.180 +			map2[j++] = add_property(merger,
  22.181 +						 &pool2[p2->name],
  22.182 +						 p2->flags,
  22.183 +						 &pool2[p2->version]);
  22.184 +		} else  {
  22.185 +			map1[i++] = map2[j++] =
  22.186 +				add_property(merger,
  22.187 +					     &pool1[p1->name],
  22.188 +					     p1->flags,
  22.189 +					     &pool1[p1->version]);
  22.190 +		}
  22.191 +	}
  22.192 +}
  22.193 +
  22.194 +static void
  22.195 +emit_properties(struct list_head *properties, struct array *source_pool,
  22.196 +		uint32_t *map, struct array *pool)
  22.197 +{
  22.198 +	uint32_t r;
  22.199 +	struct list *p, *q;
  22.200 +
  22.201 +	r = pool->size / sizeof *q;
  22.202 +	p = list_first(properties, source_pool);
  22.203 +	while (p) {
  22.204 +		q = array_add(pool, sizeof *q);
  22.205 +		q->data = map[p->data];
  22.206 +		q->flags = p->flags;
  22.207 +		p = list_next(p);
  22.208 +	}
  22.209 +
  22.210 +	list_set_ptr(properties, r);
  22.211 +}
  22.212 +
  22.213 +static uint32_t
  22.214 +add_file(struct razor_merger *merger, const char *name)
  22.215 +{
  22.216 +	struct razor_entry *e;
  22.217 +
  22.218 +	e = array_add(&merger->set->files, sizeof *e);
  22.219 +	e->name = hashtable_tokenize(&merger->table, name);
  22.220 +	e->flags = 0;
  22.221 +	e->start = 0;
  22.222 +
  22.223 +	return e - (struct razor_entry *)merger->set->files.data;
  22.224 +}
  22.225 +
  22.226 +/* FIXME. Blah */
  22.227 +static int
  22.228 +fix_file_map(uint32_t *map,
  22.229 +	     struct razor_entry *files,
  22.230 +	     struct razor_entry *top)
  22.231 +{
  22.232 +	uint32_t e;
  22.233 +	int found_file = 0;
  22.234 +
  22.235 +	e = top->start;
  22.236 +	do {
  22.237 +		if (files[e].start)
  22.238 +			fix_file_map(map, files, &files[e]);
  22.239 +		if (map[e])
  22.240 +			found_file = 1;
  22.241 +	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
  22.242 +
  22.243 +	if (found_file)
  22.244 +		map[top - files] = 1;
  22.245 +	return found_file;
  22.246 +}
  22.247 +
  22.248 +struct merge_directory {
  22.249 +	uint32_t merged, dir1, dir2;
  22.250 +};
  22.251 +
  22.252 +static void
  22.253 +merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
  22.254 +{
  22.255 +	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
  22.256 +	struct razor_set *set1, *set2;
  22.257 +	struct array merge_stack;
  22.258 +	struct merge_directory *child_md, *end_md;
  22.259 +	uint32_t *map1, *map2, start, last;
  22.260 +	int cmp;
  22.261 +	char *pool1, *pool2;
  22.262 +
  22.263 +	set1 = merger->source1.set;
  22.264 +	set2 = merger->source2.set;
  22.265 +	map1 = merger->source1.file_map;
  22.266 +	map2 = merger->source2.file_map;
  22.267 +	pool1 = set1->string_pool.data;
  22.268 +	pool2 = set2->string_pool.data;
  22.269 +	root1 = (struct razor_entry *) set1->files.data;
  22.270 +	root2 = (struct razor_entry *) set2->files.data;
  22.271 +
  22.272 +	array_init(&merge_stack);
  22.273 +
  22.274 +	start = merger->set->files.size / sizeof (struct razor_entry);
  22.275 +	last = 0;
  22.276 +	e1 = md->dir1 ? root1 + md->dir1 : NULL;
  22.277 +	e2 = md->dir2 ? root2 + md->dir2 : NULL;
  22.278 +	while (e1 || e2) {
  22.279 +		if (!e2 && !map1[e1 - root1]) {
  22.280 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  22.281 +				e1 = NULL;
  22.282 +			continue;
  22.283 +		}
  22.284 +		if (!e1 && !map2[e2 - root2]) {
  22.285 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  22.286 +				e2 = NULL;
  22.287 +			continue;
  22.288 +		}
  22.289 +		if (e1 && !map1[e1 - root1] &&
  22.290 +		    e2 && !map1[e2 - root2]) {
  22.291 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  22.292 +				e1 = NULL;
  22.293 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  22.294 +				e2 = NULL;
  22.295 +			continue;
  22.296 +		}
  22.297 +
  22.298 +		if (!e1)
  22.299 +			cmp = 1;
  22.300 +		else if (!e2)
  22.301 +			cmp = -1;
  22.302 +		else {
  22.303 +			cmp = strcmp (&pool1[e1->name],
  22.304 +				      &pool2[e2->name]);
  22.305 +		}
  22.306 +
  22.307 +		if (cmp < 0) {
  22.308 +			if (map1[e1 - root1]) {
  22.309 +				map1[e1 - root1] = last =
  22.310 +					add_file(merger, &pool1[e1->name]);
  22.311 +				if (e1->start) {
  22.312 +					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  22.313 +					child_md->merged = last;
  22.314 +					child_md->dir1 = e1->start;
  22.315 +					child_md->dir2 = 0;
  22.316 +				}
  22.317 +			}
  22.318 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  22.319 +				e1 = NULL;
  22.320 +		} else if (cmp > 0) {
  22.321 +			if (map2[e2 - root2]) {
  22.322 +				map2[e2 - root2] = last =
  22.323 +					add_file(merger, &pool2[e2->name]);
  22.324 +				if (e2->start) {
  22.325 +					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  22.326 +					child_md->merged = last;
  22.327 +					child_md->dir1 = 0;
  22.328 +					child_md->dir2 = e2->start;
  22.329 +				}
  22.330 +			}
  22.331 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  22.332 +				e2 = NULL;
  22.333 +		} else {
  22.334 +			map1[e1 - root1] = map2[e2- root2] = last =
  22.335 +				add_file(merger, &pool1[e1->name]);
  22.336 +			if (e1->start || e2->start) {
  22.337 +				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
  22.338 +				child_md->merged = last;
  22.339 +				child_md->dir1 = e1->start;
  22.340 +				child_md->dir2 = e2->start;
  22.341 +			}
  22.342 +			if ((e1++)->flags & RAZOR_ENTRY_LAST)
  22.343 +				e1 = NULL;
  22.344 +			if ((e2++)->flags & RAZOR_ENTRY_LAST)
  22.345 +				e2 = NULL;
  22.346 +		}
  22.347 +	}
  22.348 +
  22.349 +	mroot = (struct razor_entry *)merger->set->files.data;
  22.350 +	if (last) {
  22.351 +		mroot[last].flags = RAZOR_ENTRY_LAST;
  22.352 +		mroot[md->merged].start = start;
  22.353 +	} else
  22.354 +		mroot[md->merged].start = 0;
  22.355 +
  22.356 +	end_md = merge_stack.data + merge_stack.size;
  22.357 +	for (child_md = merge_stack.data; child_md < end_md; child_md++)
  22.358 +		merge_one_directory(merger, child_md);
  22.359 +	array_release(&merge_stack);
  22.360 +}
  22.361 +
  22.362 +static void
  22.363 +merge_files(struct razor_merger *merger)
  22.364 +{
  22.365 +	struct razor_entry *root;
  22.366 +	struct merge_directory md;
  22.367 +	uint32_t *map1, *map2;
  22.368 +
  22.369 +	map1 = merger->source1.file_map;
  22.370 +	map2 = merger->source2.file_map;
  22.371 +
  22.372 +	md.merged = 0;
  22.373 +
  22.374 +	if (merger->source1.set->files.size) {
  22.375 +		root = (struct razor_entry *) merger->source1.set->files.data;
  22.376 +		if (root->start)
  22.377 +			fix_file_map(map1, root, root);
  22.378 +		md.dir1 = root->start;
  22.379 +	} else
  22.380 +		md.dir1 = 0;
  22.381 +
  22.382 +	if (merger->source2.set->files.size) {
  22.383 +		root = (struct razor_entry *) merger->source2.set->files.data;
  22.384 +		if (root->start)
  22.385 +			fix_file_map(map2, root, root);
  22.386 +		md.dir2 = root->start;
  22.387 +	} else
  22.388 +		md.dir2 = 0;
  22.389 +
  22.390 +	merge_one_directory(merger, &md);
  22.391 +}
  22.392 +
  22.393 +static void
  22.394 +emit_files(struct list_head *files, struct array *source_pool,
  22.395 +	   uint32_t *map, struct array *pool)
  22.396 +{
  22.397 +	uint32_t r;
  22.398 +	struct list *p, *q;
  22.399 +
  22.400 +	r = pool->size / sizeof *q;
  22.401 +	p = list_first(files, source_pool);
  22.402 +	while (p) {
  22.403 +		q = array_add(pool, sizeof *q);
  22.404 +		q->data = map[p->data];
  22.405 +		q->flags = p->flags;
  22.406 +		p = list_next(p);
  22.407 +	}
  22.408 +
  22.409 +	list_set_ptr(files, r);
  22.410 +}
  22.411 +
  22.412 +/* Rebuild property->packages maps.  We can't just remap these, as a
  22.413 + * property may have lost or gained a number of packages.  Allocate an
  22.414 + * array per property and loop through the packages and add them to
  22.415 + * the arrays for their properties. */
  22.416 +static void
  22.417 +rebuild_property_package_lists(struct razor_set *set)
  22.418 +{
  22.419 +	struct array *pkgs, *a;
  22.420 +	struct razor_package *pkg, *pkg_end;
  22.421 +	struct razor_property *prop, *prop_end;
  22.422 +	struct list *r;
  22.423 +	uint32_t *q;
  22.424 +	int count;
  22.425 +
  22.426 +	count = set->properties.size / sizeof (struct razor_property);
  22.427 +	pkgs = zalloc(count * sizeof *pkgs);
  22.428 +	pkg_end = set->packages.data + set->packages.size;
  22.429 +
  22.430 +	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  22.431 +		r = list_first(&pkg->properties, &set->property_pool);
  22.432 +		while (r) {
  22.433 +			q = array_add(&pkgs[r->data], sizeof *q);
  22.434 +			*q = pkg - (struct razor_package *) set->packages.data;
  22.435 +			r = list_next(r);
  22.436 +		}
  22.437 +	}
  22.438 +
  22.439 +	prop_end = set->properties.data + set->properties.size;
  22.440 +	a = pkgs;
  22.441 +	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
  22.442 +		list_set_array(&prop->packages, &set->package_pool, a, 0);
  22.443 +		array_release(a);
  22.444 +	}
  22.445 +	free(pkgs);
  22.446 +}
  22.447 +
  22.448 +static void
  22.449 +rebuild_file_package_lists(struct razor_set *set)
  22.450 +{
  22.451 +	struct array *pkgs, *a;
  22.452 +	struct razor_package *pkg, *pkg_end;
  22.453 +	struct razor_entry *entry, *entry_end;
  22.454 +	struct list *r;
  22.455 +	uint32_t *q;
  22.456 +	int count;
  22.457 +
  22.458 +	count = set->files.size / sizeof (struct razor_entry);
  22.459 +	pkgs = zalloc(count * sizeof *pkgs);
  22.460 +	pkg_end = set->packages.data + set->packages.size;
  22.461 +
  22.462 +	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
  22.463 +		r = list_first(&pkg->files, &set->file_pool);
  22.464 +		while (r) {
  22.465 +			q = array_add(&pkgs[r->data], sizeof *q);
  22.466 +			*q = pkg - (struct razor_package *) set->packages.data;
  22.467 +			r = list_next(r);
  22.468 +		}
  22.469 +	}
  22.470 +
  22.471 +	entry_end = set->files.data + set->files.size;
  22.472 +	a = pkgs;
  22.473 +	for (entry = set->files.data; entry < entry_end; entry++, a++) {
  22.474 +		list_set_array(&entry->packages, &set->package_pool, a, 0);
  22.475 +		array_release(a);
  22.476 +	}
  22.477 +	free(pkgs);
  22.478 +}
  22.479 +
  22.480 +struct razor_set *
  22.481 +razor_merger_finish(struct razor_merger *merger)
  22.482 +{
  22.483 +	struct razor_set *result;
  22.484 +	struct razor_package *p, *pend;
  22.485 +
  22.486 +	/* As we built the package list, we filled out a bitvector of
  22.487 +	 * the properties that are referenced by the packages in the
  22.488 +	 * new set.  Now we do a parallel loop through the properties
  22.489 +	 * and emit those marked in the bit vector to the new set.  In
  22.490 +	 * the process, we update the bit vector to actually map from
  22.491 +	 * indices in the old property list to indices in the new
  22.492 +	 * property list for both sets. */
  22.493 +
  22.494 +	merge_properties(merger);
  22.495 +	merge_files(merger);
  22.496 +
  22.497 +	/* Now we loop through the packages again and emit the
  22.498 +	 * property lists, remapped to point to the new properties. */
  22.499 +
  22.500 +	pend = merger->set->packages.data + merger->set->packages.size;
  22.501 +	for (p = merger->set->packages.data; p < pend; p++) {
  22.502 +		struct source *src;
  22.503 +
  22.504 +		if (p->flags & UPSTREAM_SOURCE)
  22.505 +			src = &merger->source2;
  22.506 +		else
  22.507 +			src = &merger->source1;
  22.508 +
  22.509 +		emit_properties(&p->properties,
  22.510 +				&src->set->property_pool,
  22.511 +				src->property_map,
  22.512 +				&merger->set->property_pool);
  22.513 +		emit_files(&p->files,
  22.514 +			   &src->set->file_pool,
  22.515 +			   src->file_map,
  22.516 +			   &merger->set->file_pool);
  22.517 +		p->flags &= ~UPSTREAM_SOURCE;
  22.518 +	}
  22.519 +
  22.520 +	rebuild_property_package_lists(merger->set);
  22.521 +	rebuild_file_package_lists(merger->set);
  22.522 +
  22.523 +	result = merger->set;
  22.524 +	hashtable_release(&merger->table);
  22.525 +	free(merger);
  22.526 +
  22.527 +	return result;
  22.528 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/librazor/razor-internal.h	Fri Jun 20 19:04:47 2008 -0400
    23.3 @@ -0,0 +1,194 @@
    23.4 +#ifndef _RAZOR_INTERNAL_H_
    23.5 +#define _RAZOR_INTERNAL_H_
    23.6 +
    23.7 +#include <stdlib.h>
    23.8 +#include <stdint.h>
    23.9 +
   23.10 +void *zalloc(size_t size);
   23.11 +
   23.12 +struct array {
   23.13 +	void *data;
   23.14 +	int size, alloc;
   23.15 +};
   23.16 +
   23.17 +void array_init(struct array *array);
   23.18 +void array_release(struct array *array);
   23.19 +void *array_add(struct array *array, int size);
   23.20 +
   23.21 +
   23.22 +struct list_head {
   23.23 +	uint32_t list_ptr : 24;
   23.24 +	uint32_t flags    : 8;
   23.25 +};
   23.26 +
   23.27 +struct list {
   23.28 +	uint32_t data  : 24;
   23.29 +	uint32_t flags : 8;
   23.30 +};
   23.31 +
   23.32 +void list_set_empty(struct list_head *head);
   23.33 +void list_set_ptr(struct list_head *head, uint32_t ptr);
   23.34 +void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
   23.35 +
   23.36 +struct list *list_first(struct list_head *head, struct array *pool);
   23.37 +struct list *list_next(struct list *list);
   23.38 +
   23.39 +void list_remap_pool(struct array *pool, uint32_t *map);
   23.40 +void list_remap_head(struct list_head *list, uint32_t *map);
   23.41 +
   23.42 +
   23.43 +struct hashtable {
   23.44 +	struct array buckets;
   23.45 +	struct array *pool;
   23.46 +};
   23.47 +
   23.48 +void hashtable_init(struct hashtable *table, struct array *pool);
   23.49 +void hashtable_release(struct hashtable *table);
   23.50 +uint32_t hashtable_insert(struct hashtable *table, const char *key);
   23.51 +uint32_t hashtable_lookup(struct hashtable *table, const char *key);
   23.52 +uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
   23.53 +
   23.54 +
   23.55 +struct razor_set_section {
   23.56 +	uint32_t type;
   23.57 +	uint32_t offset;
   23.58 +	uint32_t size;
   23.59 +};
   23.60 +
   23.61 +struct razor_set_header {
   23.62 +	uint32_t magic;
   23.63 +	uint32_t version;
   23.64 +	struct razor_set_section sections[0];
   23.65 +};
   23.66 +
   23.67 +#define RAZOR_MAGIC 		0x7a7a7a7a
   23.68 +#define RAZOR_DETAILS_MAGIC 	0x7a7a7a7b
   23.69 +#define RAZOR_FILES_MAGIC 	0x7a7a7a7c
   23.70 +#define RAZOR_VERSION 1
   23.71 +
   23.72 +#define RAZOR_STRING_POOL		0
   23.73 +#define RAZOR_PACKAGES			1
   23.74 +#define RAZOR_PROPERTIES		2
   23.75 +#define RAZOR_PACKAGE_POOL		3
   23.76 +#define RAZOR_PROPERTY_POOL		4
   23.77 +
   23.78 +#define RAZOR_DETAILS_STRING_POOL	0
   23.79 +
   23.80 +#define RAZOR_FILES			0
   23.81 +#define RAZOR_FILE_POOL			1
   23.82 +#define RAZOR_FILE_STRING_POOL		2
   23.83 +
   23.84 +struct razor_package {
   23.85 +	uint name  : 24;
   23.86 +	uint flags : 8;
   23.87 +	uint32_t version;
   23.88 +	uint32_t arch;
   23.89 +	uint32_t summary;
   23.90 +	uint32_t description;
   23.91 +	uint32_t url;
   23.92 +	uint32_t license;
   23.93 +	struct list_head properties;
   23.94 +	struct list_head files;
   23.95 +};
   23.96 +
   23.97 +
   23.98 +struct razor_property {
   23.99 +	uint32_t name;
  23.100 +	uint32_t flags;
  23.101 +	uint32_t version;
  23.102 +	struct list_head packages;
  23.103 +};
  23.104 +
  23.105 +struct razor_entry {
  23.106 +	uint32_t name  : 24;
  23.107 +	uint32_t flags : 8;
  23.108 +	uint32_t start;
  23.109 +	struct list_head packages;
  23.110 +};
  23.111 +
  23.112 +#define RAZOR_ENTRY_LAST	0x80
  23.113 +
  23.114 +struct razor_set {
  23.115 +	struct array string_pool;
  23.116 + 	struct array packages;
  23.117 + 	struct array properties;
  23.118 + 	struct array files;
  23.119 +	struct array package_pool;
  23.120 + 	struct array property_pool;
  23.121 + 	struct array file_pool;
  23.122 +	struct array file_string_pool;
  23.123 +	struct array details_string_pool;
  23.124 +	struct razor_set_header *header;
  23.125 +	struct razor_set_header *details_header;
  23.126 +	struct razor_set_header *files_header;
  23.127 +};
  23.128 +
  23.129 +struct import_entry {
  23.130 +	uint32_t package;
  23.131 +	char *name;
  23.132 +};
  23.133 +
  23.134 +struct import_directory {
  23.135 +	uint32_t name, count;
  23.136 +	struct array files;
  23.137 +	struct array packages;
  23.138 +	struct import_directory *last;
  23.139 +};
  23.140 +
  23.141 +struct razor_importer {
  23.142 +	struct razor_set *set;
  23.143 +	struct hashtable table;
  23.144 +	struct hashtable file_table;
  23.145 +	struct hashtable details_table;
  23.146 +	struct razor_package *package;
  23.147 +	struct array properties;
  23.148 +	struct array files;
  23.149 +	struct array file_requires;
  23.150 +};
  23.151 +
  23.152 +struct razor_package_iterator {
  23.153 +	struct razor_set *set;
  23.154 +	struct razor_package *package, *end;
  23.155 +	struct list *index;
  23.156 +	int free_index;
  23.157 +};
  23.158 +
  23.159 +void
  23.160 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
  23.161 +					 struct razor_set *set,
  23.162 +					 struct razor_property *property);
  23.163 +
  23.164 +struct razor_property_iterator {
  23.165 +	struct razor_set *set;
  23.166 +	struct razor_property *property, *end;
  23.167 +	struct list *index;
  23.168 +};
  23.169 +
  23.170 +#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
  23.171 +
  23.172 +struct razor_entry *
  23.173 +razor_set_find_entry(struct razor_set *set,
  23.174 +		     struct razor_entry *dir, const char *pattern);
  23.175 +
  23.176 +struct razor_merger *
  23.177 +razor_merger_create(struct razor_set *set1, struct razor_set *set2);
  23.178 +void
  23.179 +razor_merger_add_package(struct razor_merger *merger,
  23.180 +			 struct razor_package *package);
  23.181 +struct razor_set *
  23.182 +razor_merger_finish(struct razor_merger *merger);
  23.183 +
  23.184 +/* Utility functions */
  23.185 +
  23.186 +int razor_create_dir(const char *root, const char *path);
  23.187 +int razor_write(int fd, const void *data, size_t size);
  23.188 +
  23.189 +
  23.190 +typedef int (*razor_compare_with_data_func_t)(const void *p1,
  23.191 +					      const void *p,
  23.192 +					      void *data);
  23.193 +uint32_t *
  23.194 +razor_qsort_with_data(void *base, size_t nelem, size_t size,
  23.195 +		      razor_compare_with_data_func_t compare, void *data);
  23.196 +
  23.197 +#endif /* _RAZOR_INTERNAL_H_ */
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/librazor/razor.c	Fri Jun 20 19:04:47 2008 -0400
    24.3 @@ -0,0 +1,588 @@
    24.4 +/*
    24.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    24.6 + * Copyright (C) 2008  Red Hat, Inc
    24.7 + *
    24.8 + * This program is free software; you can redistribute it and/or modify
    24.9 + * it under the terms of the GNU General Public License as published by
   24.10 + * the Free Software Foundation; either version 2 of the License, or
   24.11 + * (at your option) any later version.
   24.12 + *
   24.13 + * This program is distributed in the hope that it will be useful,
   24.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.16 + * GNU General Public License for more details.
   24.17 + *
   24.18 + * You should have received a copy of the GNU General Public License along
   24.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   24.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   24.21 + */
   24.22 +
   24.23 +#define _GNU_SOURCE
   24.24 +
   24.25 +#include <stdlib.h>
   24.26 +#include <stddef.h>
   24.27 +#include <stdint.h>
   24.28 +#include <stdio.h>
   24.29 +#include <string.h>
   24.30 +#include <sys/types.h>
   24.31 +#include <sys/stat.h>
   24.32 +#include <sys/mman.h>
   24.33 +#include <unistd.h>
   24.34 +#include <fcntl.h>
   24.35 +#include <errno.h>
   24.36 +#include <ctype.h>
   24.37 +#include <fnmatch.h>
   24.38 +
   24.39 +#include "razor.h"
   24.40 +#include "razor-internal.h"
   24.41 +
   24.42 +void *
   24.43 +zalloc(size_t size)
   24.44 +{
   24.45 +	void *p;
   24.46 +
   24.47 +	p = malloc(size);
   24.48 +	memset(p, 0, size);
   24.49 +
   24.50 +	return p;
   24.51 +}
   24.52 +
   24.53 +struct razor_set_section razor_sections[] = {
   24.54 +	{ RAZOR_STRING_POOL,	offsetof(struct razor_set, string_pool) },
   24.55 +	{ RAZOR_PACKAGES,	offsetof(struct razor_set, packages) },
   24.56 +	{ RAZOR_PROPERTIES,	offsetof(struct razor_set, properties) },
   24.57 +	{ RAZOR_PACKAGE_POOL,	offsetof(struct razor_set, package_pool) },
   24.58 +	{ RAZOR_PROPERTY_POOL,	offsetof(struct razor_set, property_pool) },
   24.59 +};
   24.60 +
   24.61 +struct razor_set_section razor_files_sections[] = {
   24.62 +	{ RAZOR_FILES,			offsetof(struct razor_set, files) },
   24.63 +	{ RAZOR_FILE_POOL,		offsetof(struct razor_set, file_pool) },
   24.64 +	{ RAZOR_FILE_STRING_POOL,	offsetof(struct razor_set, file_string_pool) },
   24.65 +};
   24.66 +
   24.67 +struct razor_set_section razor_details_sections[] = {
   24.68 +	{ RAZOR_DETAILS_STRING_POOL,	offsetof(struct razor_set, details_string_pool) },
   24.69 +};
   24.70 +struct razor_set *
   24.71 +razor_set_create(void)
   24.72 +{
   24.73 +	struct razor_set *set;
   24.74 +	struct razor_entry *e;
   24.75 +	char *empty;
   24.76 +
   24.77 +	set = zalloc(sizeof *set);
   24.78 +
   24.79 +	e = array_add(&set->files, sizeof *e);
   24.80 +	empty = array_add(&set->string_pool, 1);
   24.81 +	*empty = '\0';
   24.82 +	e->name = 0;
   24.83 +	e->flags = RAZOR_ENTRY_LAST;
   24.84 +	e->start = 0;
   24.85 +	list_set_empty(&e->packages);
   24.86 +
   24.87 +	return set;
   24.88 +}
   24.89 +
   24.90 +struct razor_set *
   24.91 +razor_set_open(const char *filename)
   24.92 +{
   24.93 +	struct razor_set *set;
   24.94 +	struct razor_set_section *s;
   24.95 +	struct stat stat;
   24.96 +	struct array *array;
   24.97 +	int fd;
   24.98 +
   24.99 +	set = zalloc(sizeof *set);
  24.100 +	fd = open(filename, O_RDONLY);
  24.101 +	if (fstat(fd, &stat) < 0)
  24.102 +		return NULL;
  24.103 +	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  24.104 +	if (set->header == MAP_FAILED) {
  24.105 +		free(set);
  24.106 +		return NULL;
  24.107 +	}
  24.108 +
  24.109 +	for (s = set->header->sections; ~s->type; s++) {
  24.110 +		if (s->type >= ARRAY_SIZE(razor_sections))
  24.111 +			continue;
  24.112 +		if (s->type != razor_sections[s->type].type)
  24.113 +			continue;
  24.114 +		array = (void *) set + razor_sections[s->type].offset;
  24.115 +		array->data = (void *) set->header + s->offset;
  24.116 +		array->size = s->size;
  24.117 +		array->alloc = s->size;
  24.118 +	}
  24.119 +	close(fd);
  24.120 +
  24.121 +	return set;
  24.122 +}
  24.123 +
  24.124 +void
  24.125 +razor_set_open_details(struct razor_set *set, const char *filename)
  24.126 +{
  24.127 +	struct razor_set_section *s;
  24.128 +	struct stat stat;
  24.129 +	struct array *array;
  24.130 +	int fd;
  24.131 +
  24.132 +	fd = open(filename, O_RDONLY);
  24.133 +	if (fstat(fd, &stat) < 0)
  24.134 +		return;
  24.135 +	set->details_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  24.136 +	if (set->details_header == MAP_FAILED)
  24.137 +		return;
  24.138 +
  24.139 +	for (s = set->details_header->sections; ~s->type; s++) {
  24.140 +		if (s->type >= ARRAY_SIZE(razor_details_sections))
  24.141 +			continue;
  24.142 +		if (s->type != razor_details_sections[s->type].type)
  24.143 +			continue;
  24.144 +		array = (void *) set + razor_details_sections[s->type].offset;
  24.145 +		array->data = (void *) set->details_header + s->offset;
  24.146 +		array->size = s->size;
  24.147 +		array->alloc = s->size;
  24.148 +	}
  24.149 +	close(fd);
  24.150 +}
  24.151 +
  24.152 +void
  24.153 +razor_set_open_files(struct razor_set *set, const char *filename)
  24.154 +{
  24.155 +	struct razor_set_section *s;
  24.156 +	struct stat stat;
  24.157 +	struct array *array;
  24.158 +	int fd;
  24.159 +
  24.160 +	fd = open(filename, O_RDONLY);
  24.161 +	if (fstat(fd, &stat) < 0)
  24.162 +		return;
  24.163 +	set->files_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  24.164 +	if (set->files_header == MAP_FAILED)
  24.165 +		return;
  24.166 +
  24.167 +	for (s = set->files_header->sections; ~s->type; s++) {
  24.168 +		if (s->type >= ARRAY_SIZE(razor_files_sections))
  24.169 +			continue;
  24.170 +		if (s->type != razor_files_sections[s->type].type)
  24.171 +			continue;
  24.172 +		array = (void *) set + razor_files_sections[s->type].offset;
  24.173 +		array->data = (void *) set->files_header + s->offset;
  24.174 +		array->size = s->size;
  24.175 +		array->alloc = s->size;
  24.176 +	}
  24.177 +	close(fd);
  24.178 +}
  24.179 +
  24.180 +void
  24.181 +razor_set_destroy(struct razor_set *set)
  24.182 +{
  24.183 +	unsigned int size;
  24.184 +	struct array *a;
  24.185 +	int i;
  24.186 +
  24.187 +	if (set->header) {
  24.188 +		for (i = 0; set->header->sections[i].type; i++)
  24.189 +			;
  24.190 +		size = set->header->sections[i].type;
  24.191 +		munmap(set->header, size);
  24.192 +	} else {
  24.193 +		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  24.194 +			a = (void *) set + razor_sections[i].offset;
  24.195 +			free(a->data);
  24.196 +		}
  24.197 +	}
  24.198 +
  24.199 +	if (set->details_header) {
  24.200 +		for (i = 0; set->details_header->sections[i].type; i++)
  24.201 +			;
  24.202 +		size = set->details_header->sections[i].type;
  24.203 +		munmap(set->details_header, size);
  24.204 +	} else {
  24.205 +		for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
  24.206 +			a = (void *) set + razor_details_sections[i].offset;
  24.207 +			free(a->data);
  24.208 +		}
  24.209 +	}
  24.210 +
  24.211 +	if (set->files_header) {
  24.212 +		for (i = 0; set->files_header->sections[i].type; i++)
  24.213 +			;
  24.214 +		size = set->files_header->sections[i].type;
  24.215 +		munmap(set->files_header, size);
  24.216 +	} else {
  24.217 +		for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
  24.218 +			a = (void *) set + razor_files_sections[i].offset;
  24.219 +			free(a->data);
  24.220 +		}
  24.221 +	}
  24.222 +
  24.223 +	free(set);
  24.224 +}
  24.225 +
  24.226 +static int
  24.227 +razor_set_write_sections_to_fd(struct razor_set *set, int fd, int magic,
  24.228 +			       struct razor_set_section *sections,
  24.229 +			       size_t array_size)
  24.230 +{
  24.231 +	char data[4096];
  24.232 +	struct razor_set_header *header = (struct razor_set_header *) data;
  24.233 +	struct array *a;
  24.234 +	uint32_t offset;
  24.235 +	int i;
  24.236 +
  24.237 +	memset(data, 0, sizeof data);
  24.238 +	header->magic = magic;
  24.239 +	header->version = RAZOR_VERSION;
  24.240 +	offset = sizeof data;
  24.241 +
  24.242 +	for (i = 0; i < array_size; i++) {
  24.243 +		if (sections[i].type != i)
  24.244 +			continue;
  24.245 +		a = (void *) set + sections[i].offset;
  24.246 +		header->sections[i].type = i;
  24.247 +		header->sections[i].offset = offset;
  24.248 +		header->sections[i].size = a->size;
  24.249 +		offset += ALIGN(a->size, 4096);
  24.250 +	}
  24.251 +
  24.252 +	header->sections[i].type = ~0;
  24.253 +	header->sections[i].offset = 0;
  24.254 +	header->sections[i].size = 0;
  24.255 +
  24.256 +	razor_write(fd, data, sizeof data);
  24.257 +	memset(data, 0, sizeof data);
  24.258 +	for (i = 0; i < array_size; i++) {
  24.259 +		if (sections[i].type != i)
  24.260 +			continue;
  24.261 +		a = (void *) set + sections[i].offset;
  24.262 +		razor_write(fd, a->data, a->size);
  24.263 +		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
  24.264 +	}
  24.265 +
  24.266 +	return 0;
  24.267 +}
  24.268 +
  24.269 +int
  24.270 +razor_set_write_to_fd(struct razor_set *set, int fd,
  24.271 +		      enum razor_repo_file_type type)
  24.272 +{
  24.273 +	switch (type) {
  24.274 +	case RAZOR_REPO_FILE_MAIN:
  24.275 +		return razor_set_write_sections_to_fd(set, fd, RAZOR_MAGIC,
  24.276 +						      razor_sections,
  24.277 +						      ARRAY_SIZE(razor_sections));
  24.278 +
  24.279 +	case RAZOR_REPO_FILE_DETAILS:
  24.280 +		return razor_set_write_sections_to_fd(set, fd, RAZOR_DETAILS_MAGIC,
  24.281 +						      razor_details_sections,
  24.282 +						      ARRAY_SIZE(razor_details_sections));
  24.283 +	case RAZOR_REPO_FILE_FILES:
  24.284 +		return razor_set_write_sections_to_fd(set, fd, RAZOR_FILES_MAGIC,
  24.285 +						      razor_files_sections,
  24.286 +						      ARRAY_SIZE(razor_files_sections));
  24.287 +	default:
  24.288 +		return -1;
  24.289 +	}
  24.290 +}
  24.291 +
  24.292 +int
  24.293 +razor_set_write(struct razor_set *set, const char *filename,
  24.294 +		enum razor_repo_file_type type)
  24.295 +{
  24.296 +	int fd, status;
  24.297 +
  24.298 +	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
  24.299 +	if (fd < 0)
  24.300 +		return -1;
  24.301 +
  24.302 +	status = razor_set_write_to_fd(set, fd, type);
  24.303 +	if (status) {
  24.304 +	    close(fd);
  24.305 +	    return status;
  24.306 +	}
  24.307 +
  24.308 +	return close(fd);
  24.309 +}
  24.310 +void
  24.311 +razor_build_evr(char *evr_buf, int size, const char *epoch,
  24.312 +		const char *version, const char *release)
  24.313 +{
  24.314 +	int len;
  24.315 +
  24.316 +	if (!version || !*version) {
  24.317 +		*evr_buf = '\0';
  24.318 +		return;
  24.319 +	}
  24.320 +
  24.321 +	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
  24.322 +		len = snprintf(evr_buf, size, "%s:", epoch);
  24.323 +		evr_buf += len;
  24.324 +		size -= len;
  24.325 +	}
  24.326 +	len = snprintf(evr_buf, size, "%s", version);
  24.327 +	evr_buf += len;
  24.328 +	size -= len;
  24.329 +	if (release && *release)
  24.330 +		snprintf(evr_buf, size, "-%s", release);
  24.331 +}
  24.332 +
  24.333 +int
  24.334 +razor_versioncmp(const char *s1, const char *s2)
  24.335 +{
  24.336 +	const char *p1, *p2;
  24.337 +	long n1, n2;
  24.338 +	int res;
  24.339 +
  24.340 +	n1 = strtol(s1, (char **) &p1, 10);
  24.341 +	n2 = strtol(s2, (char **) &p2, 10);
  24.342 +
  24.343 +	/* Epoch; if one but not the other has an epoch set, default
  24.344 +	 * the epoch-less version to 0. */
  24.345 +	res = (*p1 == ':') - (*p2 == ':');
  24.346 +	if (res < 0) {
  24.347 +		n1 = 0;
  24.348 +		p1 = s1;
  24.349 +		p2++;
  24.350 +	} else if (res > 0) {
  24.351 +		p1++;
  24.352 +		n2 = 0;
  24.353 +		p2 = s2;
  24.354 +	}
  24.355 +
  24.356 +	if (n1 != n2)
  24.357 +		return n1 - n2;
  24.358 +	while (*p1 && *p2) {
  24.359 +		if (*p1 != *p2)
  24.360 +			return *p1 - *p2;
  24.361 +		p1++;
  24.362 +		p2++;
  24.363 +		if (isdigit(*p1) && isdigit(*p2))
  24.364 +			return razor_versioncmp(p1, p2);
  24.365 +	}
  24.366 +
  24.367 +	return *p1 - *p2;
  24.368 +}
  24.369 +
  24.370 +struct razor_package *
  24.371 +razor_set_get_package(struct razor_set *set, const char *package)
  24.372 +{
  24.373 +	struct razor_package_iterator *pi;
  24.374 +	struct razor_package *p;
  24.375 +	const char *name, *version, *arch;
  24.376 +
  24.377 +	pi = razor_package_iterator_create(set);
  24.378 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  24.379 +		if (strcmp(package, name) == 0)
  24.380 +			break;
  24.381 +	}
  24.382 +	razor_package_iterator_destroy(pi);
  24.383 +
  24.384 +	return p;
  24.385 +}
  24.386 +
  24.387 +void
  24.388 +razor_package_get_details(struct razor_set *set, struct razor_package *package,
  24.389 +			  const char **summary, const char **description,
  24.390 +			  const char **url, const char **license)
  24.391 +{
  24.392 +	const char *pool = set->details_string_pool.data;
  24.393 +
  24.394 +	*summary = &pool[package->summary];
  24.395 +	*description = &pool[package->description];
  24.396 +	*url = &pool[package->url];
  24.397 +	*license = &pool[package->license];
  24.398 +}
  24.399 +
  24.400 +struct razor_entry *
  24.401 +razor_set_find_entry(struct razor_set *set,
  24.402 +		     struct razor_entry *dir, const char *pattern)
  24.403 +{
  24.404 +	struct razor_entry *e;
  24.405 +	const char *n, *pool = set->string_pool.data;
  24.406 +	int len;
  24.407 +
  24.408 +	e = (struct razor_entry *) set->files.data + dir->start;
  24.409 +	do {
  24.410 +		n = pool + e->name;
  24.411 +		if (strcmp(pattern + 1, n) == 0)
  24.412 +			return e;
  24.413 +		len = strlen(n);
  24.414 +		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
  24.415 +		    pattern[len + 1] == '/') {
  24.416 +			return razor_set_find_entry(set, e, pattern + len + 1);
  24.417 +		}
  24.418 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  24.419 +
  24.420 +	return NULL;
  24.421 +}
  24.422 +
  24.423 +static void
  24.424 +list_dir(struct razor_set *set, struct razor_entry *dir,
  24.425 +	 char *prefix, const char *pattern)
  24.426 +{
  24.427 +	struct razor_entry *e;
  24.428 +	const char *n, *pool = set->string_pool.data;
  24.429 +
  24.430 +	e = (struct razor_entry *) set->files.data + dir->start;
  24.431 +	do {
  24.432 +		n = pool + e->name;
  24.433 +		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
  24.434 +			continue;
  24.435 +		printf("%s/%s\n", prefix, n);
  24.436 +		if (e->start) {
  24.437 +			char *sub = prefix + strlen (prefix);
  24.438 +			*sub = '/';
  24.439 +			strcpy (sub + 1, n);
  24.440 +			list_dir(set, e, prefix, pattern);
  24.441 +			*sub = '\0';
  24.442 +		}
  24.443 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  24.444 +}
  24.445 +
  24.446 +void
  24.447 +razor_set_list_files(struct razor_set *set, const char *pattern)
  24.448 +{
  24.449 +	struct razor_entry *e;
  24.450 +	char buffer[512], *p, *base;
  24.451 +
  24.452 +	if (pattern == NULL || !strcmp (pattern, "/")) {
  24.453 +		buffer[0] = '\0';
  24.454 +		list_dir(set, set->files.data, buffer, NULL);
  24.455 +		return;
  24.456 +	}
  24.457 +
  24.458 +	strcpy(buffer, pattern);
  24.459 +	e = razor_set_find_entry(set, set->files.data, buffer);
  24.460 +	if (e && e->start > 0) {
  24.461 +		base = NULL;
  24.462 +	} else {
  24.463 +		p = strrchr(buffer, '/');
  24.464 +		if (p) {
  24.465 +			*p = '\0';
  24.466 +			base = p + 1;
  24.467 +		} else {
  24.468 +			base = NULL;
  24.469 +		}
  24.470 +	}
  24.471 +	e = razor_set_find_entry(set, set->files.data, buffer);
  24.472 +	if (e->start != 0)
  24.473 +		list_dir(set, e, buffer, base);
  24.474 +}
  24.475 +
  24.476 +static struct list *
  24.477 +list_package_files(struct razor_set *set, struct list *r,
  24.478 +		   struct razor_entry *dir, uint32_t end,
  24.479 +		   char *prefix)
  24.480 +{
  24.481 +	struct razor_entry *e, *f, *entries;
  24.482 +	uint32_t next, file;
  24.483 +	char *pool;
  24.484 +	int len;
  24.485 +
  24.486 +	entries = (struct razor_entry *) set->files.data;
  24.487 +	pool = set->string_pool.data;
  24.488 +
  24.489 +	e = entries + dir->start;
  24.490 +	do {
  24.491 +		if (entries + r->data == e) {
  24.492 +			printf("%s/%s\n", prefix, pool + e->name);
  24.493 +			r = list_next(r);
  24.494 +			if (!r)
  24.495 +				return NULL;
  24.496 +			if (r->data >= end)
  24.497 +				return r;
  24.498 +		}
  24.499 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
  24.500 +
  24.501 +	e = entries + dir->start;
  24.502 +	do {
  24.503 +		if (e->start == 0)
  24.504 +			continue;
  24.505 +
  24.506 +		if (e->flags & RAZOR_ENTRY_LAST)
  24.507 +			next = end;
  24.508 +		else {
  24.509 +			f = e + 1;
  24.510 +			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
  24.511 +				f++;
  24.512 +			if (f->start == 0)
  24.513 +				next = end;
  24.514 +			else
  24.515 +				next = f->start;
  24.516 +		}
  24.517 +
  24.518 +		file = r->data;
  24.519 +		if (e->start <= file && file < next) {
  24.520 +			len = strlen(prefix);
  24.521 +			prefix[len] = '/';
  24.522 +			strcpy(prefix + len + 1, pool + e->name);
  24.523 +			r = list_package_files(set, r, e, next, prefix);
  24.524 +			prefix[len] = '\0';
  24.525 +		}
  24.526 +	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
  24.527 +
  24.528 +	return r;
  24.529 +}
  24.530 +
  24.531 +void
  24.532 +razor_set_list_package_files(struct razor_set *set, const char *name)
  24.533 +{
  24.534 +	struct razor_package *package;
  24.535 +	struct list *r;
  24.536 +	uint32_t end;
  24.537 +	char buffer[512];
  24.538 +
  24.539 +	package = razor_set_get_package(set, name);
  24.540 +
  24.541 +	r = list_first(&package->files, &set->file_pool);
  24.542 +	end = set->files.size / sizeof (struct razor_entry);
  24.543 +	buffer[0] = '\0';
  24.544 +	list_package_files(set, r, set->files.data, end, buffer);
  24.545 +}
  24.546 +
  24.547 +/* The diff order matters.  We should sort the packages so that a
  24.548 + * REMOVE of a package comes before the INSTALL, and so that all
  24.549 + * requires for a package have been installed before the package.
  24.550 + **/
  24.551 +
  24.552 +void
  24.553 +razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  24.554 +	       razor_package_callback_t callback, void *data)
  24.555 +{
  24.556 + 	struct razor_package_iterator *pi1, *pi2;
  24.557 + 	struct razor_package *p1, *p2;
  24.558 +	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
  24.559 +	int res;
  24.560 +
  24.561 +	pi1 = razor_package_iterator_create(set);
  24.562 +	pi2 = razor_package_iterator_create(upstream);
  24.563 +
  24.564 +	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
  24.565 +	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
  24.566 +
  24.567 +	while (p1 || p2) {
  24.568 +		if (p1 && p2) {
  24.569 +			res = strcmp(name1, name2);
  24.570 +			if (res == 0)
  24.571 +				res = razor_versioncmp(version1, version2);
  24.572 +		} else {
  24.573 +			res = 0;
  24.574 +		}
  24.575 +
  24.576 +		if (p2 == NULL || res < 0)
  24.577 +			callback(name1, version1, NULL, arch1, data);
  24.578 +		else if (p1 == NULL || res > 0)
  24.579 +			callback(name2, NULL, version2, arch2, data);
  24.580 +
  24.581 +		if (p1 != NULL && res <= 0)
  24.582 +			razor_package_iterator_next(pi1, &p1,
  24.583 +						    &name1, &version1, &arch1);
  24.584 +		if (p2 != NULL && res >= 0)
  24.585 +			razor_package_iterator_next(pi2, &p2,
  24.586 +						    &name2, &version2, &arch2);
  24.587 +	}
  24.588 +
  24.589 +	razor_package_iterator_destroy(pi1);
  24.590 +	razor_package_iterator_destroy(pi2);
  24.591 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/librazor/razor.h	Fri Jun 20 19:04:47 2008 -0400
    25.3 @@ -0,0 +1,218 @@
    25.4 +/*
    25.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    25.6 + * Copyright (C) 2008  Red Hat, Inc
    25.7 + *
    25.8 + * This program is free software; you can redistribute it and/or modify
    25.9 + * it under the terms of the GNU General Public License as published by
   25.10 + * the Free Software Foundation; either version 2 of the License, or
   25.11 + * (at your option) any later version.
   25.12 + *
   25.13 + * This program is distributed in the hope that it will be useful,
   25.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.16 + * GNU General Public License for more details.
   25.17 + *
   25.18 + * You should have received a copy of the GNU General Public License along
   25.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   25.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   25.21 + */
   25.22 +
   25.23 +#ifndef _RAZOR_H_
   25.24 +#define _RAZOR_H_
   25.25 +
   25.26 +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
   25.27 +
   25.28 +struct razor_set;
   25.29 +struct razor_package;
   25.30 +struct razor_property;
   25.31 +
   25.32 +enum razor_repo_file_type {
   25.33 +	RAZOR_REPO_FILE_MAIN,
   25.34 +	RAZOR_REPO_FILE_DETAILS,
   25.35 +	RAZOR_REPO_FILE_FILES
   25.36 +};
   25.37 +
   25.38 +enum razor_property_flags {
   25.39 +	RAZOR_PROPERTY_LESS		= 1 << 0,
   25.40 +	RAZOR_PROPERTY_GREATER		= 1 << 1,
   25.41 +	RAZOR_PROPERTY_EQUAL		= 1 << 2,
   25.42 +	RAZOR_PROPERTY_RELATION_MASK	=
   25.43 +		RAZOR_PROPERTY_LESS |
   25.44 +		RAZOR_PROPERTY_GREATER |
   25.45 +		RAZOR_PROPERTY_EQUAL,
   25.46 +
   25.47 +	RAZOR_PROPERTY_REQUIRES		= 0 << 3,
   25.48 +	RAZOR_PROPERTY_PROVIDES		= 1 << 3,
   25.49 +	RAZOR_PROPERTY_CONFLICTS	= 2 << 3,
   25.50 +	RAZOR_PROPERTY_OBSOLETES	= 3 << 3,
   25.51 +	RAZOR_PROPERTY_TYPE_MASK	= 3 << 3,
   25.52 +		
   25.53 +	RAZOR_PROPERTY_PRE		= 1 << 5,
   25.54 +	RAZOR_PROPERTY_POST		= 1 << 6,
   25.55 +	RAZOR_PROPERTY_PREUN		= 1 << 7,
   25.56 +	RAZOR_PROPERTY_POSTUN		= 1 << 8
   25.57 +};
   25.58 +
   25.59 +const char *
   25.60 +razor_property_relation_to_string(struct razor_property *p);
   25.61 +const char *
   25.62 +razor_property_type_to_string(struct razor_property *p);
   25.63 +
   25.64 +struct razor_set *razor_set_create(void);
   25.65 +struct razor_set *razor_set_open(const char *filename);
   25.66 +void razor_set_destroy(struct razor_set *set);
   25.67 +int razor_set_write_to_fd(struct razor_set *set, int fd,
   25.68 +			  enum razor_repo_file_type type);
   25.69 +int razor_set_write(struct razor_set *set, const char *filename,
   25.70 +		    enum razor_repo_file_type type);
   25.71 +
   25.72 +void razor_set_open_details(struct razor_set *set, const char *filename);
   25.73 +void razor_set_open_files(struct razor_set *set, const char *filename);
   25.74 +
   25.75 +struct razor_package *
   25.76 +razor_set_get_package(struct razor_set *set, const char *package);
   25.77 +
   25.78 +void
   25.79 +razor_package_get_details(struct razor_set *set, struct razor_package *package,
   25.80 +			  const char **summary, const char **description,
   25.81 +			  const char **url, const char **license);
   25.82 +
   25.83 +struct razor_package_iterator;
   25.84 +struct razor_package_iterator *
   25.85 +razor_package_iterator_create(struct razor_set *set);
   25.86 +struct razor_package_iterator *
   25.87 +razor_package_iterator_create_for_property(struct razor_set *set,
   25.88 +					   struct razor_property *property);
   25.89 +struct razor_package_iterator *
   25.90 +razor_package_iterator_create_for_file(struct razor_set *set,
   25.91 +				       const char *filename);
   25.92 +
   25.93 +int razor_package_iterator_next(struct razor_package_iterator *pi,
   25.94 +				struct razor_package **package,
   25.95 +				const char **name,
   25.96 +				const char **version,
   25.97 +				const char **arch);
   25.98 +void razor_package_iterator_destroy(struct razor_package_iterator *pi);
   25.99 +
  25.100 +struct razor_package_query *
  25.101 +razor_package_query_create(struct razor_set *set);
  25.102 +void
  25.103 +razor_package_query_add_package(struct razor_package_query *pq,
  25.104 +				struct razor_package *p);
  25.105 +void
  25.106 +razor_package_query_add_iterator(struct razor_package_query *pq,
  25.107 +				 struct razor_package_iterator *pi);
  25.108 +struct razor_package_iterator *
  25.109 +razor_package_query_finish(struct razor_package_query *pq);
  25.110 +
  25.111 +struct razor_property_iterator;
  25.112 +struct razor_property_iterator *
  25.113 +razor_property_iterator_create(struct razor_set *set,
  25.114 +			       struct razor_package *package);
  25.115 +int razor_property_iterator_next(struct razor_property_iterator *pi,
  25.116 +				 struct razor_property **property,
  25.117 +				 const char **name,
  25.118 +				 uint32_t *flags,
  25.119 +				 const char **version);
  25.120 +void
  25.121 +razor_property_iterator_destroy(struct razor_property_iterator *pi);
  25.122 +
  25.123 +void razor_set_list_files(struct razor_set *set, const char *prefix);
  25.124 +void razor_set_list_package_files(struct razor_set *set, const char *name);
  25.125 +
  25.126 +void razor_set_list_unsatisfied(struct razor_set *set);
  25.127 +
  25.128 +typedef void (*razor_package_callback_t)(const char *name,
  25.129 +					 const char *old_version,
  25.130 +					 const char *new_version,
  25.131 +					 const char *arch,
  25.132 +					 void *data);
  25.133 +void
  25.134 +razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  25.135 +	       razor_package_callback_t callback, void *data);
  25.136 +
  25.137 +/* Package transactions */
  25.138 +
  25.139 +struct razor_transaction *
  25.140 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
  25.141 +void razor_transaction_install_package(struct razor_transaction *transaction,
  25.142 +				       struct razor_package *package);
  25.143 +void razor_transaction_remove_package(struct razor_transaction *transaction,
  25.144 +				      struct razor_package *package);
  25.145 +void razor_transaction_update_package(struct razor_transaction *trans,
  25.146 +				      struct razor_package *package);
  25.147 +void razor_transaction_update_all(struct razor_transaction *transaction);
  25.148 +int razor_transaction_resolve(struct razor_transaction *trans);
  25.149 +int razor_transaction_describe(struct razor_transaction *trans);
  25.150 +struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
  25.151 +void razor_transaction_destroy(struct razor_transaction *trans);
  25.152 +
  25.153 +/* Temporary helper for test suite. */
  25.154 +int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  25.155 +					   const char *name,
  25.156 +					   uint32_t flags,
  25.157 +					   const char *version);
  25.158 +
  25.159 +/* Importer interface; for building a razor set from external sources,
  25.160 + * like yum, rpmdb or razor package files. */
  25.161 +
  25.162 +struct razor_importer;
  25.163 +struct razor_rpm;
  25.164 +
  25.165 +struct razor_importer *razor_importer_new(void);
  25.166 +void razor_importer_destroy(struct razor_importer *importer);
  25.167 +void razor_importer_begin_package(struct razor_importer *importer,
  25.168 +				  const char *name,
  25.169 +				  const char *version,
  25.170 +				  const char *arch);
  25.171 +void razor_importer_add_details(struct razor_importer *importer,
  25.172 +				const char *summary,
  25.173 +				const char *description,
  25.174 +				const char *url,
  25.175 +				const char *license);
  25.176 +void razor_importer_add_property(struct razor_importer *importer,
  25.177 +				 const char *name,
  25.178 +				 uint32_t flags,
  25.179 +				 const char *version);
  25.180 +void razor_importer_add_file(struct razor_importer *importer,
  25.181 +			     const char *name);
  25.182 +void razor_importer_finish_package(struct razor_importer *importer);
  25.183 +
  25.184 +int razor_importer_add_rpm(struct razor_importer *importer,
  25.185 +			   struct razor_rpm *rpm);
  25.186 +
  25.187 +struct razor_set *razor_importer_finish(struct razor_importer *importer);
  25.188 +
  25.189 +void razor_build_evr(char *evr_buf, int size, const char *epoch,
  25.190 +		     const char *version, const char *release);
  25.191 +int razor_versioncmp(const char *s1, const char *s2);
  25.192 +
  25.193 +struct razor_set *razor_set_create_from_yum(void);
  25.194 +struct razor_set *razor_set_create_from_rpmdb(void);
  25.195 +
  25.196 +/* RPM functions */
  25.197 +
  25.198 +struct razor_rpm *razor_rpm_open(const char *filename);
  25.199 +int razor_rpm_install(struct razor_rpm *rpm, const char *root);
  25.200 +int razor_rpm_close(struct razor_rpm *rpm);
  25.201 +
  25.202 +
  25.203 +/* Razor root functions. The root data struct encapsulates filesystem
  25.204 + * conventions and the locking protocol. */
  25.205 +
  25.206 +struct razor_root;
  25.207 +#define RAZOR_ROOT_OPEN_WRITE 0x01
  25.208 +
  25.209 +int razor_root_create(const char *root);
  25.210 +struct razor_root *razor_root_open(const char *root, int flags);
  25.211 +struct razor_set *razor_root_open_read_only(const char *root);
  25.212 +struct razor_transaction *
  25.213 +razor_root_create_transaction(struct razor_root *image,
  25.214 +			      struct razor_set *upstream);
  25.215 +int razor_root_close(struct razor_root *image);
  25.216 +void razor_root_update(struct razor_root *image, struct razor_set *next);
  25.217 +int razor_root_commit(struct razor_root *image);
  25.218 +void razor_root_diff(struct razor_root *root,
  25.219 +		     razor_package_callback_t callback, void *data);
  25.220 +
  25.221 +#endif /* _RAZOR_H_ */
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/librazor/root.c	Fri Jun 20 19:04:47 2008 -0400
    26.3 @@ -0,0 +1,168 @@
    26.4 +#include <stdlib.h>
    26.5 +#include <stdint.h>
    26.6 +#include <stdio.h>
    26.7 +#include <sys/stat.h>
    26.8 +#include <dirent.h>
    26.9 +#include <unistd.h>
   26.10 +#include <fcntl.h>
   26.11 +#include "razor.h"
   26.12 +#include "razor-internal.h"
   26.13 +
   26.14 +static const char system_repo_filename[] = "system.repo";
   26.15 +static const char next_repo_filename[] = "system-next.repo";
   26.16 +static const char razor_root_path[] = "/var/lib/razor";
   26.17 +
   26.18 +struct razor_root {
   26.19 +	struct razor_set *system;
   26.20 +	struct razor_set *next;
   26.21 +	int fd;
   26.22 +	char path[PATH_MAX];
   26.23 +	char new_path[PATH_MAX];
   26.24 +};
   26.25 +
   26.26 +int
   26.27 +razor_root_create(const char *root)
   26.28 +{
   26.29 +	struct stat buf;
   26.30 +	struct razor_set *set;
   26.31 +	char path[PATH_MAX];
   26.32 +
   26.33 +	if (stat(root, &buf) < 0) {
   26.34 +		if (mkdir(root, 0777) < 0) {
   26.35 +			fprintf(stderr,
   26.36 +				"could not create install root \"%s\"\n",
   26.37 +				root);
   26.38 +			return -1;
   26.39 +		}
   26.40 +		fprintf(stderr, "created install root \"%s\"\n", root);
   26.41 +	} else if (!S_ISDIR(buf.st_mode)) {
   26.42 +		fprintf(stderr,
   26.43 +			"install root \"%s\" exists, but is not a directory\n",
   26.44 +			root);
   26.45 +		return -1;
   26.46 +	}
   26.47 +
   26.48 +	snprintf(path, sizeof path, "%s/%s",
   26.49 +		 razor_root_path, system_repo_filename);
   26.50 +	if (razor_create_dir(root, path) < 0) {
   26.51 +		fprintf(stderr, "could not create %s%s\n",
   26.52 +			root, razor_root_path);
   26.53 +		return -1;
   26.54 +	}
   26.55 +
   26.56 +	set = razor_set_create();
   26.57 +	snprintf(path, sizeof path, "%s%s/%s",
   26.58 +		 root, razor_root_path, system_repo_filename);
   26.59 +	if (stat(path, &buf) == 0) {
   26.60 +		fprintf(stderr,
   26.61 +			"a razor install root is already initialized\n");
   26.62 +		return -1;
   26.63 +	}
   26.64 +	if (razor_set_write(set, path, RAZOR_REPO_FILE_MAIN) < 0) {
   26.65 +		fprintf(stderr, "could not write initial package set\n");
   26.66 +		return -1;
   26.67 +	}
   26.68 +	razor_set_destroy(set);
   26.69 +
   26.70 +	return 0;
   26.71 +}
   26.72 +
   26.73 +struct razor_root *
   26.74 +razor_root_open(const char *root, int flags)
   26.75 +{
   26.76 +	struct razor_root *image;
   26.77 +
   26.78 +	image = malloc(sizeof *image);
   26.79 +	if (image == NULL)
   26.80 +		return NULL;
   26.81 +
   26.82 +	/* Create the new next repo file up front to ensure exclusive
   26.83 +	 * access. */
   26.84 +	snprintf(image->new_path, sizeof image->new_path,
   26.85 +		 "%s%s/%s", root, razor_root_path, next_repo_filename);
   26.86 +	image->fd = open(image->new_path,
   26.87 +			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
   26.88 +	if (image->fd < 0) {
   26.89 +		fprintf(stderr, "failed to get lock file, "
   26.90 +			"maybe previous operation crashed?\n");
   26.91 +
   26.92 +		/* FIXME: Use fcntl advisory locking on the system
   26.93 +		 * package set file to figure out whether previous
   26.94 +		 * operation crashed or is still in progress. */
   26.95 +
   26.96 +		free(image);
   26.97 +		return NULL;
   26.98 +	}
   26.99 +
  26.100 +	snprintf(image->path, sizeof image->path,
  26.101 +		 "%s%s/%s", root, razor_root_path, system_repo_filename);
  26.102 +	image->system = razor_set_open(image->path);
  26.103 +	if (image->system == NULL) {
  26.104 +		unlink(image->new_path);
  26.105 +		close(image->fd);
  26.106 +		free(image);
  26.107 +		return NULL;
  26.108 +	}
  26.109 +
  26.110 +	return image;
  26.111 +}
  26.112 +
  26.113 +struct razor_set *
  26.114 +razor_root_open_read_only(const char *root)
  26.115 +{
  26.116 +	char path[PATH_MAX];
  26.117 +
  26.118 +	snprintf(path, sizeof path, "%s%s/%s",
  26.119 +		 root, razor_root_path, system_repo_filename);
  26.120 +
  26.121 +	return razor_set_open(path);
  26.122 +}
  26.123 +
  26.124 +struct razor_transaction *
  26.125 +razor_root_create_transaction(struct razor_root *image,
  26.126 +			      struct razor_set *upstream)
  26.127 +{
  26.128 +	/* FIXME: This should take a number of upstream repos. */
  26.129 +	return razor_transaction_create(image->system, upstream);
  26.130 +}
  26.131 +
  26.132 +int
  26.133 +razor_root_close(struct razor_root *image)
  26.134 +{
  26.135 +	unlink(image->new_path);
  26.136 +	close(image->fd);
  26.137 +	free(image);
  26.138 +
  26.139 +	return 0;
  26.140 +}
  26.141 +
  26.142 +void
  26.143 +razor_root_update(struct razor_root *root, struct razor_set *next)
  26.144 +{
  26.145 +	razor_set_write_to_fd(next, root->fd, RAZOR_REPO_FILE_MAIN);
  26.146 +	root->next = next;
  26.147 +
  26.148 +	/* Sync the new repo file so the new package set is on disk
  26.149 +	 * before we start upgrading. */
  26.150 +	fsync(root->fd);
  26.151 +	printf("wrote %s\n", root->new_path);
  26.152 +}
  26.153 +
  26.154 +int
  26.155 +razor_root_commit(struct razor_root *image)
  26.156 +{
  26.157 +	/* Make it so. */
  26.158 +	rename(image->new_path, image->path);
  26.159 +	printf("renamed %s to %s\n", image->new_path, image->path);
  26.160 +	close(image->fd);
  26.161 +	free(image);
  26.162 +
  26.163 +	return 0;
  26.164 +}
  26.165 +
  26.166 +void
  26.167 +razor_root_diff(struct razor_root *root,
  26.168 +		razor_package_callback_t callback, void *data)
  26.169 +{
  26.170 +	return razor_set_diff(root->system, root->next, callback, data);
  26.171 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/librazor/rpm.c	Fri Jun 20 19:04:47 2008 -0400
    27.3 @@ -0,0 +1,828 @@
    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 <stdio.h>
   27.24 +#include <stddef.h>
   27.25 +#include <stdlib.h>
   27.26 +#include <string.h>
   27.27 +#include <errno.h>
   27.28 +#include <sys/stat.h>
   27.29 +#include <sys/mman.h>
   27.30 +#include <sys/types.h>
   27.31 +#include <sys/wait.h>
   27.32 +#include <fcntl.h>
   27.33 +#include <dirent.h>
   27.34 +#include <unistd.h>
   27.35 +#include <arpa/inet.h>
   27.36 +#include <zlib.h>
   27.37 +
   27.38 +#include "razor.h"
   27.39 +#include "razor-internal.h"
   27.40 +
   27.41 +#define	RPM_LEAD_SIZE 96
   27.42 +
   27.43 +enum {
   27.44 +    PIPE	=  1,	/*!< pipe/fifo */
   27.45 +    CDEV	=  2,	/*!< character device */
   27.46 +    XDIR	=  4,	/*!< directory */
   27.47 +    BDEV	=  6,	/*!< block device */
   27.48 +    REG		=  8,	/*!< regular file */
   27.49 +    LINK	= 10,	/*!< hard link */
   27.50 +    SOCK	= 12	/*!< socket */
   27.51 +};
   27.52 +
   27.53 +enum {
   27.54 +    RPMSENSE_LESS		= 1 << 1,
   27.55 +    RPMSENSE_GREATER		= 1 << 2,
   27.56 +    RPMSENSE_EQUAL		= 1 << 3,
   27.57 +    RPMSENSE_PREREQ		= 1 << 6,
   27.58 +    RPMSENSE_SCRIPT_PRE		= 1 << 9,
   27.59 +    RPMSENSE_SCRIPT_POST	= 1 << 10,
   27.60 +    RPMSENSE_SCRIPT_PREUN	= 1 << 11,
   27.61 +    RPMSENSE_SCRIPT_POSTUN	= 1 << 12,
   27.62 +};
   27.63 +
   27.64 +enum {
   27.65 +    RPMTAG_NAME  		= 1000,	/* s */
   27.66 +    RPMTAG_VERSION		= 1001,	/* s */
   27.67 +    RPMTAG_RELEASE		= 1002,	/* s */
   27.68 +    RPMTAG_EPOCH   		= 1003,	/* i */
   27.69 +    RPMTAG_SUMMARY		= 1004,	/* s{} */
   27.70 +    RPMTAG_DESCRIPTION		= 1005,	/* s{} */
   27.71 +    RPMTAG_BUILDTIME		= 1006,	/* i */
   27.72 +    RPMTAG_BUILDHOST		= 1007,	/* s */
   27.73 +    RPMTAG_INSTALLTIME		= 1008,	/* i */
   27.74 +    RPMTAG_SIZE			= 1009,	/* i */
   27.75 +    RPMTAG_DISTRIBUTION		= 1010,	/* s */
   27.76 +    RPMTAG_VENDOR		= 1011,	/* s */
   27.77 +    RPMTAG_GIF			= 1012,	/* x */
   27.78 +    RPMTAG_XPM			= 1013,	/* x */
   27.79 +    RPMTAG_LICENSE		= 1014,	/* s */
   27.80 +    RPMTAG_PACKAGER		= 1015,	/* s */
   27.81 +    RPMTAG_GROUP		= 1016,	/* s{} */
   27.82 +    RPMTAG_CHANGELOG		= 1017, /*!< s[] internal */
   27.83 +    RPMTAG_SOURCE		= 1018,	/* s[] */
   27.84 +    RPMTAG_PATCH		= 1019,	/* s[] */
   27.85 +    RPMTAG_URL			= 1020,	/* s */
   27.86 +    RPMTAG_OS			= 1021,	/* s legacy used int */
   27.87 +    RPMTAG_ARCH			= 1022,	/* s legacy used int */
   27.88 +    RPMTAG_PREIN		= 1023,	/* s */
   27.89 +    RPMTAG_POSTIN		= 1024,	/* s */
   27.90 +    RPMTAG_PREUN		= 1025,	/* s */
   27.91 +    RPMTAG_POSTUN		= 1026,	/* s */
   27.92 +    RPMTAG_OLDFILENAMES		= 1027, /* s[] obsolete */
   27.93 +    RPMTAG_FILESIZES		= 1028,	/* i */
   27.94 +    RPMTAG_FILESTATES		= 1029, /* c */
   27.95 +    RPMTAG_FILEMODES		= 1030,	/* h */
   27.96 +    RPMTAG_FILEUIDS		= 1031, /*!< internal */
   27.97 +    RPMTAG_FILEGIDS		= 1032, /*!< internal */
   27.98 +    RPMTAG_FILERDEVS		= 1033,	/* h */
   27.99 +    RPMTAG_FILEMTIMES		= 1034, /* i */
  27.100 +    RPMTAG_FILEMD5S		= 1035,	/* s[] */
  27.101 +    RPMTAG_FILELINKTOS		= 1036,	/* s[] */
  27.102 +    RPMTAG_FILEFLAGS		= 1037,	/* i */
  27.103 +    RPMTAG_ROOT			= 1038, /*!< internal - obsolete */
  27.104 +    RPMTAG_FILEUSERNAME		= 1039,	/* s[] */
  27.105 +    RPMTAG_FILEGROUPNAME	= 1040,	/* s[] */
  27.106 +    RPMTAG_EXCLUDE		= 1041, /*!< internal - obsolete */
  27.107 +    RPMTAG_EXCLUSIVE		= 1042, /*!< internal - obsolete */
  27.108 +    RPMTAG_ICON			= 1043,
  27.109 +    RPMTAG_SOURCERPM		= 1044,	/* s */
  27.110 +    RPMTAG_FILEVERIFYFLAGS	= 1045,	/* i */
  27.111 +    RPMTAG_ARCHIVESIZE		= 1046,	/* i */
  27.112 +    RPMTAG_PROVIDENAME		= 1047,	/* s[] */
  27.113 +    RPMTAG_REQUIREFLAGS		= 1048,	/* i */
  27.114 +    RPMTAG_REQUIRENAME		= 1049,	/* s[] */
  27.115 +    RPMTAG_REQUIREVERSION	= 1050,	/* s[] */
  27.116 +    RPMTAG_NOSOURCE		= 1051, /*!< internal */
  27.117 +    RPMTAG_NOPATCH		= 1052, /*!< internal */
  27.118 +    RPMTAG_CONFLICTFLAGS	= 1053, /* i */
  27.119 +    RPMTAG_CONFLICTNAME		= 1054,	/* s[] */
  27.120 +    RPMTAG_CONFLICTVERSION	= 1055,	/* s[] */
  27.121 +    RPMTAG_DEFAULTPREFIX	= 1056, /*!< internal - deprecated */
  27.122 +    RPMTAG_BUILDROOT		= 1057, /*!< internal */
  27.123 +    RPMTAG_INSTALLPREFIX	= 1058, /*!< internal - deprecated */
  27.124 +    RPMTAG_EXCLUDEARCH		= 1059,
  27.125 +    RPMTAG_EXCLUDEOS		= 1060,
  27.126 +    RPMTAG_EXCLUSIVEARCH	= 1061,
  27.127 +    RPMTAG_EXCLUSIVEOS		= 1062,
  27.128 +    RPMTAG_AUTOREQPROV		= 1063, /*!< internal */
  27.129 +    RPMTAG_RPMVERSION		= 1064,	/* s */
  27.130 +    RPMTAG_TRIGGERSCRIPTS	= 1065,	/* s[] */
  27.131 +    RPMTAG_TRIGGERNAME		= 1066,	/* s[] */
  27.132 +    RPMTAG_TRIGGERVERSION	= 1067,	/* s[] */
  27.133 +    RPMTAG_TRIGGERFLAGS		= 1068,	/* i */
  27.134 +    RPMTAG_TRIGGERINDEX		= 1069,	/* i */
  27.135 +    RPMTAG_VERIFYSCRIPT		= 1079,	/* s */
  27.136 +    RPMTAG_CHANGELOGTIME	= 1080,	/* i */
  27.137 +    RPMTAG_CHANGELOGNAME	= 1081,	/* s[] */
  27.138 +    RPMTAG_CHANGELOGTEXT	= 1082,	/* s[] */
  27.139 +    RPMTAG_BROKENMD5		= 1083, /*!< internal - obsolete */
  27.140 +    RPMTAG_PREREQ		= 1084, /*!< internal */
  27.141 +    RPMTAG_PREINPROG		= 1085,	/* s */
  27.142 +    RPMTAG_POSTINPROG		= 1086,	/* s */
  27.143 +    RPMTAG_PREUNPROG		= 1087,	/* s */
  27.144 +    RPMTAG_POSTUNPROG		= 1088,	/* s */
  27.145 +    RPMTAG_BUILDARCHS		= 1089,
  27.146 +    RPMTAG_OBSOLETENAME		= 1090,	/* s[] */
  27.147 +    RPMTAG_VERIFYSCRIPTPROG	= 1091,	/* s */
  27.148 +    RPMTAG_TRIGGERSCRIPTPROG	= 1092,	/* s */
  27.149 +    RPMTAG_DOCDIR		= 1093, /*!< internal */
  27.150 +    RPMTAG_COOKIE		= 1094,	/* s */
  27.151 +    RPMTAG_FILEDEVICES		= 1095,	/* i */
  27.152 +    RPMTAG_FILEINODES		= 1096,	/* i */
  27.153 +    RPMTAG_FILELANGS		= 1097,	/* s[] */
  27.154 +    RPMTAG_PREFIXES		= 1098,	/* s[] */
  27.155 +    RPMTAG_INSTPREFIXES		= 1099,	/* s[] */
  27.156 +    RPMTAG_TRIGGERIN		= 1100, /*!< internal */
  27.157 +    RPMTAG_TRIGGERUN		= 1101, /*!< internal */
  27.158 +    RPMTAG_TRIGGERPOSTUN	= 1102, /*!< internal */
  27.159 +    RPMTAG_AUTOREQ		= 1103, /*!< internal */
  27.160 +    RPMTAG_AUTOPROV		= 1104, /*!< internal */
  27.161 +    RPMTAG_CAPABILITY		= 1105, /*!< internal - obsolete */
  27.162 +    RPMTAG_SOURCEPACKAGE	= 1106, /*!< i src.rpm header marker */
  27.163 +    RPMTAG_OLDORIGFILENAMES	= 1107, /*!< internal - obsolete */
  27.164 +    RPMTAG_BUILDPREREQ		= 1108, /*!< internal */
  27.165 +    RPMTAG_BUILDREQUIRES	= 1109, /*!< internal */
  27.166 +    RPMTAG_BUILDCONFLICTS	= 1110, /*!< internal */
  27.167 +    RPMTAG_BUILDMACROS		= 1111, /*!< internal - unused */
  27.168 +    RPMTAG_PROVIDEFLAGS		= 1112,	/* i */
  27.169 +    RPMTAG_PROVIDEVERSION	= 1113,	/* s[] */
  27.170 +    RPMTAG_OBSOLETEFLAGS	= 1114,	/* i */
  27.171 +    RPMTAG_OBSOLETEVERSION	= 1115,	/* s[] */
  27.172 +    RPMTAG_DIRINDEXES		= 1116,	/* i */
  27.173 +    RPMTAG_BASENAMES		= 1117,	/* s[] */
  27.174 +    RPMTAG_DIRNAMES		= 1118,	/* s[] */
  27.175 +    RPMTAG_ORIGDIRINDEXES	= 1119, /*!< internal */
  27.176 +    RPMTAG_ORIGBASENAMES	= 1120, /*!< internal */
  27.177 +    RPMTAG_ORIGDIRNAMES		= 1121, /*!< internal */
  27.178 +    RPMTAG_OPTFLAGS		= 1122,	/* s */
  27.179 +    RPMTAG_DISTURL		= 1123,	/* s */
  27.180 +    RPMTAG_PAYLOADFORMAT	= 1124,	/* s */
  27.181 +    RPMTAG_PAYLOADCOMPRESSOR	= 1125,	/* s */
  27.182 +    RPMTAG_PAYLOADFLAGS		= 1126,	/* s */
  27.183 +    RPMTAG_INSTALLCOLOR		= 1127, /*!< i transaction color when installed */
  27.184 +    RPMTAG_INSTALLTID		= 1128,	/* i */
  27.185 +    RPMTAG_REMOVETID		= 1129,	/* i */
  27.186 +    RPMTAG_SHA1RHN		= 1130, /*!< internal - obsolete */
  27.187 +    RPMTAG_RHNPLATFORM		= 1131,	/* s */
  27.188 +    RPMTAG_PLATFORM		= 1132,	/* s */
  27.189 +    RPMTAG_PATCHESNAME		= 1133, /*!< placeholder (SuSE) */
  27.190 +    RPMTAG_PATCHESFLAGS		= 1134, /*!< placeholder (SuSE) */
  27.191 +    RPMTAG_PATCHESVERSION	= 1135, /*!< placeholder (SuSE) */
  27.192 +    RPMTAG_CACHECTIME		= 1136,	/* i */
  27.193 +    RPMTAG_CACHEPKGPATH		= 1137,	/* s */
  27.194 +    RPMTAG_CACHEPKGSIZE		= 1138,	/* i */
  27.195 +    RPMTAG_CACHEPKGMTIME	= 1139,	/* i */
  27.196 +    RPMTAG_FILECOLORS		= 1140,	/* i */
  27.197 +    RPMTAG_FILECLASS		= 1141,	/* i */
  27.198 +    RPMTAG_CLASSDICT		= 1142,	/* s[] */
  27.199 +    RPMTAG_FILEDEPENDSX		= 1143,	/* i */
  27.200 +    RPMTAG_FILEDEPENDSN		= 1144,	/* i */
  27.201 +    RPMTAG_DEPENDSDICT		= 1145,	/* i */
  27.202 +    RPMTAG_SOURCEPKGID		= 1146,	/* x */
  27.203 +    RPMTAG_FILECONTEXTS		= 1147,	/* s[] */
  27.204 +    RPMTAG_FSCONTEXTS		= 1148,	/*!< s[] extension */
  27.205 +    RPMTAG_RECONTEXTS		= 1149,	/*!< s[] extension */
  27.206 +    RPMTAG_POLICIES		= 1150,	/*!< s[] selinux *.te policy file. */
  27.207 +    RPMTAG_PRETRANS		= 1151,	/* s */
  27.208 +    RPMTAG_POSTTRANS		= 1152,	/* s */
  27.209 +    RPMTAG_PRETRANSPROG		= 1153,	/* s */
  27.210 +    RPMTAG_POSTTRANSPROG	= 1154,	/* s */
  27.211 +    RPMTAG_DISTTAG		= 1155,	/* s */
  27.212 +    RPMTAG_SUGGESTSNAME		= 1156,	/* s[] extension placeholder */
  27.213 +    RPMTAG_SUGGESTSVERSION	= 1157,	/* s[] extension placeholder */
  27.214 +    RPMTAG_SUGGESTSFLAGS	= 1158,	/* i   extension placeholder */
  27.215 +    RPMTAG_ENHANCESNAME		= 1159,	/* s[] extension placeholder */
  27.216 +    RPMTAG_ENHANCESVERSION	= 1160,	/* s[] extension placeholder */
  27.217 +    RPMTAG_ENHANCESFLAGS	= 1161,	/* i   extension placeholder */
  27.218 +    RPMTAG_PRIORITY		= 1162, /* i   extension placeholder */
  27.219 +    RPMTAG_CVSID		= 1163, /* s */
  27.220 +    RPMTAG_TRIGGERPREIN		= 1171, /*!< internal */
  27.221 +};
  27.222 +
  27.223 +struct rpm_header {
  27.224 +	unsigned char magic[4];
  27.225 +	unsigned char reserved[4];
  27.226 +	int nindex;
  27.227 +	int hsize;
  27.228 +};
  27.229 +
  27.230 +struct rpm_header_index {
  27.231 +	int tag;
  27.232 +	int type;
  27.233 +	int offset;
  27.234 +	int count;
  27.235 +};
  27.236 +
  27.237 +struct razor_rpm {
  27.238 +	struct rpm_header *signature;
  27.239 +	struct rpm_header *header;
  27.240 +	const char **dirs;
  27.241 +	const char *pool;
  27.242 +	void *map;
  27.243 +	size_t size;
  27.244 +	void *payload;
  27.245 +};
  27.246 +
  27.247 +static struct rpm_header_index *
  27.248 +razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
  27.249 +{
  27.250 +	struct rpm_header_index *index, *end;
  27.251 +
  27.252 +	index = (struct rpm_header_index *) (rpm->header + 1);
  27.253 +	end = index + ntohl(rpm->header->nindex);
  27.254 +	while (index < end) {
  27.255 +		if (ntohl(index->tag) == tag)
  27.256 +			return index;
  27.257 +		index++;
  27.258 +	}
  27.259 +
  27.260 +	return NULL;
  27.261 +}
  27.262 +
  27.263 +static const void *
  27.264 +razor_rpm_get_indirect(struct razor_rpm *rpm,
  27.265 +		       unsigned int tag, unsigned int *count)
  27.266 +{
  27.267 +	struct rpm_header_index *index;
  27.268 +
  27.269 +	index = razor_rpm_get_header(rpm, tag);
  27.270 +	if (index != NULL) {
  27.271 +		if (count)
  27.272 +			*count = ntohl(index->count);
  27.273 +
  27.274 +		return rpm->pool + ntohl(index->offset);
  27.275 +	}
  27.276 +
  27.277 +	return NULL;
  27.278 +}
  27.279 +
  27.280 +static uint32_t
  27.281 +rpm_to_razor_flags(uint32_t flags)
  27.282 +{
  27.283 +	uint32_t razor_flags;
  27.284 +
  27.285 +	razor_flags = 0;
  27.286 +	if (flags & RPMSENSE_LESS)
  27.287 +		razor_flags |= RAZOR_PROPERTY_LESS;
  27.288 +	if (flags & RPMSENSE_EQUAL)
  27.289 +		razor_flags |= RAZOR_PROPERTY_EQUAL;
  27.290 +	if (flags & RPMSENSE_GREATER)
  27.291 +		razor_flags |= RAZOR_PROPERTY_GREATER;
  27.292 +
  27.293 +	if (flags & RPMSENSE_SCRIPT_PRE)
  27.294 +		razor_flags |= RAZOR_PROPERTY_PRE;
  27.295 +	if (flags & RPMSENSE_SCRIPT_POST)
  27.296 +		razor_flags |= RAZOR_PROPERTY_POST;
  27.297 +	if (flags & RPMSENSE_SCRIPT_PREUN)
  27.298 +		razor_flags |= RAZOR_PROPERTY_PREUN;
  27.299 +	if (flags & RPMSENSE_SCRIPT_POSTUN)
  27.300 +		razor_flags |= RAZOR_PROPERTY_POSTUN;
  27.301 +	
  27.302 +	return razor_flags;
  27.303 +}
  27.304 +
  27.305 +static void
  27.306 +import_properties(struct razor_importer *importer, uint32_t type,
  27.307 +		  struct razor_rpm *rpm,
  27.308 +		  int name_tag, int version_tag, int flags_tag)
  27.309 +{
  27.310 +	const char *name, *version;
  27.311 +	const uint32_t *flags;
  27.312 +	uint32_t f;
  27.313 +	unsigned int i, count;
  27.314 +
  27.315 +	name = razor_rpm_get_indirect(rpm, name_tag, &count);
  27.316 +	if (name == NULL)
  27.317 +		return;
  27.318 +
  27.319 +	flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
  27.320 +
  27.321 +	version = razor_rpm_get_indirect(rpm, version_tag, &count);
  27.322 +	for (i = 0; i < count; i++) {
  27.323 +		f = rpm_to_razor_flags(ntohl(flags[i]));
  27.324 +		razor_importer_add_property(importer, name, f | type, version);
  27.325 +		name += strlen(name) + 1;
  27.326 +		version += strlen(version) + 1;
  27.327 +	}
  27.328 +}
  27.329 +
  27.330 +static void
  27.331 +import_files(struct razor_importer *importer, struct razor_rpm *rpm)
  27.332 +{
  27.333 +	const char *name;
  27.334 +	const uint32_t *index;
  27.335 +	unsigned int i, count;
  27.336 +	char buffer[256];
  27.337 +
  27.338 +	if (rpm->dirs == NULL)
  27.339 +		return;
  27.340 +
  27.341 +	/* assert: count is the same for all arrays */
  27.342 +	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
  27.343 +	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
  27.344 +	for (i = 0; i < count; i++) {
  27.345 +		snprintf(buffer, sizeof buffer,
  27.346 +			 "%s%s", rpm->dirs[ntohl(*index)], name);
  27.347 +		razor_importer_add_file(importer, buffer);
  27.348 +		name += strlen(name) + 1;
  27.349 +		index++;
  27.350 +	}
  27.351 +}
  27.352 +
  27.353 +struct razor_rpm *
  27.354 +razor_rpm_open(const char *filename)
  27.355 +{
  27.356 +	struct razor_rpm *rpm;
  27.357 +	struct rpm_header_index *base, *index;
  27.358 +	struct stat buf;
  27.359 +	unsigned int count, i, nindex, hsize;
  27.360 +	const char *name;
  27.361 +	int fd;
  27.362 +
  27.363 +	rpm = malloc(sizeof *rpm);
  27.364 +	if (rpm == NULL)
  27.365 +		return NULL;
  27.366 +	memset(rpm, 0, sizeof *rpm);
  27.367 +
  27.368 +	fd = open(filename, O_RDONLY);
  27.369 +	if (fd < 0) {
  27.370 +		fprintf(stderr, "couldn't open %s\n", filename);
  27.371 +		return NULL;
  27.372 +	}
  27.373 +
  27.374 +	if (fstat(fd, &buf) < 0) {
  27.375 +		fprintf(stderr, "failed to stat %s (%m)\n", filename);
  27.376 +		return NULL;
  27.377 +	}
  27.378 +
  27.379 +	rpm->size = buf.st_size;
  27.380 +	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
  27.381 +	if (rpm->map == MAP_FAILED) {
  27.382 +		fprintf(stderr, "couldn't mmap %s\n", filename);
  27.383 +		return NULL;
  27.384 +	}
  27.385 +	close(fd);
  27.386 +
  27.387 +	rpm->signature = rpm->map + RPM_LEAD_SIZE;
  27.388 +	nindex = ntohl(rpm->signature->nindex);
  27.389 +	hsize = ntohl(rpm->signature->hsize);
  27.390 +	rpm->header = (void *) (rpm->signature + 1) +
  27.391 +		ALIGN(nindex * sizeof *index + hsize, 8);
  27.392 +	nindex = ntohl(rpm->header->nindex);
  27.393 +	hsize = ntohl(rpm->header->hsize);
  27.394 +	rpm->payload = (void *) (rpm->header + 1) +
  27.395 +		nindex * sizeof *index + hsize;
  27.396 +
  27.397 +	base = (struct rpm_header_index *) (rpm->header + 1);
  27.398 +	rpm->pool = (void *) base + nindex * sizeof *index;
  27.399 +
  27.400 +	/* Look up dir names now so we can index them directly. */
  27.401 +	name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
  27.402 +	if (name) {
  27.403 +		rpm->dirs = calloc(count, sizeof *rpm->dirs);
  27.404 +		for (i = 0; i < count; i++) {
  27.405 +			rpm->dirs[i] = name;
  27.406 +			name += strlen(name) + 1;
  27.407 +		}
  27.408 +	} else {
  27.409 +		name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
  27.410 +					      &count);
  27.411 +		if (name) {
  27.412 +			fprintf(stderr, "old filenames not supported\n");
  27.413 +			return NULL;
  27.414 +		}
  27.415 +	}
  27.416 +
  27.417 +	return rpm;
  27.418 +}
  27.419 +
  27.420 +struct cpio_file_header {
  27.421 +	char magic[6];
  27.422 +	char inode[8];
  27.423 +	char mode[8];
  27.424 +	char uid[8];
  27.425 +	char gid[8];
  27.426 +	char nlink[8];
  27.427 +	char mtime[8];
  27.428 +	char filesize[8];
  27.429 +	char devmajor[8];
  27.430 +	char devminor[8];
  27.431 +	char rdevmajor[8];
  27.432 +	char rdevminor[8];
  27.433 +	char namesize[8];
  27.434 +	char checksum[8];
  27.435 +	char filename[0];
  27.436 +};
  27.437 +
  27.438 +/* gzip flags */
  27.439 +#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
  27.440 +#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
  27.441 +#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  27.442 +#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  27.443 +#define COMMENT      0x10 /* bit 4 set: file comment present */
  27.444 +#define RESERVED     0xE0 /* bits 5..7: reserved */
  27.445 +
  27.446 +struct installer {
  27.447 +	const char *root;
  27.448 +	struct razor_rpm *rpm;
  27.449 +	z_stream stream;
  27.450 +	unsigned char buffer[32768];
  27.451 +	size_t rest, length;
  27.452 +};
  27.453 +
  27.454 +static int
  27.455 +installer_inflate(struct installer *installer)
  27.456 +{
  27.457 +	size_t length;
  27.458 +	int err;
  27.459 +
  27.460 +	if (installer->rest > sizeof installer->buffer)
  27.461 +		length = sizeof installer->buffer;
  27.462 +	else
  27.463 +		length = installer->rest;
  27.464 +
  27.465 +	installer->stream.next_out = installer->buffer;
  27.466 +	installer->stream.avail_out = length;
  27.467 +	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  27.468 +	if (err != Z_OK && err != Z_STREAM_END) {
  27.469 +		fprintf(stderr, "inflate error: %d (%m)\n", err);
  27.470 +		return -1;
  27.471 +	}
  27.472 +
  27.473 +	installer->rest -= length;
  27.474 +	installer->length = length;
  27.475 +
  27.476 +	return 0;
  27.477 +}
  27.478 +
  27.479 +static int
  27.480 +installer_align(struct installer *installer, size_t size)
  27.481 +{
  27.482 +	unsigned char buffer[4];
  27.483 +	int err;
  27.484 +
  27.485 +	installer->stream.next_out = buffer;
  27.486 +	installer->stream.avail_out =
  27.487 +		(size - installer->stream.total_out) & (size - 1);
  27.488 +
  27.489 +	if (installer->stream.avail_out == 0)
  27.490 +		return 0;
  27.491 +
  27.492 +	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  27.493 +	if (err != Z_OK && err != Z_STREAM_END) {
  27.494 +		fprintf(stderr, "inflate error: %d (%m)\n", err);
  27.495 +		return -1;
  27.496 +	}
  27.497 +
  27.498 +	return 0;
  27.499 +}
  27.500 +
  27.501 +static int
  27.502 +create_path(struct installer *installer, const char *path, unsigned int mode)
  27.503 +{
  27.504 +	char buffer[PATH_MAX];
  27.505 +	struct stat buf;
  27.506 +	int fd, ret;
  27.507 +
  27.508 +	if (razor_create_dir(installer->root, path) < 0)
  27.509 +		return -1;
  27.510 +
  27.511 +	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
  27.512 +
  27.513 +	switch (mode >> 12) {
  27.514 +	case REG:
  27.515 +		/* FIXME: handle the case where a file is already there. */
  27.516 +		fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, mode & 0x1ff);
  27.517 +		if (fd < 0){
  27.518 +			fprintf(stderr, "failed to create file %s\n", buffer);
  27.519 +			return -1;
  27.520 +		}
  27.521 +		while (installer->rest > 0) {
  27.522 +			if (installer_inflate(installer)) {
  27.523 +				fprintf(stderr, "failed to inflate\n");
  27.524 +				return -1;
  27.525 +			}
  27.526 +			if (razor_write(fd, installer->buffer,
  27.527 +					installer->length)) {
  27.528 +				fprintf(stderr, "failed to write payload\n");
  27.529 +				return -1;
  27.530 +			}
  27.531 +		}
  27.532 +		if (close(fd) < 0) {
  27.533 +			fprintf(stderr, "failed to close %s: %m\n", buffer);
  27.534 +			return -1;
  27.535 +		}
  27.536 +		return 0;
  27.537 +	case XDIR:
  27.538 +		ret = mkdir(buffer, mode & 0x1ff);
  27.539 +		if (ret == 0 || errno != EEXIST)
  27.540 +			return ret;
  27.541 +		if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
  27.542 +			/* FIXME: also check that mode match. */
  27.543 +			fprintf(stderr,
  27.544 +				"%s exists but is not a directory\n", buffer);
  27.545 +			return -1;
  27.546 +		}
  27.547 +		return 0;
  27.548 +	case PIPE:
  27.549 +	case CDEV:
  27.550 +	case BDEV:
  27.551 +	case SOCK:
  27.552 +		printf("%s: unhandled file type %d\n", buffer, mode >> 12);
  27.553 +		return 0;
  27.554 +	case LINK:
  27.555 +		if (installer_inflate(installer)) {
  27.556 +			fprintf(stderr, "failed to inflate\n");
  27.557 +			return -1;
  27.558 +		}
  27.559 +		if (installer->length >= sizeof installer->buffer) {
  27.560 +			fprintf(stderr, "link name too long\n");
  27.561 +			return -1;
  27.562 +		}
  27.563 +		installer->buffer[installer->length] = '\0';
  27.564 +		if (symlink((const char *) installer->buffer, buffer)) {
  27.565 +			fprintf(stderr, "failed to create symlink, %m\n");
  27.566 +			return -1;
  27.567 +		}
  27.568 +		return 0;
  27.569 +	default:
  27.570 +		printf("%s: unknown file type %d\n", buffer, mode >> 12);
  27.571 +		return 0;
  27.572 +	}
  27.573 +}
  27.574 +
  27.575 +static int
  27.576 +run_script(struct installer *installer,
  27.577 +	   unsigned int program_tag, unsigned int script_tag)
  27.578 +{
  27.579 +	int pid, status, fd[2];
  27.580 +	const char *script = NULL, *program = NULL;
  27.581 +
  27.582 +	program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
  27.583 +	script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
  27.584 +	if (program == NULL && script == NULL) {
  27.585 +		return 0;
  27.586 +	} else if (program == NULL) {
  27.587 +		program = "/bin/sh";
  27.588 +	}
  27.589 +
  27.590 +	if (pipe(fd) < 0) {
  27.591 +		fprintf(stderr, "failed to create pipe\n");
  27.592 +		return -1;
  27.593 +	}
  27.594 +	pid = fork();
  27.595 +	if (pid < 0) {
  27.596 +		fprintf(stderr, "failed to fork, %m\n");
  27.597 +	} else if (pid == 0) {
  27.598 +		if (dup2(fd[0], STDIN_FILENO) < 0) {
  27.599 +			fprintf(stderr, "failed redirect stdin, %m\n");
  27.600 +			return -1;
  27.601 +		}
  27.602 +		if (close(fd[0]) < 0 || close(fd[1]) < 0) {
  27.603 +			fprintf(stderr, "failed to close pipe, %m\n");
  27.604 +			return -1;
  27.605 +		}
  27.606 +		if (chroot(installer->root) < 0) {
  27.607 +			fprintf(stderr, "failed to chroot to %s, %m\n",
  27.608 +				installer->root);
  27.609 +			return -1;
  27.610 +		}
  27.611 +		printf("executing program %s in chroot %s\n",
  27.612 +		       program, installer->root);
  27.613 +		if (execl(program, program, NULL)) {
  27.614 +			fprintf(stderr, "failed to exec %s, %m\n", program);
  27.615 +			exit(-1);
  27.616 +		}
  27.617 +	} else {
  27.618 +		if (script && razor_write(fd[1], script, strlen(script)) < 0) {
  27.619 +			fprintf(stderr, "failed to pipe script, %m\n");
  27.620 +			return -1;
  27.621 +		}
  27.622 +		if (close(fd[0]) || close(fd[1])) {
  27.623 +			fprintf(stderr, "failed to close pipe, %m\n");
  27.624 +			return -1;
  27.625 +		}
  27.626 +		if (wait(&status) < 0) {
  27.627 +			fprintf(stderr, "wait for child failed, %m");
  27.628 +			return -1;
  27.629 +		}
  27.630 +		if (status)
  27.631 +			printf("script exited with status %d\n", status);
  27.632 +	}
  27.633 +
  27.634 +	return 0;
  27.635 +}
  27.636 +
  27.637 +static int
  27.638 +installer_init(struct installer *installer)
  27.639 +{
  27.640 +	unsigned char *gz_header;
  27.641 +	int method, flags, err;
  27.642 +
  27.643 +	gz_header = installer->rpm->payload;
  27.644 +	if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
  27.645 +		fprintf(stderr, "payload section doesn't have gz header\n");
  27.646 +		return -1;
  27.647 +	}
  27.648 +
  27.649 +	method = gz_header[2];
  27.650 +	flags = gz_header[3];
  27.651 +
  27.652 +	if (method != Z_DEFLATED || flags != 0) {
  27.653 +		fprintf(stderr,
  27.654 +			"unknown payload compression method or flags set\n");
  27.655 +		return -1;
  27.656 +	}
  27.657 +
  27.658 +	installer->stream.zalloc = NULL;
  27.659 +	installer->stream.zfree = NULL;
  27.660 +	installer->stream.opaque = NULL;
  27.661 +
  27.662 +	installer->stream.next_in  = gz_header + 10;
  27.663 +	installer->stream.avail_in =
  27.664 +		(installer->rpm->map + installer->rpm->size) -
  27.665 +		(void *) installer->stream.next_in;
  27.666 +	installer->stream.next_out = NULL;
  27.667 +	installer->stream.avail_out = 0;
  27.668 +
  27.669 +	err = inflateInit2(&installer->stream, -MAX_WBITS);
  27.670 +	if (err != Z_OK) {
  27.671 +		fprintf(stderr, "inflateInit error: %d\n", err);
  27.672 +		return -1;
  27.673 +	}
  27.674 +
  27.675 +	return 0;
  27.676 +}
  27.677 +
  27.678 +static int
  27.679 +installer_finish(struct installer *installer)
  27.680 +{
  27.681 +	int err;
  27.682 +
  27.683 +	err = inflateEnd(&installer->stream);
  27.684 +
  27.685 +	if (err != Z_OK) {
  27.686 +		fprintf(stderr, "inflateEnd error: %d\n", err);
  27.687 +		return -1;
  27.688 +	}
  27.689 +
  27.690 +	return 0;
  27.691 +}
  27.692 +
  27.693 +static unsigned long
  27.694 +fixed_hex_to_ulong(const char *hex, int length)
  27.695 +{
  27.696 +	long l;
  27.697 +	int i;
  27.698 +
  27.699 +	for (i = 0, l = 0; i < length; i++) {
  27.700 +		if (hex[i] < 'a')
  27.701 +			l = l * 16 + hex[i] - '0';
  27.702 +		else
  27.703 +			l = l * 16 + hex[i] - 'a' + 10;
  27.704 +	}
  27.705 +
  27.706 +	return l;
  27.707 +}
  27.708 +
  27.709 +int
  27.710 +razor_rpm_install(struct razor_rpm *rpm, const char *root)
  27.711 +{
  27.712 +	struct installer installer;
  27.713 +	struct cpio_file_header *header;
  27.714 +	struct stat buf;
  27.715 +	unsigned int mode;
  27.716 +	char *path;
  27.717 +	size_t filesize;
  27.718 +
  27.719 +	installer.rpm = rpm;
  27.720 +	installer.root = root;
  27.721 +
  27.722 +	/* FIXME: Only do this before a transaction, not per rpm. */
  27.723 +	if (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
  27.724 +		fprintf(stderr,
  27.725 +			"root installation directory \"%s\" does not exist\n",
  27.726 +			root);
  27.727 +		return -1;
  27.728 +	}
  27.729 +
  27.730 +	if (installer_init(&installer))
  27.731 +		return -1;
  27.732 +
  27.733 +	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
  27.734 +
  27.735 +	while (installer.stream.avail_in > 0) {
  27.736 +		installer.rest = sizeof *header;
  27.737 +		if (installer_inflate(&installer))
  27.738 +			return -1;
  27.739 +
  27.740 +		header = (struct cpio_file_header *) installer.buffer;
  27.741 +		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
  27.742 +		filesize = fixed_hex_to_ulong(header->filesize,
  27.743 +					      sizeof header->filesize);
  27.744 +
  27.745 +		installer.rest = fixed_hex_to_ulong(header->namesize,
  27.746 +						    sizeof header->namesize);
  27.747 +
  27.748 +		if (installer_inflate(&installer) ||
  27.749 +		    installer_align(&installer, 4))
  27.750 +			return -1;
  27.751 +
  27.752 +		path = (char *) installer.buffer;
  27.753 +		/* This convention is so lame... */
  27.754 +		if (strcmp(path, "TRAILER!!!") == 0)
  27.755 +			break;
  27.756 +
  27.757 +		installer.rest = filesize;
  27.758 +		if (create_path(&installer, path + 1, mode) < 0)
  27.759 +			return -1;
  27.760 +		if (installer_align(&installer, 4))
  27.761 +			return -1;
  27.762 +	}
  27.763 +
  27.764 +	if (installer_finish(&installer))
  27.765 +		return -1;
  27.766 +
  27.767 +	run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
  27.768 +
  27.769 +	return 0;
  27.770 +}
  27.771 +
  27.772 +int
  27.773 +razor_rpm_close(struct razor_rpm *rpm)
  27.774 +{
  27.775 +	int err;
  27.776 +
  27.777 +	free(rpm->dirs);
  27.778 +	err = munmap(rpm->map, rpm->size);
  27.779 +	free(rpm);
  27.780 +
  27.781 +	return err;
  27.782 +}
  27.783 +
  27.784 +int
  27.785 +razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
  27.786 +{
  27.787 +	const char *name, *version, *release, *arch, *summary;
  27.788 +	const uint32_t *epoch;
  27.789 +	char evr[128], buf[16];
  27.790 +
  27.791 +	name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
  27.792 +	epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
  27.793 +	version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
  27.794 +	release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
  27.795 +	arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
  27.796 +	summary = razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
  27.797 +
  27.798 +	if (epoch) {
  27.799 +		snprintf(buf, sizeof buf, "%u", ntohl(*epoch));
  27.800 +		razor_build_evr(evr, sizeof evr, buf, version, release);
  27.801 +	} else {
  27.802 +		razor_build_evr(evr, sizeof evr, NULL, version, release);
  27.803 +	}
  27.804 +	razor_importer_begin_package(importer, name, evr, arch);
  27.805 +
  27.806 +	import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
  27.807 +			  RPMTAG_REQUIRENAME,
  27.808 +			  RPMTAG_REQUIREVERSION,
  27.809 +			  RPMTAG_REQUIREFLAGS);
  27.810 +
  27.811 +	import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
  27.812 +			  RPMTAG_PROVIDENAME,
  27.813 +			  RPMTAG_PROVIDEVERSION,
  27.814 +			  RPMTAG_PROVIDEFLAGS);
  27.815 +
  27.816 +	import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
  27.817 +			  RPMTAG_OBSOLETENAME,
  27.818 +			  RPMTAG_OBSOLETEVERSION,
  27.819 +			  RPMTAG_OBSOLETEFLAGS);
  27.820 +
  27.821 +	import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
  27.822 +			  RPMTAG_CONFLICTNAME,
  27.823 +			  RPMTAG_CONFLICTVERSION,
  27.824 +			  RPMTAG_CONFLICTFLAGS);
  27.825 +
  27.826 +	import_files(importer, rpm);
  27.827 +
  27.828 +	razor_importer_finish_package(importer);
  27.829 +
  27.830 +	return 0;
  27.831 +}
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/librazor/transaction.c	Fri Jun 20 19:04:47 2008 -0400
    28.3 @@ -0,0 +1,912 @@
    28.4 +/*
    28.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    28.6 + * Copyright (C) 2008  Red Hat, Inc
    28.7 + *
    28.8 + * This program is free software; you can redistribute it and/or modify
    28.9 + * it under the terms of the GNU General Public License as published by
   28.10 + * the Free Software Foundation; either version 2 of the License, or
   28.11 + * (at your option) any later version.
   28.12 + *
   28.13 + * This program is distributed in the hope that it will be useful,
   28.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.16 + * GNU General Public License for more details.
   28.17 + *
   28.18 + * You should have received a copy of the GNU General Public License along
   28.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   28.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   28.21 + */
   28.22 +
   28.23 +#define _GNU_SOURCE
   28.24 +
   28.25 +#include <stdlib.h>
   28.26 +#include <stddef.h>
   28.27 +#include <stdint.h>
   28.28 +#include <stdio.h>
   28.29 +#include <string.h>
   28.30 +#include <sys/types.h>
   28.31 +#include <sys/stat.h>
   28.32 +#include <sys/mman.h>
   28.33 +#include <unistd.h>
   28.34 +#include <fcntl.h>
   28.35 +#include <errno.h>
   28.36 +#include <ctype.h>
   28.37 +#include <fnmatch.h>
   28.38 +
   28.39 +#include "razor-internal.h"
   28.40 +#include "razor.h"
   28.41 +
   28.42 +static int
   28.43 +provider_satisfies_requirement(struct razor_property *provider,
   28.44 +			       const char *provider_strings,
   28.45 +			       uint32_t flags,
   28.46 +			       const char *required)
   28.47 +{
   28.48 +	int cmp, len;
   28.49 +	const char *provided = &provider_strings[provider->version];
   28.50 +
   28.51 +	if (!*required)
   28.52 +		return 1;
   28.53 +	if (!*provided) {
   28.54 +		if (flags & RAZOR_PROPERTY_LESS)
   28.55 +			return 0;
   28.56 +		else
   28.57 +			return 1;
   28.58 +	}
   28.59 +
   28.60 +	cmp = razor_versioncmp(provided, required);
   28.61 +
   28.62 +	switch (flags & RAZOR_PROPERTY_RELATION_MASK) {
   28.63 +	case RAZOR_PROPERTY_LESS:
   28.64 +		return cmp < 0;
   28.65 +
   28.66 +	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
   28.67 +		if (cmp <= 0)
   28.68 +			return 1;
   28.69 +		/* fall through: FIXME, make sure this is correct */
   28.70 +
   28.71 +	case RAZOR_PROPERTY_EQUAL:
   28.72 +		if (cmp == 0)
   28.73 +			return 1;
   28.74 +
   28.75 +		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
   28.76 +		len = strlen(required);
   28.77 +		if (!strncmp(required, provided, len) && provided[len] == '-')
   28.78 +			return 1;
   28.79 +		return 0;
   28.80 +
   28.81 +	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
   28.82 +		return cmp >= 0;
   28.83 +
   28.84 +	case RAZOR_PROPERTY_GREATER:
   28.85 +		return cmp > 0;
   28.86 +	}
   28.87 +
   28.88 +	/* shouldn't happen */
   28.89 +	return 0;
   28.90 +}
   28.91 +
   28.92 +#define TRANS_PACKAGE_PRESENT		1
   28.93 +#define TRANS_PACKAGE_UPDATE		2
   28.94 +#define TRANS_PROPERTY_SATISFIED	0x80000000
   28.95 +
   28.96 +struct transaction_set {
   28.97 +	struct razor_set *set;
   28.98 +	uint32_t *packages;
   28.99 +	uint32_t *properties;
  28.100 +};
  28.101 +
  28.102 +struct razor_transaction {
  28.103 +	int package_count, errors;
  28.104 +	struct transaction_set system, upstream;
  28.105 +	int changes;
  28.106 +};
  28.107 +
  28.108 +static void
  28.109 +transaction_set_init(struct transaction_set *ts, struct razor_set *set)
  28.110 +{
  28.111 +	int count;
  28.112 +
  28.113 +	ts->set = set;
  28.114 +	count = set->packages.size / sizeof (struct razor_package);
  28.115 +	ts->packages = zalloc(count * sizeof *ts->packages);
  28.116 +	count = set->properties.size / sizeof (struct razor_property);
  28.117 +	ts->properties = zalloc(count * sizeof *ts->properties);
  28.118 +}
  28.119 +
  28.120 +static void
  28.121 +transaction_set_release(struct transaction_set *ts)
  28.122 +{
  28.123 +	free(ts->packages);
  28.124 +	free(ts->properties);
  28.125 +}
  28.126 +
  28.127 +static void
  28.128 +transaction_set_install_package(struct transaction_set *ts,
  28.129 +				struct razor_package *package)
  28.130 +{
  28.131 +	struct razor_package *pkgs;
  28.132 +	struct list *prop;
  28.133 +	int i;
  28.134 +
  28.135 +	pkgs = ts->set->packages.data;
  28.136 +	i = package - pkgs;
  28.137 +	if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
  28.138 +		return;
  28.139 +
  28.140 +	ts->packages[i] = TRANS_PACKAGE_PRESENT;
  28.141 +
  28.142 +	prop = list_first(&package->properties, &ts->set->property_pool);
  28.143 +	while (prop) {
  28.144 +		ts->properties[prop->data]++;
  28.145 +		prop = list_next(prop);
  28.146 +	}
  28.147 +}
  28.148 +
  28.149 +static void
  28.150 +transaction_set_remove_package(struct transaction_set *ts,
  28.151 +			       struct razor_package *package)
  28.152 +{
  28.153 +	struct razor_package *pkgs;
  28.154 +	struct list *prop;
  28.155 +	int i;
  28.156 +
  28.157 +	pkgs = ts->set->packages.data;
  28.158 +	i = package - pkgs;
  28.159 +	if (ts->packages[i] == 0)
  28.160 +		return;
  28.161 +
  28.162 +	ts->packages[i] = 0;
  28.163 +
  28.164 +	prop = list_first(&package->properties, &ts->set->property_pool);
  28.165 +	while (prop) {
  28.166 +		ts->properties[prop->data]--;
  28.167 +		prop = list_next(prop);
  28.168 +	}
  28.169 +}
  28.170 +
  28.171 +struct razor_transaction *
  28.172 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
  28.173 +{
  28.174 +	struct razor_transaction *trans;
  28.175 +	struct razor_package *p, *spkgs, *pend;
  28.176 +
  28.177 +	trans = zalloc(sizeof *trans);
  28.178 +	transaction_set_init(&trans->system, system);
  28.179 +	transaction_set_init(&trans->upstream, upstream);
  28.180 +
  28.181 +	spkgs = trans->system.set->packages.data;
  28.182 +	pend = trans->system.set->packages.data +
  28.183 +		trans->system.set->packages.size;
  28.184 +	for (p = spkgs; p < pend; p++)
  28.185 +		transaction_set_install_package(&trans->system, p);
  28.186 +
  28.187 +	return trans;
  28.188 +}
  28.189 +
  28.190 +void
  28.191 +razor_transaction_install_package(struct razor_transaction *trans,
  28.192 +				  struct razor_package *package)
  28.193 +{
  28.194 +	transaction_set_install_package(&trans->upstream, package);
  28.195 +	trans->changes++;
  28.196 +}
  28.197 +
  28.198 +void
  28.199 +razor_transaction_remove_package(struct razor_transaction *trans,
  28.200 +				 struct razor_package *package)
  28.201 +{
  28.202 +	transaction_set_remove_package(&trans->system, package);
  28.203 +	trans->changes++;
  28.204 +}
  28.205 +
  28.206 +void
  28.207 +razor_transaction_update_package(struct razor_transaction *trans,
  28.208 +				  struct razor_package *package)
  28.209 +{
  28.210 +	struct razor_package *spkgs, *upkgs, *end;
  28.211 +
  28.212 +	spkgs = trans->system.set->packages.data;
  28.213 +	upkgs = trans->upstream.set->packages.data;
  28.214 +	end = trans->system.set->packages.data +
  28.215 +		trans->system.set->packages.size;
  28.216 +	if (spkgs <= package && package < end)
  28.217 +		trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
  28.218 +	else
  28.219 +		trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
  28.220 +}
  28.221 +
  28.222 +struct prop_iter {
  28.223 +	struct razor_property *p, *start, *end;
  28.224 +	const char *pool;
  28.225 +	uint32_t *present;
  28.226 +};
  28.227 +
  28.228 +static void
  28.229 +prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
  28.230 +{
  28.231 +	pi->p = ts->set->properties.data;
  28.232 +	pi->start = ts->set->properties.data;
  28.233 +	pi->end = ts->set->properties.data + ts->set->properties.size;
  28.234 +	pi->pool = ts->set->string_pool.data;
  28.235 +	pi->present = ts->properties;
  28.236 +}
  28.237 +
  28.238 +static int
  28.239 +prop_iter_next(struct prop_iter *pi, uint32_t flags, struct razor_property **p)
  28.240 +{
  28.241 +	while (pi->p < pi->end) {
  28.242 +		if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
  28.243 +		    (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) == flags) {
  28.244 +			*p = pi->p++;
  28.245 +			return 1;
  28.246 +		}
  28.247 +		pi->p++;
  28.248 +	}
  28.249 +
  28.250 +	return 0;
  28.251 +}
  28.252 +
  28.253 +static struct razor_property *
  28.254 +prop_iter_seek_to(struct prop_iter *pi,
  28.255 +		  uint32_t flags, const char *match)
  28.256 +{
  28.257 +	uint32_t name;
  28.258 +
  28.259 +	while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
  28.260 +		pi->p++;
  28.261 +
  28.262 +	if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
  28.263 +		return NULL;
  28.264 +
  28.265 +	name = pi->p->name;
  28.266 +	while (pi->p < pi->end &&
  28.267 +	       pi->p->name == name &&
  28.268 +	       (pi->p->flags & RAZOR_PROPERTY_TYPE_MASK) != flags)
  28.269 +		pi->p++;
  28.270 +
  28.271 +	if (pi->p == pi->end || pi->p->name != name)
  28.272 +		return NULL;
  28.273 +
  28.274 +	return pi->p;
  28.275 +}
  28.276 +
  28.277 +/* Remove packages from set that provide any of the matching (same
  28.278 + * name and type) providers from ppi onwards that match the
  28.279 + * requirement that rpi points to. */
  28.280 +static void
  28.281 +remove_matching_providers(struct razor_transaction *trans,
  28.282 +			  struct prop_iter *ppi,
  28.283 +			  uint32_t flags,
  28.284 +			  const char *version)
  28.285 +{
  28.286 +	struct razor_property *p;
  28.287 +	struct razor_package *pkg, *pkgs;
  28.288 +	struct razor_package_iterator pkg_iter;
  28.289 +	struct razor_set *set;
  28.290 +	const char *n, *v, *a;
  28.291 +	uint32_t type;
  28.292 +
  28.293 +	if (ppi->present == trans->system.properties)
  28.294 +		set = trans->system.set;
  28.295 +	else
  28.296 +		set = trans->upstream.set;
  28.297 +
  28.298 +	pkgs = (struct razor_package *) set->packages.data;
  28.299 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  28.300 +	for (p = ppi->p;
  28.301 +	     p < ppi->end &&
  28.302 +	     p->name == ppi->p->name &&
  28.303 +	     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  28.304 +	     p++) {
  28.305 +		if (!ppi->present[p - ppi->start])
  28.306 +			continue;
  28.307 +		if (!provider_satisfies_requirement(p, ppi->pool,
  28.308 +						    flags, version))
  28.309 +			continue;
  28.310 +
  28.311 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  28.312 +		while (razor_package_iterator_next(&pkg_iter,
  28.313 +						   &pkg, &n, &v, &a)) {
  28.314 +			fprintf(stderr, "removing %s-%s\n", n, v);
  28.315 +			razor_transaction_remove_package(trans, pkg);
  28.316 +		}
  28.317 +	}
  28.318 +}
  28.319 +
  28.320 +static void
  28.321 +flag_matching_providers(struct razor_transaction *trans,
  28.322 +			struct prop_iter *ppi,
  28.323 +			struct razor_property *r,
  28.324 +			struct prop_iter *rpi,
  28.325 +			unsigned int flag)
  28.326 +{
  28.327 +	struct razor_property *p;
  28.328 +	struct razor_package *pkg, *pkgs;
  28.329 +	struct razor_package_iterator pkg_iter;
  28.330 +	struct razor_set *set;
  28.331 +	const char *name, *version, *arch;
  28.332 +	uint32_t *flags, type;
  28.333 +
  28.334 +	if (ppi->present == trans->system.properties) {
  28.335 +		set = trans->system.set;
  28.336 +		flags = trans->system.packages;
  28.337 +	} else {
  28.338 +		set = trans->upstream.set;
  28.339 +		flags = trans->upstream.packages;
  28.340 +	}
  28.341 +
  28.342 +	pkgs = (struct razor_package *) set->packages.data;
  28.343 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  28.344 +	for (p = ppi->p;
  28.345 +	     p < ppi->end &&
  28.346 +		     p->name == ppi->p->name &&
  28.347 +		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  28.348 +	     p++) {
  28.349 +		if (!ppi->present[p - ppi->start])
  28.350 +			continue;
  28.351 +		if (!provider_satisfies_requirement(p, ppi->pool,
  28.352 +						    r->flags,
  28.353 +						    &rpi->pool[r->version]))
  28.354 +			continue;
  28.355 +
  28.356 +		razor_package_iterator_init_for_property(&pkg_iter, set, p);
  28.357 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  28.358 +						   &name, &version, &arch)) {
  28.359 +
  28.360 +			fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
  28.361 +				name, version,
  28.362 +				ppi->pool + p->name,
  28.363 +				rpi->pool + r->name,
  28.364 +				rpi->pool + r->version);
  28.365 +			flags[pkg - pkgs] |= flag;
  28.366 +		}
  28.367 +	}
  28.368 +}
  28.369 +
  28.370 +static struct razor_package *
  28.371 +pick_matching_provider(struct razor_set *set,
  28.372 +		       struct prop_iter *ppi,
  28.373 +		       uint32_t flags,
  28.374 +		       const char *version)
  28.375 +{
  28.376 +	struct razor_property *p;
  28.377 +	struct razor_package *pkgs;
  28.378 +	struct list *i;
  28.379 +	uint32_t type;
  28.380 +
  28.381 +	/* This is where we decide which pkgs to pull in to satisfy a
  28.382 +	 * requirement.  There may be several different providers
  28.383 +	 * (different versions) and each version of a provider may
  28.384 +	 * come from a number of packages.  We pick the first package
  28.385 +	 * from the first provider that matches. */
  28.386 +
  28.387 +	pkgs = set->packages.data;
  28.388 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  28.389 +	for (p = ppi->p;
  28.390 +	     p < ppi->end &&
  28.391 +		     p->name == ppi->p->name &&
  28.392 +		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type &&
  28.393 +		     ppi->present[p - ppi->start] == 0;
  28.394 +	     p++) {
  28.395 +		if (!provider_satisfies_requirement(p, ppi->pool,
  28.396 +						    flags, version))
  28.397 +			continue;
  28.398 +
  28.399 +		i = list_first(&p->packages, &set->package_pool);
  28.400 +
  28.401 +		return &pkgs[i->data];
  28.402 +	}
  28.403 +
  28.404 +	return NULL;
  28.405 +}
  28.406 +
  28.407 +static void
  28.408 +remove_obsoleted_packages(struct razor_transaction *trans)
  28.409 +{
  28.410 +	struct razor_property *up;
  28.411 +	struct razor_package *spkgs;
  28.412 +	struct prop_iter spi, upi;
  28.413 +
  28.414 +	spkgs = trans->system.set->packages.data;
  28.415 +	prop_iter_init(&spi, &trans->system);
  28.416 +	prop_iter_init(&upi, &trans->upstream);
  28.417 +
  28.418 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
  28.419 +		if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  28.420 +				       &upi.pool[up->name]))
  28.421 +			continue;
  28.422 +		remove_matching_providers(trans, &spi, up->flags,
  28.423 +					  &upi.pool[up->version]);
  28.424 +	}
  28.425 +}
  28.426 +
  28.427 +static int
  28.428 +any_provider_satisfies_requirement(struct prop_iter *ppi,
  28.429 +				   uint32_t flags,
  28.430 +				   const char *version)
  28.431 +{
  28.432 +	struct razor_property *p;
  28.433 +	uint32_t type;
  28.434 +
  28.435 +	type = ppi->p->flags & RAZOR_PROPERTY_TYPE_MASK;
  28.436 +	for (p = ppi->p;
  28.437 +	     p < ppi->end &&
  28.438 +		     p->name == ppi->p->name &&
  28.439 +		     (p->flags & RAZOR_PROPERTY_TYPE_MASK) == type;
  28.440 +	     p++) {
  28.441 +		if (ppi->present[p - ppi->start] > 0 &&
  28.442 +		    provider_satisfies_requirement(p, ppi->pool,
  28.443 +						   flags, version))
  28.444 +			return 1;
  28.445 +	}
  28.446 +
  28.447 +	return 0;
  28.448 +}
  28.449 +
  28.450 +static void
  28.451 +clear_requires_flags(struct transaction_set *ts)
  28.452 +{
  28.453 +	struct razor_property *p;
  28.454 +	const char *pool;
  28.455 +	int i, count;
  28.456 +
  28.457 +	count = ts->set->properties.size / sizeof *p;
  28.458 +	p = ts->set->properties.data;
  28.459 +	pool = ts->set->string_pool.data;
  28.460 +	for (i = 0; i < count; i++) {
  28.461 +		ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
  28.462 +		if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
  28.463 +			ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
  28.464 +	}
  28.465 +}
  28.466 +
  28.467 +const char *
  28.468 +razor_property_relation_to_string(struct razor_property *p)
  28.469 +{
  28.470 +	switch (p->flags & RAZOR_PROPERTY_RELATION_MASK) {
  28.471 +	case RAZOR_PROPERTY_LESS:
  28.472 +		return "<";
  28.473 +
  28.474 +	case RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL:
  28.475 +		return "<=";
  28.476 +
  28.477 +	case RAZOR_PROPERTY_EQUAL:
  28.478 +		return "=";
  28.479 +
  28.480 +	case RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL:
  28.481 +		return ">=";
  28.482 +
  28.483 +	case RAZOR_PROPERTY_GREATER:
  28.484 +		return ">";
  28.485 +
  28.486 +	default:
  28.487 +		return "?";
  28.488 +	}
  28.489 +}
  28.490 +
  28.491 +const char *
  28.492 +razor_property_type_to_string(struct razor_property *p)
  28.493 +{
  28.494 +	switch (p->flags & RAZOR_PROPERTY_TYPE_MASK) {
  28.495 +	case RAZOR_PROPERTY_REQUIRES:
  28.496 +		return "requires";
  28.497 +	case RAZOR_PROPERTY_PROVIDES:
  28.498 +		return "provides";
  28.499 +	case RAZOR_PROPERTY_CONFLICTS:
  28.500 +		return "conflicts";
  28.501 +	case RAZOR_PROPERTY_OBSOLETES:
  28.502 +		return "obsoletes";
  28.503 +	default:
  28.504 +		return NULL;
  28.505 +	}
  28.506 +}
  28.507 +
  28.508 +static void
  28.509 +mark_satisfied_requires(struct razor_transaction *trans,
  28.510 +			struct transaction_set *rts,
  28.511 +			struct transaction_set *pts)
  28.512 +{
  28.513 +	struct prop_iter rpi, ppi;
  28.514 +	struct razor_property *rp;
  28.515 +
  28.516 +	prop_iter_init(&rpi, rts);
  28.517 +	prop_iter_init(&ppi, pts);
  28.518 +
  28.519 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  28.520 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
  28.521 +				       &rpi.pool[rp->name]))
  28.522 +			continue;
  28.523 +
  28.524 +		if (any_provider_satisfies_requirement(&ppi, rp->flags,
  28.525 +						       &rpi.pool[rp->version]))
  28.526 +			rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
  28.527 +	}
  28.528 +}
  28.529 +
  28.530 +static void
  28.531 +mark_all_satisfied_requires(struct razor_transaction *trans)
  28.532 +{
  28.533 +	clear_requires_flags(&trans->system);
  28.534 +	clear_requires_flags(&trans->upstream);
  28.535 +	mark_satisfied_requires(trans, &trans->system, &trans->system);
  28.536 +	mark_satisfied_requires(trans, &trans->system, &trans->upstream);
  28.537 +	mark_satisfied_requires(trans, &trans->upstream, &trans->system);
  28.538 +	mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
  28.539 +}
  28.540 +
  28.541 +static void
  28.542 +update_unsatisfied_packages(struct razor_transaction *trans)
  28.543 +{
  28.544 +	struct razor_package *spkgs, *pkg;
  28.545 +	struct razor_property *sp;
  28.546 +	struct prop_iter spi;
  28.547 +	struct razor_package_iterator pkg_iter;
  28.548 +	const char *name, *version, *arch;
  28.549 +
  28.550 +	spkgs = trans->system.set->packages.data;
  28.551 +	prop_iter_init(&spi, &trans->system);
  28.552 +
  28.553 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
  28.554 +		if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
  28.555 +			continue;
  28.556 +
  28.557 +		razor_package_iterator_init_for_property(&pkg_iter,
  28.558 +							 trans->system.set,
  28.559 +							 sp);
  28.560 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  28.561 +						   &name, &version, &arch)) {
  28.562 +			fprintf(stderr, "updating %s because %s %s %s "
  28.563 +				"isn't satisfied\n",
  28.564 +				name, spi.pool + sp->name,
  28.565 +				razor_property_relation_to_string(sp),
  28.566 +				spi.pool + sp->version);
  28.567 +			trans->system.packages[pkg - spkgs] |=
  28.568 +				TRANS_PACKAGE_UPDATE;
  28.569 +		}
  28.570 +	}
  28.571 +}
  28.572 +
  28.573 +void
  28.574 +razor_transaction_update_all(struct razor_transaction *trans)
  28.575 +{
  28.576 +	struct razor_package *p;
  28.577 +	int i, count;
  28.578 +
  28.579 +	count = trans->system.set->packages.size / sizeof *p;
  28.580 +	for (i = 0; i < count; i++)
  28.581 +		trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
  28.582 +}
  28.583 +
  28.584 +static void
  28.585 +update_conflicted_packages(struct razor_transaction *trans)
  28.586 +{
  28.587 +	struct razor_package *pkg, *spkgs;
  28.588 +	struct razor_property *up, *sp;
  28.589 +	struct prop_iter spi, upi;
  28.590 +	struct razor_package_iterator pkg_iter;
  28.591 +	const char *name, *version, *arch;
  28.592 +
  28.593 +	spkgs = trans->system.set->packages.data;
  28.594 +	prop_iter_init(&spi, &trans->system);
  28.595 +	prop_iter_init(&upi, &trans->upstream);
  28.596 +
  28.597 +	while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
  28.598 +		if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
  28.599 +				       &spi.pool[sp->name]))
  28.600 +			continue;
  28.601 +
  28.602 +		if (!any_provider_satisfies_requirement(&upi, sp->flags,
  28.603 +							&spi.pool[sp->version]))
  28.604 +			continue;
  28.605 +
  28.606 +		razor_package_iterator_init_for_property(&pkg_iter,
  28.607 +							 trans->system.set,
  28.608 +							 sp);
  28.609 +		while (razor_package_iterator_next(&pkg_iter, &pkg,
  28.610 +						   &name, &version, &arch)) {
  28.611 +			fprintf(stderr, "updating %s %s because it conflicts with %s",
  28.612 +				name, version, spi.pool + sp->name);
  28.613 +			trans->system.packages[pkg - spkgs] |=
  28.614 +				TRANS_PACKAGE_UPDATE;
  28.615 +		}
  28.616 +	}
  28.617 +
  28.618 +	prop_iter_init(&spi, &trans->system);
  28.619 +	prop_iter_init(&upi, &trans->upstream);
  28.620 +
  28.621 +	while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
  28.622 +		sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
  28.623 +				       &upi.pool[upi.p->name]);
  28.624 +
  28.625 +		if (sp)
  28.626 +			flag_matching_providers(trans, &spi, up, &upi,
  28.627 +						TRANS_PACKAGE_UPDATE);
  28.628 +	}
  28.629 +}
  28.630 +
  28.631 +static void
  28.632 +pull_in_requirements(struct razor_transaction *trans,
  28.633 +		     struct prop_iter *rpi, struct prop_iter *ppi)
  28.634 +{
  28.635 +	struct razor_property *rp, *pp;
  28.636 +	struct razor_package *pkg, *upkgs;
  28.637 +
  28.638 +	upkgs = trans->upstream.set->packages.data;
  28.639 +	while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  28.640 +		if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
  28.641 +			continue;
  28.642 +
  28.643 +		pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
  28.644 +				       &rpi->pool[rp->name]);
  28.645 +		if (pp == NULL)
  28.646 +			continue;
  28.647 +		pkg = pick_matching_provider(trans->upstream.set,
  28.648 +					     ppi, rp->flags,
  28.649 +					     &rpi->pool[rp->version]);
  28.650 +		if (pkg == NULL)
  28.651 +			continue;
  28.652 +
  28.653 +		rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
  28.654 +
  28.655 +		fprintf(stderr, "pulling in %s which provides %s %s %s "
  28.656 +			"to satisfy %s %s %s\n",
  28.657 +			ppi->pool + pkg->name,
  28.658 +			ppi->pool + pp->name,
  28.659 +			razor_property_relation_to_string(pp),
  28.660 +			ppi->pool + pp->version,
  28.661 +			&rpi->pool[rp->name],
  28.662 +			razor_property_relation_to_string(rp),
  28.663 +			&rpi->pool[rp->version]);
  28.664 +
  28.665 +		trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
  28.666 +	}
  28.667 +}
  28.668 +
  28.669 +static void
  28.670 +pull_in_all_requirements(struct razor_transaction *trans)
  28.671 +{
  28.672 +	struct prop_iter rpi, ppi;
  28.673 +
  28.674 +	prop_iter_init(&rpi, &trans->system);
  28.675 +	prop_iter_init(&ppi, &trans->upstream);
  28.676 +	pull_in_requirements(trans, &rpi, &ppi);
  28.677 +
  28.678 +	prop_iter_init(&rpi, &trans->upstream);
  28.679 +	prop_iter_init(&ppi, &trans->upstream);
  28.680 +	pull_in_requirements(trans, &rpi, &ppi);
  28.681 +}
  28.682 +
  28.683 +static void
  28.684 +flush_scheduled_system_updates(struct razor_transaction *trans)
  28.685 +{
  28.686 + 	struct razor_package_iterator *pi;
  28.687 + 	struct razor_package *p, *pkg, *spkgs;
  28.688 +	struct prop_iter ppi;
  28.689 +	const char *name, *version, *arch;
  28.690 +
  28.691 +	spkgs = trans->system.set->packages.data;
  28.692 +	pi = razor_package_iterator_create(trans->system.set);
  28.693 +	prop_iter_init(&ppi, &trans->upstream);
  28.694 +
  28.695 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  28.696 +		if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
  28.697 +			continue;
  28.698 +
  28.699 +		if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
  28.700 +			continue;
  28.701 +
  28.702 +		pkg = pick_matching_provider(trans->upstream.set, &ppi,
  28.703 +					     RAZOR_PROPERTY_GREATER, version);
  28.704 +		if (pkg == NULL)
  28.705 +			continue;
  28.706 +
  28.707 +		fprintf(stderr, "updating %s-%s to %s-%s\n",
  28.708 +			name, version,
  28.709 +			&ppi.pool[pkg->name], &ppi.pool[pkg->version]);
  28.710 +
  28.711 +		razor_transaction_remove_package(trans, p);
  28.712 +		razor_transaction_install_package(trans, pkg);
  28.713 +	}
  28.714 +
  28.715 +	razor_package_iterator_destroy(pi);
  28.716 +}
  28.717 +
  28.718 +static void
  28.719 +flush_scheduled_upstream_updates(struct razor_transaction *trans)
  28.720 +{
  28.721 + 	struct razor_package_iterator *pi;
  28.722 + 	struct razor_package *p, *upkgs;
  28.723 +	struct prop_iter spi;
  28.724 +	const char *name, *version, *arch;
  28.725 +
  28.726 +	upkgs = trans->upstream.set->packages.data;
  28.727 +	pi = razor_package_iterator_create(trans->upstream.set);
  28.728 +	prop_iter_init(&spi, &trans->system);
  28.729 +
  28.730 +	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
  28.731 +		if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
  28.732 +			continue;
  28.733 +
  28.734 +		if (prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
  28.735 +			remove_matching_providers(trans,
  28.736 +						  &spi,
  28.737 +						  RAZOR_PROPERTY_LESS,
  28.738 +						  version);
  28.739 +		razor_transaction_install_package(trans, p);
  28.740 +		fprintf(stderr, "installing %s-%s\n", name, version);
  28.741 +	}
  28.742 +}
  28.743 +
  28.744 +int
  28.745 +razor_transaction_resolve(struct razor_transaction *trans)
  28.746 +{
  28.747 +	int last = 0;
  28.748 +
  28.749 +	flush_scheduled_system_updates(trans);
  28.750 +	flush_scheduled_upstream_updates(trans);
  28.751 +
  28.752 +	while (last < trans->changes) {
  28.753 +		last = trans->changes;
  28.754 +		remove_obsoleted_packages(trans);
  28.755 +		mark_all_satisfied_requires(trans);
  28.756 +		update_unsatisfied_packages(trans);
  28.757 +		update_conflicted_packages(trans);
  28.758 +		pull_in_all_requirements(trans);
  28.759 +		flush_scheduled_system_updates(trans);
  28.760 +		flush_scheduled_upstream_updates(trans);
  28.761 +	}
  28.762 +
  28.763 +	return trans->changes;
  28.764 +}
  28.765 +
  28.766 +static void
  28.767 +describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
  28.768 +{
  28.769 +	struct razor_package_iterator pi;
  28.770 +	struct razor_package *pkg;
  28.771 +	const char *name, *version, *arch, *pool;
  28.772 +
  28.773 +	pool = set->string_pool.data;
  28.774 +	if (pool[rp->version] == '\0') {
  28.775 +		razor_package_iterator_init_for_property(&pi, set, rp);
  28.776 +		while (razor_package_iterator_next(&pi, &pkg,
  28.777 +						   &name, &version, &arch))
  28.778 +			fprintf(stderr, "%s is needed by %s-%s.%s\n",
  28.779 +				&pool[rp->name],
  28.780 +				name, version, arch);
  28.781 +	} else {
  28.782 +		razor_package_iterator_init_for_property(&pi, set, rp);
  28.783 +		while (razor_package_iterator_next(&pi, &pkg,
  28.784 +						   &name, &version, &arch))
  28.785 +			fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
  28.786 +				&pool[rp->name],
  28.787 +				razor_property_relation_to_string(rp),
  28.788 +				&pool[rp->version],
  28.789 +				name, version, arch);
  28.790 +	}
  28.791 +}
  28.792 +
  28.793 +int
  28.794 +razor_transaction_describe(struct razor_transaction *trans)
  28.795 +{
  28.796 +	struct prop_iter rpi;
  28.797 +	struct razor_property *rp;
  28.798 +	int unsatisfied;
  28.799 +
  28.800 +	flush_scheduled_system_updates(trans);
  28.801 +	flush_scheduled_upstream_updates(trans);
  28.802 +	mark_all_satisfied_requires(trans);
  28.803 +
  28.804 +	unsatisfied = 0;
  28.805 +	prop_iter_init(&rpi, &trans->system);
  28.806 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  28.807 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  28.808 +			describe_unsatisfied(trans->system.set, rp);
  28.809 +		        unsatisfied++;
  28.810 +		}
  28.811 +	}
  28.812 +
  28.813 +	prop_iter_init(&rpi, &trans->upstream);
  28.814 +	while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
  28.815 +		if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
  28.816 +			describe_unsatisfied(trans->upstream.set, rp);
  28.817 +			unsatisfied++;
  28.818 +		}
  28.819 +	}
  28.820 +
  28.821 +	return unsatisfied;
  28.822 +}
  28.823 +
  28.824 +int
  28.825 +razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  28.826 +				       const char *name,
  28.827 +				       uint32_t flags,
  28.828 +				       const char *version)
  28.829 +{
  28.830 +	struct prop_iter pi;
  28.831 +	struct razor_property *p;
  28.832 +
  28.833 +	prop_iter_init(&pi, &trans->system);
  28.834 +	while (prop_iter_next(&pi, flags, &p)) {
  28.835 +		if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  28.836 +		    p->flags == flags &&
  28.837 +		    strcmp(&pi.pool[p->name], name) == 0 &&
  28.838 +		    strcmp(&pi.pool[p->version], version) == 0)
  28.839 +
  28.840 +			return 1;
  28.841 +	}
  28.842 +
  28.843 +	prop_iter_init(&pi, &trans->upstream);
  28.844 +	while (prop_iter_next(&pi, flags, &p)) {
  28.845 +		if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
  28.846 +		    p->flags == flags &&
  28.847 +		    strcmp(&pi.pool[p->name], name) == 0 &&
  28.848 +		    strcmp(&pi.pool[p->version], version) == 0)
  28.849 +
  28.850 +			return 1;
  28.851 +	}
  28.852 +
  28.853 +	return 0;
  28.854 +}
  28.855 +
  28.856 +struct razor_set *
  28.857 +razor_transaction_finish(struct razor_transaction *trans)
  28.858 +{
  28.859 +	struct razor_merger *merger;
  28.860 +	struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
  28.861 +	char *upool, *spool;
  28.862 +	int cmp;
  28.863 +
  28.864 +	s = trans->system.set->packages.data;
  28.865 +	spkgs = trans->system.set->packages.data;
  28.866 +	send = trans->system.set->packages.data +
  28.867 +		trans->system.set->packages.size;
  28.868 +	spool = trans->system.set->string_pool.data;
  28.869 +
  28.870 +	u = trans->upstream.set->packages.data;
  28.871 +	upkgs = trans->upstream.set->packages.data;
  28.872 +	uend = trans->upstream.set->packages.data +
  28.873 +		trans->upstream.set->packages.size;
  28.874 +	upool = trans->upstream.set->string_pool.data;
  28.875 +
  28.876 +	merger = razor_merger_create(trans->system.set, trans->upstream.set);
  28.877 +	while (s < send || u < uend) {
  28.878 +		if (s < send && u < uend)
  28.879 +			cmp = strcmp(&spool[s->name], &upool[u->name]);
  28.880 +		else if (s < send)
  28.881 +			cmp = -1;
  28.882 +		else
  28.883 +			cmp = 1;
  28.884 +
  28.885 +		if (cmp < 0) {
  28.886 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  28.887 +				razor_merger_add_package(merger, s);
  28.888 +			s++;
  28.889 +		} else if (cmp == 0) {
  28.890 +			if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
  28.891 +				razor_merger_add_package(merger, s);
  28.892 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  28.893 +				razor_merger_add_package(merger, u);
  28.894 +
  28.895 +			s++;
  28.896 +			u++;
  28.897 +		} else {
  28.898 +			if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
  28.899 +				razor_merger_add_package(merger, u);
  28.900 +			u++;
  28.901 +		}
  28.902 +	}
  28.903 +
  28.904 +	razor_transaction_destroy(trans);
  28.905 +
  28.906 +	return razor_merger_finish(merger);
  28.907 +}
  28.908 +
  28.909 +void
  28.910 +razor_transaction_destroy(struct razor_transaction *trans)
  28.911 +{
  28.912 +	transaction_set_release(&trans->system);
  28.913 +	transaction_set_release(&trans->upstream);
  28.914 +	free(trans);
  28.915 +}
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/librazor/types.c	Fri Jun 20 19:04:47 2008 -0400
    29.3 @@ -0,0 +1,246 @@
    29.4 +#include <stdlib.h>
    29.5 +#include <string.h>
    29.6 +
    29.7 +#include "razor-internal.h"
    29.8 +
    29.9 +void
   29.10 +array_init(struct array *array)
   29.11 +{
   29.12 +	memset(array, 0, sizeof *array);
   29.13 +}
   29.14 +
   29.15 +void
   29.16 +array_release(struct array *array)
   29.17 +{
   29.18 +	free(array->data);
   29.19 +}
   29.20 +
   29.21 +void *
   29.22 +array_add(struct array *array, int size)
   29.23 +{
   29.24 +	int alloc;
   29.25 +	void *data, *p;
   29.26 +
   29.27 +	if (array->alloc > 0)
   29.28 +		alloc = array->alloc;
   29.29 +	else
   29.30 +		alloc = 16;
   29.31 +
   29.32 +	while (alloc < array->size + size)
   29.33 +		alloc *= 2;
   29.34 +
   29.35 +	if (array->alloc < alloc) {
   29.36 +		data = realloc(array->data, alloc);
   29.37 +		if (data == NULL)
   29.38 +			return 0;
   29.39 +		array->data = data;
   29.40 +		array->alloc = alloc;
   29.41 +	}
   29.42 +
   29.43 +	p = array->data + array->size;
   29.44 +	array->size += size;
   29.45 +
   29.46 +	return p;
   29.47 +}
   29.48 +
   29.49 +/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
   29.50 +#define RAZOR_ENTRY_LAST 0x80
   29.51 +#define RAZOR_IMMEDIATE  0x80
   29.52 +#define RAZOR_EMPTY_LIST 0xff
   29.53 +
   29.54 +void
   29.55 +list_set_empty(struct list_head *head)
   29.56 +{
   29.57 +	head->list_ptr = ~0;
   29.58 +	head->flags = RAZOR_EMPTY_LIST;
   29.59 +}
   29.60 +
   29.61 +void
   29.62 +list_set_ptr(struct list_head *head, uint32_t ptr)
   29.63 +{
   29.64 +	head->list_ptr = ptr;
   29.65 +	head->flags = 0;
   29.66 +}
   29.67 +
   29.68 +void
   29.69 +list_set_array(struct list_head *head, struct array *pool,
   29.70 +	       struct array *items, int force_indirect)
   29.71 +{
   29.72 +	struct list *p;
   29.73 +
   29.74 +	if (!force_indirect) {
   29.75 +		if (items->size == 0) {
   29.76 +			list_set_empty(head);
   29.77 +			return;
   29.78 +		} else if (items->size == sizeof (uint32_t)) {
   29.79 +			head->list_ptr = *(uint32_t *) items->data;
   29.80 +			head->flags = RAZOR_IMMEDIATE;
   29.81 +			return;
   29.82 +		}
   29.83 +	}
   29.84 +
   29.85 +	p = array_add(pool, items->size);
   29.86 +	memcpy(p, items->data, items->size);
   29.87 +	p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
   29.88 +	list_set_ptr(head, p - (struct list *) pool->data);
   29.89 +}
   29.90 +
   29.91 +struct list *
   29.92 +list_first(struct list_head *head, struct array *pool)
   29.93 +{
   29.94 +	if (head->flags == RAZOR_EMPTY_LIST)
   29.95 +		return NULL;
   29.96 +	else if (head->flags == RAZOR_IMMEDIATE)
   29.97 +		return (struct list *) head;
   29.98 +	else
   29.99 +		return (struct list *) pool->data + head->list_ptr;
  29.100 +}
  29.101 +
  29.102 +struct list *
  29.103 +list_next(struct list *list)
  29.104 +{
  29.105 +	if (list->flags)
  29.106 +		return NULL;
  29.107 +	return ++list;
  29.108 +}
  29.109 +
  29.110 +void
  29.111 +list_remap_pool(struct array *pool, uint32_t *map)
  29.112 +{
  29.113 +	struct list *p, *end;
  29.114 +
  29.115 +	end = pool->data + pool->size;
  29.116 +	for (p = pool->data; p < end; p++)
  29.117 +		p->data = map[p->data];
  29.118 +}
  29.119 +
  29.120 +void
  29.121 +list_remap_head(struct list_head *head, uint32_t *map)
  29.122 +{
  29.123 +	if (head->flags == RAZOR_IMMEDIATE)
  29.124 +		head->list_ptr = map[head->list_ptr];
  29.125 +}
  29.126 +
  29.127 +
  29.128 +void
  29.129 +hashtable_init(struct hashtable *table, struct array *pool)
  29.130 +{
  29.131 +	array_init(&table->buckets);
  29.132 +	table->pool = pool;
  29.133 +}
  29.134 +
  29.135 +void
  29.136 +hashtable_release(struct hashtable *table)
  29.137 +{
  29.138 +	array_release(&table->buckets);
  29.139 +}
  29.140 +
  29.141 +static unsigned int
  29.142 +hash_string(const char *key)
  29.143 +{
  29.144 +	const char *p;
  29.145 +	unsigned int hash = 0;
  29.146 +
  29.147 +	for (p = key; *p; p++)
  29.148 +		hash = (hash * 617) ^ *p;
  29.149 +
  29.150 +	return hash;
  29.151 +}
  29.152 +
  29.153 +uint32_t
  29.154 +hashtable_lookup(struct hashtable *table, const char *key)
  29.155 +{
  29.156 +	unsigned int mask, start, i;
  29.157 +	uint32_t *b;
  29.158 +	char *pool;
  29.159 +
  29.160 +	pool = table->pool->data;
  29.161 +	mask = table->buckets.alloc - 1;
  29.162 +	start = hash_string(key) * sizeof(uint32_t);
  29.163 +
  29.164 +	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  29.165 +		b = table->buckets.data + ((start + i) & mask);
  29.166 +
  29.167 +		if (*b == 0)
  29.168 +			return 0;
  29.169 +
  29.170 +		if (strcmp(key, &pool[*b]) == 0)
  29.171 +			return *b;
  29.172 +	}
  29.173 +
  29.174 +	return 0;
  29.175 +}
  29.176 +
  29.177 +static void
  29.178 +do_insert(struct hashtable *table, uint32_t value)
  29.179 +{
  29.180 +	unsigned int mask, start, i;
  29.181 +	uint32_t *b;
  29.182 +	const char *key;
  29.183 +
  29.184 +	key = (char *) table->pool->data + value;
  29.185 +	mask = table->buckets.alloc - 1;
  29.186 +	start = hash_string(key) * sizeof(uint32_t);
  29.187 +
  29.188 +	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  29.189 +		b = table->buckets.data + ((start + i) & mask);
  29.190 +		if (*b == 0) {
  29.191 +			*b = value;
  29.192 +			break;
  29.193 +		}
  29.194 +	}
  29.195 +}
  29.196 +
  29.197 +static uint32_t
  29.198 +add_to_string_pool(struct hashtable *table, const char *key)
  29.199 +{
  29.200 +	int len;
  29.201 +	char *p;
  29.202 +
  29.203 +	len = strlen(key) + 1;
  29.204 +	p = array_add(table->pool, len);
  29.205 +	memcpy(p, key, len);
  29.206 +
  29.207 +	return p - (char *) table->pool->data;
  29.208 +}
  29.209 +
  29.210 +uint32_t
  29.211 +hashtable_insert(struct hashtable *table, const char *key)
  29.212 +{
  29.213 +	uint32_t value, *buckets, *b, *end;
  29.214 +	int alloc;
  29.215 +
  29.216 +	alloc = table->buckets.alloc;
  29.217 +	array_add(&table->buckets, 4 * sizeof *buckets);
  29.218 +	if (alloc != table->buckets.alloc) {
  29.219 +		end = table->buckets.data + alloc;
  29.220 +		memset(end, 0, table->buckets.alloc - alloc);
  29.221 +		for (b = table->buckets.data; b < end; b++) {
  29.222 +			value = *b;
  29.223 +			if (value != 0) {
  29.224 +				*b = 0;
  29.225 +				do_insert(table, value);
  29.226 +			}
  29.227 +		}
  29.228 +	}
  29.229 +
  29.230 +	value = add_to_string_pool(table, key);
  29.231 +	do_insert (table, value);
  29.232 +
  29.233 +	return value;
  29.234 +}
  29.235 +
  29.236 +uint32_t
  29.237 +hashtable_tokenize(struct hashtable *table, const char *string)
  29.238 +{
  29.239 +	uint32_t token;
  29.240 +
  29.241 +	if (string == NULL)
  29.242 +		string = "";
  29.243 +
  29.244 +	token = hashtable_lookup(table, string);
  29.245 +	if (token != 0)
  29.246 +		return token;
  29.247 +
  29.248 +	return hashtable_insert(table, string);
  29.249 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/librazor/util.c	Fri Jun 20 19:04:47 2008 -0400
    30.3 @@ -0,0 +1,167 @@
    30.4 +#include <limits.h>
    30.5 +#include <string.h>
    30.6 +#include <sys/stat.h>
    30.7 +#include <stdlib.h>
    30.8 +#include <stdio.h>
    30.9 +#include <stdint.h>
   30.10 +#include <unistd.h>
   30.11 +
   30.12 +#include "razor-internal.h"
   30.13 +
   30.14 +int
   30.15 +razor_create_dir(const char *root, const char *path)
   30.16 +{
   30.17 +	char buffer[PATH_MAX], *p;
   30.18 +	const char *slash, *next;
   30.19 +	struct stat buf;
   30.20 +
   30.21 +	/* Create all sub-directories in dir. We know root exists and
   30.22 +	 * is a dir, root does not end in a '/', and path has a
   30.23 +	 * leading '/'. */
   30.24 +
   30.25 +	strcpy(buffer, root);
   30.26 +	p = buffer + strlen(buffer);
   30.27 +	slash = path;
   30.28 +	for (slash = path; *slash != '\0'; slash = next) {
   30.29 +		next = strchr(slash + 1, '/');
   30.30 +		if (next == NULL)
   30.31 +			break;
   30.32 +
   30.33 +		memcpy(p, slash, next - slash);
   30.34 +		p += next - slash;
   30.35 +		*p = '\0';
   30.36 +
   30.37 +		if (stat(buffer, &buf) == 0) {
   30.38 +			if (!S_ISDIR(buf.st_mode)) {
   30.39 +				fprintf(stderr,
   30.40 +					"%s exists but is not a directory\n",
   30.41 +					buffer);
   30.42 +				return -1;
   30.43 +			}
   30.44 +		} else if (mkdir(buffer, 0777) < 0) {
   30.45 +			fprintf(stderr, "failed to make directory %s: %m\n",
   30.46 +				buffer);
   30.47 +			return -1;
   30.48 +		}
   30.49 +
   30.50 +		/* FIXME: What to do about permissions for dirs we
   30.51 +		 * have to create but are not in the cpio archive? */
   30.52 +	}
   30.53 +
   30.54 +	return 0;
   30.55 +}
   30.56 +
   30.57 +int
   30.58 +razor_write(int fd, const void *data, size_t size)
   30.59 +{
   30.60 +	size_t rest;
   30.61 +	ssize_t written;
   30.62 +	const unsigned char *p;
   30.63 +
   30.64 +	rest = size;
   30.65 +	p = data;
   30.66 +	while (rest > 0) {
   30.67 +		written = write(fd, p, rest);
   30.68 +		if (written < 0) {
   30.69 +			fprintf(stderr, "write error: %m\n");
   30.70 +			return -1;
   30.71 +		}
   30.72 +		rest -= written;
   30.73 +		p += written;
   30.74 +	}
   30.75 +
   30.76 +	return 0;
   30.77 +}
   30.78 +
   30.79 +struct qsort_context {
   30.80 +	size_t size;
   30.81 +	razor_compare_with_data_func_t compare;
   30.82 +	void *data;
   30.83 +};
   30.84 +
   30.85 +static void
   30.86 +qsort_swap(void *p1, void *p2, size_t size)
   30.87 +{
   30.88 +	char buffer[size];
   30.89 +
   30.90 +	memcpy(buffer, p1, size);
   30.91 +	memcpy(p1, p2, size);
   30.92 +	memcpy(p2, buffer, size);
   30.93 +}
   30.94 +
   30.95 +static void
   30.96 +__qsort_with_data(void *base, size_t nelem, uint32_t *map,
   30.97 +		  struct qsort_context *ctx)
   30.98 +{
   30.99 +	void *p, *start, *end, *pivot;
  30.100 +	uint32_t *mp, *mstart, *mend, tmp;
  30.101 +	int left, right, result;
  30.102 +	size_t size = ctx->size;
  30.103 +
  30.104 +	p = base;
  30.105 +	start = base;
  30.106 +	end = base + nelem * size;
  30.107 +	mp = map;
  30.108 +	mstart = map;
  30.109 +	mend = map + nelem;
  30.110 +	pivot = base + (random() % nelem) * size;
  30.111 +
  30.112 +	while (p < end) {
  30.113 +		result = ctx->compare(p, pivot, ctx->data);
  30.114 +		if (result < 0) {
  30.115 +			qsort_swap(p, start, size);
  30.116 +			tmp = *mp;
  30.117 +			*mp = *mstart;
  30.118 +			*mstart = tmp;
  30.119 +			if (start == pivot)
  30.120 +				pivot = p;
  30.121 +			start += size;
  30.122 +			mstart++;
  30.123 +			p += size;
  30.124 +			mp++;
  30.125 +		} else if (result == 0) {
  30.126 +			p += size;
  30.127 +			mp++;
  30.128 +		} else {
  30.129 + 			end -= size;
  30.130 +			mend--;
  30.131 +			qsort_swap(p, end, size);
  30.132 +			tmp = *mp;
  30.133 +			*mp = *mend;
  30.134 +			*mend = tmp;
  30.135 +			if (end == pivot)
  30.136 +				pivot = p;
  30.137 +		}
  30.138 +	}
  30.139 +
  30.140 +	left = (start - base) / size;
  30.141 +	right = (base + nelem * size - end) / size;
  30.142 +	if (left > 1)
  30.143 +		__qsort_with_data(base, left, map, ctx);
  30.144 +	if (right > 1)
  30.145 +		__qsort_with_data(end, right, mend, ctx);
  30.146 +}
  30.147 +
  30.148 +uint32_t *
  30.149 +razor_qsort_with_data(void *base, size_t nelem, size_t size,
  30.150 +		      razor_compare_with_data_func_t compare, void *data)
  30.151 +{
  30.152 +	struct qsort_context ctx;
  30.153 +	uint32_t *map;
  30.154 +	int i;
  30.155 +
  30.156 +	if (nelem == 0)
  30.157 +		return NULL;
  30.158 +
  30.159 +	ctx.size = size;
  30.160 +	ctx.compare = compare;
  30.161 +	ctx.data = data;
  30.162 +
  30.163 +	map = malloc(nelem * sizeof (uint32_t));
  30.164 +	for (i = 0; i < nelem; i++)
  30.165 +		map[i] = i;
  30.166 +
  30.167 +	__qsort_with_data(base, nelem, map, &ctx);
  30.168 +
  30.169 +	return map;
  30.170 +}
    31.1 --- a/main.c	Sun Jun 15 18:16:20 2008 -0400
    31.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3 @@ -1,915 +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 -#include <stdlib.h>
   31.24 -#include <stddef.h>
   31.25 -#include <stdio.h>
   31.26 -#include <stdint.h>
   31.27 -#include <string.h>
   31.28 -#include <sys/stat.h>
   31.29 -#include <unistd.h>
   31.30 -#include <fcntl.h>
   31.31 -#include <dirent.h>
   31.32 -#include <curl/curl.h>
   31.33 -#include <fnmatch.h>
   31.34 -#include <errno.h>
   31.35 -#include "razor.h"
   31.36 -#include "razor-internal.h"
   31.37 -
   31.38 -static const char system_repo_filename[] = "system.repo";
   31.39 -static const char next_repo_filename[] = "system-next.repo";
   31.40 -static const char rawhide_repo_filename[] = "rawhide.repo";
   31.41 -static const char updated_repo_filename[] = "system-updated.repo";
   31.42 -static const char razor_root_path[] = "/var/lib/razor";
   31.43 -static const char root[] = "install";
   31.44 -static const char *repo_filename = system_repo_filename;
   31.45 -
   31.46 -static int
   31.47 -command_list(int argc, const char *argv[])
   31.48 -{
   31.49 -	struct razor_set *set;
   31.50 -	struct razor_package_iterator *pi;
   31.51 -	struct razor_package *package;
   31.52 -	const char *pattern, *name, *version, *arch;
   31.53 -	int only_names = 0, i = 0;
   31.54 -
   31.55 -	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
   31.56 -		only_names = 1;
   31.57 -		i++;
   31.58 -	}
   31.59 -
   31.60 -	pattern = argv[i];
   31.61 -	set = razor_set_open(repo_filename);
   31.62 -	pi = razor_package_iterator_create(set);
   31.63 -	while (razor_package_iterator_next(pi, &package,
   31.64 -					   &name, &version, &arch)) {
   31.65 -		if (pattern && fnmatch(pattern, name, 0) != 0)
   31.66 -			continue;
   31.67 -
   31.68 -		if (only_names)
   31.69 -			printf("%s\n", name);
   31.70 -		else
   31.71 -			printf("%s-%s.%s\n", name, version, arch);
   31.72 -	}
   31.73 -	razor_package_iterator_destroy(pi);
   31.74 -	razor_set_destroy(set);
   31.75 -
   31.76 -	return 0;
   31.77 -}
   31.78 -
   31.79 -static int
   31.80 -list_properties(const char *package_name,
   31.81 -		enum razor_property_type required_type)
   31.82 -{
   31.83 -	struct razor_set *set;
   31.84 -	struct razor_property *property;
   31.85 -	struct razor_package *package;
   31.86 -	struct razor_property_iterator *pi;
   31.87 -	const char *name, *version;
   31.88 -	enum razor_property_type type;
   31.89 -	enum razor_version_relation relation;
   31.90 -
   31.91 -	set = razor_set_open(repo_filename);
   31.92 -	if (package_name)
   31.93 -		package = razor_set_get_package(set, package_name);
   31.94 -	else
   31.95 -		package = NULL;
   31.96 -
   31.97 -	pi = razor_property_iterator_create(set, package);
   31.98 -	while (razor_property_iterator_next(pi, &property,
   31.99 -					    &name, &relation, &version,
  31.100 -					    &type)) {
  31.101 -		if (type != required_type)
  31.102 -			continue;
  31.103 -		if (version[0] == '\0')
  31.104 -			printf("%s\n", name);
  31.105 -		else
  31.106 -			printf("%s %s %s\n", name,
  31.107 -			       razor_version_relations[relation], version);
  31.108 -	}
  31.109 -	razor_property_iterator_destroy(pi);
  31.110 -
  31.111 -	razor_set_destroy(set);
  31.112 -
  31.113 -	return 0;
  31.114 -}
  31.115 -
  31.116 -static int
  31.117 -command_list_requires(int argc, const char *argv[])
  31.118 -{
  31.119 -	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
  31.120 -}
  31.121 -
  31.122 -static int
  31.123 -command_list_provides(int argc, const char *argv[])
  31.124 -{
  31.125 -	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
  31.126 -}
  31.127 -
  31.128 -static int
  31.129 -command_list_obsoletes(int argc, const char *argv[])
  31.130 -{
  31.131 -	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
  31.132 -}
  31.133 -
  31.134 -static int
  31.135 -command_list_conflicts(int argc, const char *argv[])
  31.136 -{
  31.137 -	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
  31.138 -}
  31.139 -
  31.140 -static int
  31.141 -command_list_files(int argc, const char *argv[])
  31.142 -{
  31.143 -	struct razor_set *set;
  31.144 -
  31.145 -	set = razor_set_open(repo_filename);
  31.146 -	razor_set_open_files(set, "system-files.repo");
  31.147 -	if (set == NULL)
  31.148 -		return 1;
  31.149 -	razor_set_list_files(set, argv[0]);
  31.150 -	razor_set_destroy(set);
  31.151 -
  31.152 -	return 0;
  31.153 -}
  31.154 -
  31.155 -static int
  31.156 -command_list_file_packages(int argc, const char *argv[])
  31.157 -{
  31.158 -	struct razor_set *set;
  31.159 -	struct razor_package_iterator *pi;
  31.160 -	struct razor_package *package;
  31.161 -	const char *name, *version, *arch;
  31.162 -
  31.163 -	set = razor_set_open(repo_filename);
  31.164 -	razor_set_open_files(set, "system-files.repo");
  31.165 -	if (set == NULL)
  31.166 -		return 1;
  31.167 -
  31.168 -	pi = razor_package_iterator_create_for_file(set, argv[0]);
  31.169 -	while (razor_package_iterator_next(pi, &package,
  31.170 -					   &name, &version, &arch))
  31.171 -		printf("%s-%s\n", name, version);
  31.172 -	razor_package_iterator_destroy(pi);
  31.173 -
  31.174 -	razor_set_destroy(set);
  31.175 -
  31.176 -	return 0;
  31.177 -}
  31.178 -
  31.179 -static int
  31.180 -command_list_package_files(int argc, const char *argv[])
  31.181 -{
  31.182 -	struct razor_set *set;
  31.183 -
  31.184 -	set = razor_set_open(repo_filename);
  31.185 -	razor_set_open_files(set, "system-files.repo");
  31.186 -	if (set == NULL)
  31.187 -		return 1;
  31.188 -	razor_set_list_package_files(set, argv[0]);
  31.189 -	razor_set_destroy(set);
  31.190 -
  31.191 -	return 0;
  31.192 -}
  31.193 -
  31.194 -static void
  31.195 -list_packages_for_property(struct razor_set *set,
  31.196 -			   struct razor_property *property)
  31.197 -{
  31.198 -	struct razor_package_iterator *pi;
  31.199 -	struct razor_package *package;
  31.200 -	const char *name, *version, *arch;
  31.201 -
  31.202 -	pi = razor_package_iterator_create_for_property(set, property);
  31.203 -	while (razor_package_iterator_next(pi, &package,
  31.204 -					   &name, &version, &arch))
  31.205 -		printf("%s-%s.%s\n", name, version, arch);
  31.206 -	razor_package_iterator_destroy(pi);
  31.207 -}
  31.208 -
  31.209 -static int
  31.210 -list_property_packages(const char *ref_name,
  31.211 -		       const char *ref_version,
  31.212 -		       enum razor_property_type ref_type)
  31.213 -{
  31.214 -	struct razor_set *set;
  31.215 -	struct razor_property *property;
  31.216 -	struct razor_property_iterator *pi;
  31.217 -	const char *name, *version;
  31.218 -	enum razor_property_type type;
  31.219 -	enum razor_version_relation relation;
  31.220 -
  31.221 -	if (ref_name == NULL)
  31.222 -		return 0;
  31.223 -
  31.224 -	set = razor_set_open(repo_filename);
  31.225 -	if (set == NULL)
  31.226 -		return 1;
  31.227 -
  31.228 -	pi = razor_property_iterator_create(set, NULL);
  31.229 -	while (razor_property_iterator_next(pi, &property,
  31.230 -					    &name, &relation, &version,
  31.231 -					    &type)) {
  31.232 -		if (strcmp(ref_name, name) != 0)
  31.233 -			continue;
  31.234 -		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
  31.235 -		    strcmp(ref_version, version) != 0)
  31.236 -			continue;
  31.237 -		if (ref_type != type)
  31.238 -			continue;
  31.239 -
  31.240 -		list_packages_for_property(set, property);
  31.241 -	}
  31.242 -	razor_property_iterator_destroy(pi);
  31.243 -
  31.244 -	return 0;
  31.245 -}
  31.246 -
  31.247 -static int
  31.248 -command_what_requires(int argc, const char *argv[])
  31.249 -{
  31.250 -	return list_property_packages(argv[0], argv[1],
  31.251 -				      RAZOR_PROPERTY_REQUIRES);
  31.252 -}
  31.253 -
  31.254 -static int
  31.255 -command_what_provides(int argc, const char *argv[])
  31.256 -{
  31.257 -	return list_property_packages(argv[0], argv[1],
  31.258 -				      RAZOR_PROPERTY_PROVIDES);
  31.259 -}
  31.260 -
  31.261 -static int
  31.262 -show_progress(void *clientp,
  31.263 -	      double dltotal, double dlnow, double ultotal, double ulnow)
  31.264 -{
  31.265 -	const char *file = clientp;
  31.266 -
  31.267 -	if (!dlnow < dltotal)
  31.268 -		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
  31.269 -			file, (int) dlnow / 1024, (int) dltotal / 1024);
  31.270 -
  31.271 -	return 0;
  31.272 -}
  31.273 -
  31.274 -static int
  31.275 -download_if_missing(const char *url, const char *file)
  31.276 -{
  31.277 -	CURL *curl;
  31.278 -	struct stat buf;
  31.279 -	char error[256];
  31.280 -	FILE *fp;
  31.281 -	CURLcode res;
  31.282 -	long response;
  31.283 -
  31.284 -	curl = curl_easy_init();
  31.285 -	if (curl == NULL)
  31.286 -		return 1;
  31.287 -
  31.288 -	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
  31.289 -	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  31.290 -	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
  31.291 -	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
  31.292 -
  31.293 -	if (stat(file, &buf) < 0) {
  31.294 -		fp = fopen(file, "w");
  31.295 -		if (fp == NULL) {
  31.296 -			fprintf(stderr,
  31.297 -				"failed to open %s for writing\n", file);
  31.298 -			return -1;
  31.299 -		}
  31.300 -		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  31.301 -		curl_easy_setopt(curl, CURLOPT_URL, url);
  31.302 -		res = curl_easy_perform(curl);
  31.303 -		fclose(fp);
  31.304 -		if (res != CURLE_OK) {
  31.305 -			fprintf(stderr, "curl error: %s\n", error);
  31.306 -			unlink(file);
  31.307 -			return -1;
  31.308 -		}
  31.309 -		res = curl_easy_getinfo(curl,
  31.310 -					CURLINFO_RESPONSE_CODE, &response);
  31.311 -		if (res != CURLE_OK) {
  31.312 -			fprintf(stderr, "curl error: %s\n", error);
  31.313 -                        unlink(file);
  31.314 -                        return -1;
  31.315 -		}
  31.316 -		if (response != 200) {
  31.317 -			fprintf(stderr, " - failed %ld\n", response);
  31.318 -                        unlink(file);
  31.319 -                        return -1;
  31.320 -		}
  31.321 -		fprintf(stderr, "\n");
  31.322 -	}
  31.323 -
  31.324 -	curl_easy_cleanup(curl);
  31.325 -
  31.326 -	return 0;
  31.327 -}
  31.328 -
  31.329 -#define REPO_URL "http://download.fedora.redhat.com" \
  31.330 -	"/pub/fedora/linux/development/i386/os"
  31.331 -
  31.332 -static int
  31.333 -command_import_yum(int argc, const char *argv[])
  31.334 -{
  31.335 -	struct razor_set *set;
  31.336 -
  31.337 -	if (download_if_missing(REPO_URL "/repodata/primary.xml.gz",
  31.338 -				"primary.xml.gz") < 0)
  31.339 -		return -1;
  31.340 -	if (download_if_missing(REPO_URL "/repodata/filelists.xml.gz",
  31.341 -				"filelists.xml.gz") < 0)
  31.342 -		return -1;
  31.343 -
  31.344 -	set = razor_set_create_from_yum();
  31.345 -	if (set == NULL)
  31.346 -		return 1;
  31.347 -	razor_set_write(set, rawhide_repo_filename, RAZOR_REPO_FILE_MAIN);
  31.348 -	razor_set_write(set, "rawhide-details.repo", RAZOR_REPO_FILE_DETAILS);
  31.349 -	razor_set_write(set, "rawhide-files.repo", RAZOR_REPO_FILE_FILES);
  31.350 -	razor_set_destroy(set);
  31.351 -	printf("wrote %s\n", rawhide_repo_filename);
  31.352 -
  31.353 -	return 0;
  31.354 -}
  31.355 -
  31.356 -static int
  31.357 -command_import_rpmdb(int argc, const char *argv[])
  31.358 -{
  31.359 -	struct razor_set *set;
  31.360 -
  31.361 -	set = razor_set_create_from_rpmdb();
  31.362 -	if (set == NULL)
  31.363 -		return 1;
  31.364 -	razor_set_write(set, repo_filename, RAZOR_REPO_FILE_MAIN);
  31.365 -	razor_set_write(set, "system-details.repo", RAZOR_REPO_FILE_DETAILS);
  31.366 -	razor_set_write(set, "system-files.repo", RAZOR_REPO_FILE_FILES);
  31.367 -	razor_set_destroy(set);
  31.368 -	printf("wrote %s\n", repo_filename);
  31.369 -
  31.370 -	return 0;
  31.371 -}
  31.372 -
  31.373 -static int
  31.374 -command_validate(int argc, const char *argv[])
  31.375 -{
  31.376 -	struct razor_set *set;
  31.377 -
  31.378 -	set = razor_set_open(repo_filename);
  31.379 -	if (set == NULL)
  31.380 -		return 1;
  31.381 -	razor_set_list_unsatisfied(set);
  31.382 -	razor_set_destroy(set);
  31.383 -
  31.384 -	return 0;
  31.385 -}
  31.386 -
  31.387 -static int
  31.388 -mark_packages_for_update(struct razor_transaction *trans,
  31.389 -			 struct razor_set *set, const char *pattern)
  31.390 -{
  31.391 -	struct razor_package_iterator *pi;
  31.392 -	struct razor_package *package;
  31.393 -	const char *name, *version, *arch;
  31.394 -	int matches = 0;
  31.395 -
  31.396 -	pi = razor_package_iterator_create(set);
  31.397 -	while (razor_package_iterator_next(pi, &package,
  31.398 -					   &name, &version, &arch)) {
  31.399 -		if (pattern && fnmatch(pattern, name, 0) == 0) {
  31.400 -			razor_transaction_install_package(trans, package);
  31.401 -			matches++;
  31.402 -		}
  31.403 -	}
  31.404 -	razor_package_iterator_destroy(pi);
  31.405 -
  31.406 -	return matches;
  31.407 -}
  31.408 -
  31.409 -static int
  31.410 -mark_packages_for_removal(struct razor_transaction *trans,
  31.411 -			  struct razor_set *set, const char *pattern)
  31.412 -{
  31.413 -	struct razor_package_iterator *pi;
  31.414 -	struct razor_package *package;
  31.415 -	const char *name, *version, *arch;
  31.416 -	int matches = 0;
  31.417 -
  31.418 -	pi = razor_package_iterator_create(set);
  31.419 -	while (razor_package_iterator_next(pi, &package,
  31.420 -					   &name, &version, &arch)) {
  31.421 -		if (pattern && fnmatch(pattern, name, 0) == 0) {
  31.422 -			razor_transaction_remove_package(trans, package);
  31.423 -			matches++;
  31.424 -		}
  31.425 -	}
  31.426 -	razor_package_iterator_destroy(pi);
  31.427 -
  31.428 -	return matches;
  31.429 -}
  31.430 -
  31.431 -static int
  31.432 -command_update(int argc, const char *argv[])
  31.433 -{
  31.434 -	struct razor_set *set, *upstream;
  31.435 -	struct razor_transaction *trans;
  31.436 -	int i, errors;
  31.437 -
  31.438 -	set = razor_set_open(repo_filename);
  31.439 -	upstream = razor_set_open(rawhide_repo_filename);
  31.440 -	if (set == NULL || upstream == NULL)
  31.441 -		return 1;
  31.442 -
  31.443 -	trans = razor_transaction_create(set, upstream);
  31.444 -	if (argc == 0)
  31.445 -		razor_transaction_update_all(trans);
  31.446 -	for (i = 0; i < argc; i++) {
  31.447 -		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
  31.448 -			fprintf(stderr, "no match for %s\n", argv[i]);
  31.449 -			return 1;
  31.450 -		}
  31.451 -	}
  31.452 -		
  31.453 -	errors = razor_transaction_resolve(trans);
  31.454 -	if (errors)
  31.455 -		return 1;
  31.456 -
  31.457 -	set = razor_transaction_finish(trans);
  31.458 -	razor_set_write(set, updated_repo_filename, RAZOR_REPO_FILE_MAIN);
  31.459 -	razor_set_destroy(set);
  31.460 -	razor_set_destroy(upstream);
  31.461 -	printf("wrote system-updated.repo\n");
  31.462 -
  31.463 -	return 0;
  31.464 -}
  31.465 -
  31.466 -static int
  31.467 -command_remove(int argc, const char *argv[])
  31.468 -{
  31.469 -	struct razor_set *set;
  31.470 -	struct razor_transaction *trans;
  31.471 -	int i, errors;
  31.472 -
  31.473 -	set = razor_set_open(repo_filename);
  31.474 -	if (set == NULL)
  31.475 -		return 1;
  31.476 -
  31.477 -	trans = razor_transaction_create(set, NULL);
  31.478 -	for (i = 0; i < argc; i++) {
  31.479 -		if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
  31.480 -			fprintf(stderr, "no match for %s\n", argv[i]);
  31.481 -			return 1;
  31.482 -		}
  31.483 -	}
  31.484 -
  31.485 -	errors = razor_transaction_resolve(trans);
  31.486 -	if (errors)
  31.487 -		return 1;
  31.488 -
  31.489 -	set = razor_transaction_finish(trans);
  31.490 -	razor_set_write(set, updated_repo_filename, RAZOR_REPO_FILE_MAIN);
  31.491 -	razor_set_destroy(set);
  31.492 -	printf("wrote system-updated.repo\n");
  31.493 -
  31.494 -	return 0;
  31.495 -}
  31.496 -
  31.497 -static void
  31.498 -print_diff(const char *name,
  31.499 -	   const char *old_version, const char *new_version, const char *arch,
  31.500 -	   void *data)
  31.501 -{
  31.502 -	if (old_version)
  31.503 -		printf("removing %s %s\n", name, old_version);
  31.504 -	else
  31.505 -		printf("install %s %s\n", name, new_version);
  31.506 -}
  31.507 -
  31.508 -static int
  31.509 -command_diff(int argc, const char *argv[])
  31.510 -{
  31.511 -	struct razor_set *set, *updated;
  31.512 -
  31.513 -	set = razor_set_open(repo_filename);
  31.514 -	updated = razor_set_open(updated_repo_filename);
  31.515 -	if (set == NULL || updated == NULL)
  31.516 -		return 1;
  31.517 -
  31.518 -	razor_set_diff(set, updated, print_diff, NULL);	
  31.519 -
  31.520 -	razor_set_destroy(set);
  31.521 -	razor_set_destroy(updated);
  31.522 -
  31.523 -	return 0;
  31.524 -}
  31.525 -
  31.526 -static int
  31.527 -command_import_rpms(int argc, const char *argv[])
  31.528 -{
  31.529 -	DIR *dir;
  31.530 -	struct dirent *de;
  31.531 -	struct razor_importer *importer;
  31.532 -	struct razor_set *set;
  31.533 -	struct razor_rpm *rpm;
  31.534 -	int len;
  31.535 -	char filename[256];
  31.536 -	const char *dirname = argv[0];
  31.537 -
  31.538 -	if (dirname == NULL) {
  31.539 -		fprintf(stderr, "usage: razor import-rpms DIR\n");
  31.540 -		return -1;
  31.541 -	}
  31.542 -
  31.543 -	dir = opendir(dirname);
  31.544 -	if (dir == NULL) {
  31.545 -		fprintf(stderr, "couldn't read dir %s\n", dirname);
  31.546 -		return -1;
  31.547 -	}
  31.548 -
  31.549 -	importer = razor_importer_new();
  31.550 -
  31.551 -	while (de = readdir(dir), de != NULL) {
  31.552 -		len = strlen(de->d_name);
  31.553 -		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
  31.554 -		    continue;
  31.555 -		snprintf(filename, sizeof filename,
  31.556 -			 "%s/%s", dirname, de->d_name);
  31.557 -		rpm = razor_rpm_open(filename);
  31.558 -		if (rpm == NULL) {
  31.559 -			fprintf(stderr,
  31.560 -				"failed to open rpm \"%s\"\n", filename);
  31.561 -			continue;
  31.562 -		}
  31.563 -		if (razor_importer_add_rpm(importer, rpm)) {
  31.564 -			fprintf(stderr, "couldn't import %s\n", filename);
  31.565 -			break;
  31.566 -		}
  31.567 -		razor_rpm_close(rpm);
  31.568 -	}
  31.569 -
  31.570 -	if (de != NULL) {
  31.571 -		razor_importer_destroy(importer);
  31.572 -		return -1;
  31.573 -	}
  31.574 -
  31.575 -	set = razor_importer_finish(importer);
  31.576 -
  31.577 -	razor_set_write(set, repo_filename, RAZOR_REPO_FILE_MAIN);
  31.578 -	razor_set_destroy(set);
  31.579 -	printf("wrote %s\n", repo_filename);
  31.580 -
  31.581 -	return 0;
  31.582 -}
  31.583 -
  31.584 -static void
  31.585 -download_package(const char *name,
  31.586 -		 const char *old_version,
  31.587 -		 const char *new_version,
  31.588 -		 const char *arch,
  31.589 -		 void *data)
  31.590 -{
  31.591 -	char file[PATH_MAX], url[256];
  31.592 -	const char *v;
  31.593 -	int *errors = data;
  31.594 -
  31.595 -	if (old_version)
  31.596 -		return;
  31.597 -
  31.598 -	/* Skip epoch */
  31.599 -	v = strchr(new_version, ':');
  31.600 -	if (v != NULL)
  31.601 -		v = v + 1;
  31.602 -	else
  31.603 -		v = new_version;
  31.604 -
  31.605 -	snprintf(url, sizeof url,
  31.606 -		 REPO_URL "/Packages/%s-%s.%s.rpm", name, v, arch);
  31.607 -	snprintf(file, sizeof file,
  31.608 -		 "rpms/%s-%s.%s.rpm", name, v, arch);
  31.609 -	if (download_if_missing(url, file) < 0)
  31.610 -		(*errors)++;
  31.611 -}
  31.612 -
  31.613 -static void
  31.614 -install_package(const char *name,
  31.615 -		const char *old_version,
  31.616 -		const char *new_version,
  31.617 -		const char *arch,
  31.618 -		void *data)
  31.619 -{
  31.620 -	const char *v, *root = data;
  31.621 -	char file[PATH_MAX];
  31.622 -	struct razor_rpm *rpm;
  31.623 -
  31.624 -	if (old_version) {
  31.625 -		printf("removing %s %s not handled\n", name, old_version);
  31.626 -		return;
  31.627 -	}
  31.628 -
  31.629 -	/* Skip epoch */
  31.630 -	v = strchr(new_version, ':');
  31.631 -	if (v != NULL)
  31.632 -		v = v + 1;
  31.633 -	else
  31.634 -		v = new_version;
  31.635 -
  31.636 -	printf("install %s %s\n", name, v);
  31.637 -	snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
  31.638 -
  31.639 - 	rpm = razor_rpm_open(file);
  31.640 -	if (rpm == NULL) {
  31.641 -		fprintf(stderr, "failed to open rpm %s\n", file);
  31.642 -		return;
  31.643 -	}
  31.644 -	if (razor_rpm_install(rpm, root) < 0) {
  31.645 -		fprintf(stderr,
  31.646 -			"failed to install rpm %s\n", file);
  31.647 -		return;
  31.648 -	}
  31.649 -	razor_rpm_close(rpm);
  31.650 -}
  31.651 -
  31.652 -static int
  31.653 -command_install(int argc, const char *argv[])
  31.654 -{
  31.655 -	struct razor_set *system, *upstream, *next;
  31.656 -	struct razor_transaction *trans;
  31.657 -	char path[PATH_MAX], new_path[PATH_MAX];
  31.658 -	int i = 0, errors, fd, dependencies = 1;
  31.659 -
  31.660 -	if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
  31.661 -		dependencies = 0;
  31.662 -		i++;
  31.663 -	}
  31.664 -
  31.665 -	/* Create the new next repo file up front to ensure exclusive
  31.666 -	 * access. */
  31.667 -	snprintf(new_path, sizeof new_path,
  31.668 -		 "%s%s/%s", root, razor_root_path, next_repo_filename);
  31.669 -	fd = open(new_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
  31.670 -	if (fd < 0) {
  31.671 -		fprintf(stderr, "failed to get lock file, "
  31.672 -			"maybe previous operation crashed?\n");
  31.673 -
  31.674 -		/* FIXME: Use fcntl advisory locking to figure out
  31.675 -		 * whether previous operation crashed or is still in
  31.676 -		 * progress. */
  31.677 -
  31.678 -		return -1;
  31.679 -	}
  31.680 -
  31.681 -	upstream = razor_set_open(rawhide_repo_filename);
  31.682 -	snprintf(path, sizeof path,
  31.683 -		 "%s%s/%s", root, razor_root_path, system_repo_filename);
  31.684 -	system = razor_set_open(path);
  31.685 -	if (system == NULL || upstream == NULL) {
  31.686 -		unlink(new_path);
  31.687 -		return 1;
  31.688 -	}
  31.689 -	trans = razor_transaction_create(system, upstream);
  31.690 -	for (; i < argc; i++) {
  31.691 -		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
  31.692 -			fprintf(stderr, "no package matched %s\n", argv[i]);
  31.693 -			unlink(new_path);
  31.694 -			return 1;
  31.695 -		}
  31.696 -	}
  31.697 -
  31.698 -	if (dependencies) {
  31.699 -		errors = razor_transaction_resolve(trans);
  31.700 -		if (errors) {
  31.701 -			unlink(new_path);
  31.702 -			return 1;
  31.703 -		}
  31.704 -	}
  31.705 -
  31.706 -	next = razor_transaction_finish(trans);
  31.707 -
  31.708 -	razor_set_write_to_fd(next, fd, RAZOR_REPO_FILE_MAIN);
  31.709 -	printf("wrote %s\n", new_path);
  31.710 -
  31.711 -	if (mkdir("rpms", 0777) && errno != EEXIST) {
  31.712 -		fprintf(stderr, "failed to create rpms directory.\n");
  31.713 -		return 1;
  31.714 -	}
  31.715 -
  31.716 -	razor_set_diff(system, next, download_package, &errors);
  31.717 -	if (errors > 0) {
  31.718 -		fprintf(stderr, "failed to download %d packages\n", errors);
  31.719 -		unlink(new_path);
  31.720 -                return 1;
  31.721 -        }
  31.722 -
  31.723 -	/* FIXME: We need to figure out the right install order here,
  31.724 -	 * so the post and pre scripts can run. */
  31.725 -	razor_set_diff(system, next, install_package, (void *) root);
  31.726 -
  31.727 -	razor_set_destroy(next);
  31.728 -	razor_set_destroy(system);
  31.729 -	razor_set_destroy(upstream);
  31.730 -
  31.731 -	/* Make it so. */
  31.732 -	rename(new_path, path);
  31.733 -	printf("renamed %s to %s\n", new_path, path);
  31.734 -
  31.735 -	return 0;
  31.736 -}
  31.737 -
  31.738 -static int
  31.739 -command_init(int argc, const char *argv[])
  31.740 -{
  31.741 -	struct stat buf;
  31.742 -	struct razor_set *set;
  31.743 -	char path[PATH_MAX];
  31.744 -
  31.745 -	if (stat(root, &buf) < 0) {
  31.746 -		if (mkdir(root, 0777) < 0) {
  31.747 -			fprintf(stderr,
  31.748 -				"could not create install root \"%s\"\n",
  31.749 -				root);
  31.750 -			return -1;
  31.751 -		}
  31.752 -		fprintf(stderr, "created install root \"%s\"\n", root);
  31.753 -	} else if (!S_ISDIR(buf.st_mode)) {
  31.754 -		fprintf(stderr,
  31.755 -			"install root \"%s\" exists, but is not a directory\n",
  31.756 -			root);
  31.757 -		return -1;
  31.758 -	}
  31.759 -
  31.760 -	snprintf(path, sizeof path, "%s/%s",
  31.761 -		 razor_root_path, system_repo_filename);
  31.762 -	if (razor_create_dir(root, path) < 0) {
  31.763 -		fprintf(stderr, "could not create %s%s\n",
  31.764 -			root, razor_root_path);
  31.765 -		return -1;
  31.766 -	}
  31.767 -
  31.768 -	set = razor_set_create();
  31.769 -	snprintf(path, sizeof path, "%s%s/%s",
  31.770 -		 root, razor_root_path, system_repo_filename);
  31.771 -	if (razor_set_write(set, path, RAZOR_REPO_FILE_MAIN) < 0) {
  31.772 -		fprintf(stderr, "could not write initial package set\n");
  31.773 -		return -1;
  31.774 -	}
  31.775 -	razor_set_destroy(set);
  31.776 -
  31.777 -	return 0;
  31.778 -}
  31.779 -
  31.780 -static int
  31.781 -command_download(int argc, const char *argv[])
  31.782 -{
  31.783 -	struct razor_set *set;
  31.784 -	struct razor_package_iterator *pi;
  31.785 -	struct razor_package *package;
  31.786 -	const char *pattern = argv[0], *name, *version, *arch;
  31.787 -	char url[256], file[256];
  31.788 -	int matches = 0;
  31.789 -
  31.790 -	if (mkdir("rpms", 0777) && errno != EEXIST) {
  31.791 -		fprintf(stderr, "failed to create rpms directory.\n");
  31.792 -		return 1;
  31.793 -	}
  31.794 -
  31.795 -	set = razor_set_open(rawhide_repo_filename);
  31.796 -	pi = razor_package_iterator_create(set);
  31.797 -	while (razor_package_iterator_next(pi, &package,
  31.798 -					   &name, &version, &arch)) {
  31.799 -		if (pattern && fnmatch(pattern, name, 0) != 0)
  31.800 -			continue;
  31.801 -
  31.802 -		matches++;
  31.803 -		snprintf(url, sizeof url,
  31.804 -			 REPO_URL "/Packages/%s-%s.%s.rpm",
  31.805 -			 name, version, arch);
  31.806 -		snprintf(file, sizeof file,
  31.807 -			 "rpms/%s-%s.%s.rpm", name, version, arch);
  31.808 -		download_if_missing(url, file);
  31.809 -	}
  31.810 -	razor_package_iterator_destroy(pi);
  31.811 -	razor_set_destroy(set);
  31.812 -
  31.813 -	if (matches == 0)
  31.814 -		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
  31.815 -	else if (matches == 1)
  31.816 -		fprintf(stderr, "downloaded 1 package\n");
  31.817 -	else
  31.818 -		fprintf(stderr, "downloaded %d packages\n", matches);
  31.819 -
  31.820 -	return 0;
  31.821 -}
  31.822 -
  31.823 -static int
  31.824 -command_info(int argc, const char *argv[])
  31.825 -{
  31.826 -	struct razor_set *set;
  31.827 -	struct razor_package_iterator *pi;
  31.828 -	struct razor_package *package;
  31.829 -	const char *pattern = argv[0], *name, *version, *arch;
  31.830 -	const char *summary, *description, *url, *license;
  31.831 -
  31.832 -	set = razor_set_open(repo_filename);
  31.833 -	razor_set_open_details(set, "system-details.repo");
  31.834 -	pi = razor_package_iterator_create(set);
  31.835 -	while (razor_package_iterator_next(pi, &package,
  31.836 -					   &name, &version, &arch)) {
  31.837 -		if (pattern && fnmatch(pattern, name, 0) != 0)
  31.838 -			continue;
  31.839 -
  31.840 -		razor_package_get_details (set, package, &summary, &description,
  31.841 -					   &url, &license);
  31.842 -
  31.843 -		printf ("Name:        %s\n", name);
  31.844 -		printf ("Arch:        %s\n", arch);
  31.845 -		printf ("Version:     %s\n", version);
  31.846 -		printf ("URL:         %s\n", url);
  31.847 -		printf ("License:     %s\n", license);
  31.848 -		printf ("Summary:     %s\n", summary);
  31.849 -		printf ("Description:\n");
  31.850 -		printf ("%s\n", description);
  31.851 -		printf ("\n");
  31.852 -	}
  31.853 -	razor_package_iterator_destroy(pi);
  31.854 -	razor_set_destroy(set);
  31.855 -
  31.856 -	return 0;
  31.857 -}
  31.858 -
  31.859 -static struct {
  31.860 -	const char *name;
  31.861 -	const char *description;
  31.862 -	int (*func)(int argc, const char *argv[]);
  31.863 -} razor_commands[] = {
  31.864 -	{ "list", "list all packages", command_list },
  31.865 -	{ "list-requires", "list all requires for the given package", command_list_requires },
  31.866 -	{ "list-provides", "list all provides for the given package", command_list_provides },
  31.867 -	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
  31.868 -	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
  31.869 -	{ "list-files", "list files for package set", command_list_files },
  31.870 -	{ "list-file-packages", "list packages owning file", command_list_file_packages },
  31.871 -	{ "list-package-files", "list files in package", command_list_package_files },
  31.872 -	{ "what-requires", "list the packages that have the given requires", command_what_requires },
  31.873 -	{ "what-provides", "list the packages that have the given provides", command_what_provides },
  31.874 -	{ "import-yum", "import yum metadata files", command_import_yum },
  31.875 -	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
  31.876 -	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
  31.877 -	{ "validate", "validate a package set", command_validate },
  31.878 -	{ "update", "update all or specified packages", command_update },
  31.879 -	{ "remove", "remove specified packages", command_remove },
  31.880 -	{ "diff", "show diff between two package sets", command_diff },
  31.881 -	{ "install", "install rpm", command_install },
  31.882 -	{ "init", "init razor root", command_init },
  31.883 -	{ "download", "download packages", command_download },
  31.884 -	{ "info", "display package details", command_info }
  31.885 -};
  31.886 -
  31.887 -static int
  31.888 -usage(void)
  31.889 -{
  31.890 -	int i;
  31.891 -
  31.892 -	printf("usage:\n");
  31.893 -	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  31.894 -		printf("  %-20s%s\n",
  31.895 -		       razor_commands[i].name, razor_commands[i].description);
  31.896 -
  31.897 -	return 1;
  31.898 -}
  31.899 -
  31.900 -int
  31.901 -main(int argc, const char *argv[])
  31.902 -{
  31.903 -	char *repo;
  31.904 -	int i;
  31.905 -
  31.906 -	repo = getenv("RAZOR_REPO");
  31.907 -	if (repo != NULL)
  31.908 -		repo_filename = repo;
  31.909 -
  31.910 -	if (argc < 2)
  31.911 -		return usage();
  31.912 -
  31.913 -	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  31.914 -		if (strcmp(razor_commands[i].name, argv[1]) == 0)
  31.915 -			return razor_commands[i].func(argc - 2, argv + 2);
  31.916 -
  31.917 -	return usage();
  31.918 -}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/po/.gitignore	Fri Jun 20 19:04:47 2008 -0400
    32.3 @@ -0,0 +1,4 @@
    32.4 +POTFILES
    32.5 +Makefile.in.in
    32.6 +stamp-it
    32.7 +
    33.1 --- a/razor-internal.h	Sun Jun 15 18:16:20 2008 -0400
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,19 +0,0 @@
    33.4 -#ifndef _RAZOR_INTERNAL_H_
    33.5 -#define _RAZOR_INTERNAL_H_
    33.6 -
    33.7 -#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
    33.8 -
    33.9 -/* Utility functions */
   33.10 -
   33.11 -int razor_create_dir(const char *root, const char *path);
   33.12 -int razor_write(int fd, const void *data, size_t size);
   33.13 -
   33.14 -
   33.15 -typedef int (*razor_compare_with_data_func_t)(const void *p1,
   33.16 -					      const void *p,
   33.17 -					      void *data);
   33.18 -uint32_t *
   33.19 -razor_qsort_with_data(void *base, size_t nelem, size_t size,
   33.20 -		      razor_compare_with_data_func_t compare, void *data);
   33.21 -
   33.22 -#endif /* _RAZOR_INTERNAL_H_ */
    34.1 --- a/razor.c	Sun Jun 15 18:16:20 2008 -0400
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,3244 +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 -#define _GNU_SOURCE
   34.24 -
   34.25 -#include <stdlib.h>
   34.26 -#include <stddef.h>
   34.27 -#include <stdint.h>
   34.28 -#include <stdio.h>
   34.29 -#include <string.h>
   34.30 -#include <sys/types.h>
   34.31 -#include <sys/stat.h>
   34.32 -#include <sys/mman.h>
   34.33 -#include <unistd.h>
   34.34 -#include <fcntl.h>
   34.35 -#include <errno.h>
   34.36 -#include <ctype.h>
   34.37 -#include <fnmatch.h>
   34.38 -
   34.39 -#include "razor.h"
   34.40 -#include "razor-internal.h"
   34.41 -#include "types.h"
   34.42 -
   34.43 -struct razor_set_section {
   34.44 -	uint32_t type;
   34.45 -	uint32_t offset;
   34.46 -	uint32_t size;
   34.47 -};
   34.48 -
   34.49 -struct razor_set_header {
   34.50 -	uint32_t magic;
   34.51 -	uint32_t version;
   34.52 -	struct razor_set_section sections[0];
   34.53 -};
   34.54 -
   34.55 -#define RAZOR_MAGIC 		0x7a7a7a7a
   34.56 -#define RAZOR_DETAILS_MAGIC 	0x7a7a7a7b
   34.57 -#define RAZOR_FILES_MAGIC 	0x7a7a7a7c
   34.58 -#define RAZOR_VERSION 1
   34.59 -
   34.60 -#define RAZOR_STRING_POOL		0
   34.61 -#define RAZOR_PACKAGES			1
   34.62 -#define RAZOR_PROPERTIES		2
   34.63 -#define RAZOR_PACKAGE_POOL		3
   34.64 -#define RAZOR_PROPERTY_POOL		4
   34.65 -
   34.66 -#define RAZOR_DETAILS_STRING_POOL	0
   34.67 -
   34.68 -#define RAZOR_FILES			0
   34.69 -#define RAZOR_FILE_POOL			1
   34.70 -#define RAZOR_FILE_STRING_POOL		2
   34.71 -
   34.72 -struct razor_package {
   34.73 -	uint name  : 24;
   34.74 -	uint flags : 8;
   34.75 -	uint32_t version;
   34.76 -	uint32_t arch;
   34.77 -	uint32_t summary;
   34.78 -	uint32_t description;
   34.79 -	uint32_t url;
   34.80 -	uint32_t license;
   34.81 -	struct list_head properties;
   34.82 -	struct list_head files;
   34.83 -};
   34.84 -
   34.85 -struct razor_property {
   34.86 -	uint name  : 24;
   34.87 -	uint flags : 6;
   34.88 -	enum razor_property_type type : 2;
   34.89 -	enum razor_version_relation relation : 32;
   34.90 -	uint32_t version;
   34.91 -	struct list_head packages;
   34.92 -};
   34.93 -
   34.94 -struct razor_entry {
   34.95 -	uint name  : 24;
   34.96 -	uint flags : 8;
   34.97 -	uint32_t start;
   34.98 -	struct list_head packages;
   34.99 -};
  34.100 -
  34.101 -#define RAZOR_ENTRY_LAST	0x80
  34.102 -
  34.103 -struct razor_set {
  34.104 -	struct array string_pool;
  34.105 - 	struct array packages;
  34.106 - 	struct array properties;
  34.107 - 	struct array files;
  34.108 -	struct array package_pool;
  34.109 - 	struct array property_pool;
  34.110 - 	struct array file_pool;
  34.111 -	struct array file_string_pool;
  34.112 -	struct array details_string_pool;
  34.113 -	struct razor_set_header *header;
  34.114 -	struct razor_set_header *details_header;
  34.115 -	struct razor_set_header *files_header;
  34.116 -};
  34.117 -
  34.118 -struct import_entry {
  34.119 -	uint32_t package;
  34.120 -	char *name;
  34.121 -};
  34.122 -
  34.123 -struct import_directory {
  34.124 -	uint32_t name, count;
  34.125 -	struct array files;
  34.126 -	struct array packages;
  34.127 -	struct import_directory *last;
  34.128 -};
  34.129 -
  34.130 -struct razor_importer {
  34.131 -	struct razor_set *set;
  34.132 -	struct hashtable table;
  34.133 -	struct hashtable file_table;
  34.134 -	struct hashtable details_table;
  34.135 -	struct razor_package *package;
  34.136 -	struct array properties;
  34.137 -	struct array files;
  34.138 -	struct array file_requires;
  34.139 -};
  34.140 -
  34.141 -static void *
  34.142 -zalloc(size_t size)
  34.143 -{
  34.144 -	void *p;
  34.145 -
  34.146 -	p = malloc(size);
  34.147 -	memset(p, 0, size);
  34.148 -
  34.149 -	return p;
  34.150 -}
  34.151 -
  34.152 -struct razor_set_section razor_sections[] = {
  34.153 -	{ RAZOR_STRING_POOL,		offsetof(struct razor_set, string_pool) },
  34.154 -	{ RAZOR_PACKAGES,		offsetof(struct razor_set, packages) },
  34.155 -	{ RAZOR_PROPERTIES,		offsetof(struct razor_set, properties) },
  34.156 -	{ RAZOR_PACKAGE_POOL,		offsetof(struct razor_set, package_pool) },
  34.157 -	{ RAZOR_PROPERTY_POOL,		offsetof(struct razor_set, property_pool) },
  34.158 -};
  34.159 -
  34.160 -struct razor_set_section razor_files_sections[] = {
  34.161 -	{ RAZOR_FILES,			offsetof(struct razor_set, files) },
  34.162 -	{ RAZOR_FILE_POOL,		offsetof(struct razor_set, file_pool) },
  34.163 -	{ RAZOR_FILE_STRING_POOL,	offsetof(struct razor_set, file_string_pool) },
  34.164 -};
  34.165 -
  34.166 -struct razor_set_section razor_details_sections[] = {
  34.167 -	{ RAZOR_DETAILS_STRING_POOL,	offsetof(struct razor_set, details_string_pool) },
  34.168 -};
  34.169 -
  34.170 -struct razor_set *
  34.171 -razor_set_create(void)
  34.172 -{
  34.173 -	struct razor_set *set;
  34.174 -	struct razor_entry *e;
  34.175 -	char *empty;
  34.176 -
  34.177 -	set = zalloc(sizeof *set);
  34.178 -
  34.179 -	e = array_add(&set->files, sizeof *e);
  34.180 -	empty = array_add(&set->string_pool, 1);
  34.181 -	*empty = '\0';
  34.182 -	empty = array_add(&set->file_string_pool, 1);
  34.183 -	*empty = '\0';
  34.184 -	empty = array_add(&set->details_string_pool, 1);
  34.185 -	*empty = '\0';
  34.186 -	e->name = 0;
  34.187 -	e->flags = RAZOR_ENTRY_LAST;
  34.188 -	e->start = 0;
  34.189 -	list_set_empty(&e->packages);
  34.190 -
  34.191 -	return set;
  34.192 -}
  34.193 -
  34.194 -struct razor_set *
  34.195 -razor_set_open(const char *filename)
  34.196 -{
  34.197 -	struct razor_set *set;
  34.198 -	struct razor_set_section *s;
  34.199 -	struct stat stat;
  34.200 -	struct array *array;
  34.201 -	int fd;
  34.202 -
  34.203 -	set = zalloc(sizeof *set);
  34.204 -	fd = open(filename, O_RDONLY);
  34.205 -	if (fstat(fd, &stat) < 0)
  34.206 -		return NULL;
  34.207 -	set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  34.208 -	if (set->header == MAP_FAILED) {
  34.209 -		free(set);
  34.210 -		return NULL;
  34.211 -	}
  34.212 -
  34.213 -	for (s = set->header->sections; ~s->type; s++) {
  34.214 -		if (s->type >= ARRAY_SIZE(razor_sections))
  34.215 -			continue;
  34.216 -		if (s->type != razor_sections[s->type].type)
  34.217 -			continue;
  34.218 -		array = (void *) set + razor_sections[s->type].offset;
  34.219 -		array->data = (void *) set->header + s->offset;
  34.220 -		array->size = s->size;
  34.221 -		array->alloc = s->size;
  34.222 -	}
  34.223 -	close(fd);
  34.224 -
  34.225 -	return set;
  34.226 -}
  34.227 -
  34.228 -void
  34.229 -razor_set_destroy(struct razor_set *set)
  34.230 -{
  34.231 -	unsigned int size;
  34.232 -	struct array *a;
  34.233 -	int i;
  34.234 -
  34.235 -	if (set->header) {
  34.236 -		for (i = 0; set->header->sections[i].type; i++)
  34.237 -			;
  34.238 -		size = set->header->sections[i].type;
  34.239 -		munmap(set->header, size);
  34.240 -	} else {
  34.241 -		for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
  34.242 -			a = (void *) set + razor_sections[i].offset;
  34.243 -			free(a->data);
  34.244 -		}
  34.245 -	}
  34.246 -
  34.247 -	if (set->details_header) {
  34.248 -		for (i = 0; set->details_header->sections[i].type; i++)
  34.249 -			;
  34.250 -		size = set->details_header->sections[i].type;
  34.251 -		munmap(set->details_header, size);
  34.252 -	} else {
  34.253 -		for (i = 0; i < ARRAY_SIZE(razor_details_sections); i++) {
  34.254 -			a = (void *) set + razor_details_sections[i].offset;
  34.255 -			free(a->data);
  34.256 -		}
  34.257 -	}
  34.258 -
  34.259 -	if (set->files_header) {
  34.260 -		for (i = 0; set->files_header->sections[i].type; i++)
  34.261 -			;
  34.262 -		size = set->files_header->sections[i].type;
  34.263 -		munmap(set->files_header, size);
  34.264 -	} else {
  34.265 -		for (i = 0; i < ARRAY_SIZE(razor_files_sections); i++) {
  34.266 -			a = (void *) set + razor_files_sections[i].offset;
  34.267 -			free(a->data);
  34.268 -		}
  34.269 -	}
  34.270 -
  34.271 -	free(set);
  34.272 -}
  34.273 -
  34.274 -void
  34.275 -razor_set_open_details(struct razor_set *set, const char *filename)
  34.276 -{
  34.277 -	struct razor_set_section *s;
  34.278 -	struct stat stat;
  34.279 -	struct array *array;
  34.280 -	int fd;
  34.281 -
  34.282 -	fd = open(filename, O_RDONLY);
  34.283 -	if (fstat(fd, &stat) < 0)
  34.284 -		return;
  34.285 -	set->details_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  34.286 -	if (set->details_header == MAP_FAILED)
  34.287 -		return;
  34.288 -
  34.289 -	for (s = set->details_header->sections; ~s->type; s++) {
  34.290 -		if (s->type >= ARRAY_SIZE(razor_details_sections))
  34.291 -			continue;
  34.292 -		if (s->type != razor_details_sections[s->type].type)
  34.293 -			continue;
  34.294 -		array = (void *) set + razor_details_sections[s->type].offset;
  34.295 -		array->data = (void *) set->details_header + s->offset;
  34.296 -		array->size = s->size;
  34.297 -		array->alloc = s->size;
  34.298 -	}
  34.299 -	close(fd);
  34.300 -}
  34.301 -
  34.302 -void
  34.303 -razor_set_open_files(struct razor_set *set, const char *filename)
  34.304 -{
  34.305 -	struct razor_set_section *s;
  34.306 -	struct stat stat;
  34.307 -	struct array *array;
  34.308 -	int fd;
  34.309 -
  34.310 -	fd = open(filename, O_RDONLY);
  34.311 -	if (fstat(fd, &stat) < 0)
  34.312 -		return;
  34.313 -	set->files_header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  34.314 -	if (set->files_header == MAP_FAILED)
  34.315 -		return;
  34.316 -
  34.317 -	for (s = set->files_header->sections; ~s->type; s++) {
  34.318 -		if (s->type >= ARRAY_SIZE(razor_files_sections))
  34.319 -			continue;
  34.320 -		if (s->type != razor_files_sections[s->type].type)
  34.321 -			continue;
  34.322 -		array = (void *) set + razor_files_sections[s->type].offset;
  34.323 -		array->data = (void *) set->files_header + s->offset;
  34.324 -		array->size = s->size;
  34.325 -		array->alloc = s->size;
  34.326 -	}
  34.327 -	close(fd);
  34.328 -}
  34.329 -
  34.330 -static int
  34.331 -razor_set_write_sections_to_fd(struct razor_set *set, int fd, int magic,
  34.332 -			       struct razor_set_section *sections,
  34.333 -			       size_t array_size)
  34.334 -{
  34.335 -	char data[4096];
  34.336 -	struct razor_set_header *header = (struct razor_set_header *) data;
  34.337 -	struct array *a;
  34.338 -	uint32_t offset;
  34.339 -	int i;
  34.340 -
  34.341 -	memset(data, 0, sizeof data);
  34.342 -	header->magic = magic;
  34.343 -	header->version = RAZOR_VERSION;
  34.344 -	offset = sizeof data;
  34.345 -
  34.346 -	for (i = 0; i < array_size; i++) {
  34.347 -		if (sections[i].type != i)
  34.348 -			continue;
  34.349 -		a = (void *) set + sections[i].offset;
  34.350 -		header->sections[i].type = i;
  34.351 -		header->sections[i].offset = offset;
  34.352 -		header->sections[i].size = a->size;
  34.353 -		offset += ALIGN(a->size, 4096);
  34.354 -	}
  34.355 -
  34.356 -	header->sections[i].type = ~0;
  34.357 -	header->sections[i].offset = 0;
  34.358 -	header->sections[i].size = 0;
  34.359 -
  34.360 -	razor_write(fd, data, sizeof data);
  34.361 -	memset(data, 0, sizeof data);
  34.362 -	for (i = 0; i < array_size; i++) {
  34.363 -		if (sections[i].type != i)
  34.364 -			continue;
  34.365 -		a = (void *) set + sections[i].offset;
  34.366 -		razor_write(fd, a->data, a->size);
  34.367 -		razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
  34.368 -	}
  34.369 -
  34.370 -	return 0;
  34.371 -}
  34.372 -
  34.373 -int
  34.374 -razor_set_write_to_fd(struct razor_set *set, int fd,
  34.375 -		      enum razor_repo_file_type type)
  34.376 -{
  34.377 -	switch (type) {
  34.378 -	case RAZOR_REPO_FILE_MAIN:
  34.379 -		return razor_set_write_sections_to_fd(set, fd, RAZOR_MAGIC,
  34.380 -						      razor_sections,
  34.381 -						      ARRAY_SIZE(razor_sections));
  34.382 -
  34.383 -	case RAZOR_REPO_FILE_DETAILS:
  34.384 -		return razor_set_write_sections_to_fd(set, fd, RAZOR_DETAILS_MAGIC,
  34.385 -						      razor_details_sections,
  34.386 -						      ARRAY_SIZE(razor_details_sections));
  34.387 -	case RAZOR_REPO_FILE_FILES:
  34.388 -		return razor_set_write_sections_to_fd(set, fd, RAZOR_FILES_MAGIC,
  34.389 -						      razor_files_sections,
  34.390 -						      ARRAY_SIZE(razor_files_sections));
  34.391 -	default:
  34.392 -		return -1;
  34.393 -	}
  34.394 -}
  34.395 -
  34.396 -int
  34.397 -razor_set_write(struct razor_set *set, const char *filename,
  34.398 -		enum razor_repo_file_type type)
  34.399 -{
  34.400 -	int fd, status;
  34.401 -
  34.402 -	fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
  34.403 -	if (fd < 0)
  34.404 -		return -1;
  34.405 -
  34.406 -	status = razor_set_write_to_fd(set, fd, type);
  34.407 -	if (status) {
  34.408 -	    close(fd);
  34.409 -	    return status;
  34.410 -	}
  34.411 -
  34.412 -	return close(fd);
  34.413 -}
  34.414 -
  34.415 -void
  34.416 -razor_build_evr(char *evr_buf, int size, const char *epoch,
  34.417 -		const char *version, const char *release)
  34.418 -{
  34.419 -	int len;
  34.420 -
  34.421 -	if (!version || !*version) {
  34.422 -		*evr_buf = '\0';
  34.423 -		return;
  34.424 -	}
  34.425 -
  34.426 -	if (epoch && *epoch && strcmp(epoch, "0") != 0) {
  34.427 -		len = snprintf(evr_buf, size, "%s:", epoch);
  34.428 -		evr_buf += len;
  34.429 -		size -= len;
  34.430 -	}
  34.431 -	len = snprintf(evr_buf, size, "%s", version);
  34.432 -	evr_buf += len;
  34.433 -	size -= len;
  34.434 -	if (release && *release)
  34.435 -		snprintf(evr_buf, size, "-%s", release);
  34.436 -}
  34.437 -
  34.438 -void
  34.439 -razor_importer_begin_package(struct razor_importer *importer,
  34.440 -			     const char *name,
  34.441 -			     const char *version,
  34.442 -			     const char *arch)
  34.443 -{
  34.444 -	struct razor_package *p;
  34.445 -
  34.446 -	p = array_add(&importer->set->packages, sizeof *p);
  34.447 -	p->name = hashtable_tokenize(&importer->table, name);
  34.448 -	p->flags = 0;
  34.449 -	p->version = hashtable_tokenize(&importer->table, version);
  34.450 -	p->arch = hashtable_tokenize(&importer->table, arch);
  34.451 -
  34.452 -	importer->package = p;
  34.453 -	array_init(&importer->properties);
  34.454 -}
  34.455 -
  34.456 -void
  34.457 -razor_importer_finish_package(struct razor_importer *importer)
  34.458 -{
  34.459 -	list_set_array(&importer->package->properties,
  34.460 -		       &importer->set->property_pool,
  34.461 -		       &importer->properties,
  34.462 -		       1);
  34.463 -
  34.464 -	array_release(&importer->properties);
  34.465 -}
  34.466 -
  34.467 -void
  34.468 -razor_importer_add_details(struct razor_importer *importer,
  34.469 -			   const char *summary,
  34.470 -			   const char *description,
  34.471 -			   const char *url,
  34.472 -			   const char *license)
  34.473 -{
  34.474 -	importer->package->summary = hashtable_tokenize(&importer->details_table, summary);
  34.475 -	importer->package->description = hashtable_tokenize(&importer->details_table, description);
  34.476 -	importer->package->url = hashtable_tokenize(&importer->details_table, url);
  34.477 -	importer->package->license = hashtable_tokenize(&importer->details_table, license);
  34.478 -}
  34.479 -
  34.480 -void
  34.481 -razor_importer_add_property(struct razor_importer *importer,
  34.482 -			    const char *name,
  34.483 -			    enum razor_version_relation relation,
  34.484 -			    const char *version,
  34.485 -			    enum razor_property_type type)
  34.486 -{
  34.487 -	struct razor_property *p;
  34.488 -	uint32_t *r;
  34.489 -
  34.490 -	p = array_add(&importer->set->properties, sizeof *p);
  34.491 -	p->name = hashtable_tokenize(&importer->table, name);
  34.492 -	p->flags = 0;
  34.493 -	p->type = type;
  34.494 -	p->relation = relation;
  34.495 -	p->version = hashtable_tokenize(&importer->table, version);
  34.496 -	list_set_ptr(&p->packages, importer->package -
  34.497 -		     (struct razor_package *) importer->set->packages.data);
  34.498 -
  34.499 -	r = array_add(&importer->properties, sizeof *r);
  34.500 -	*r = p - (struct razor_property *) importer->set->properties.data;
  34.501 -
  34.502 -	if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
  34.503 -		r = array_add(&importer->file_requires, sizeof *r);
  34.504 -		*r = p->name;
  34.505 -	}
  34.506 -}
  34.507 -
  34.508 -void
  34.509 -razor_importer_add_file(struct razor_importer *importer, const char *name)
  34.510 -{
  34.511 -	struct import_entry *e;
  34.512 -
  34.513 -	e = array_add(&importer->files, sizeof *e);
  34.514 -
  34.515 -	e->package = importer->package -
  34.516 -		(struct razor_package *) importer->set->packages.data;
  34.517 -	e->name = strdup(name);
  34.518 -}
  34.519 -
  34.520 -struct razor_importer *
  34.521 -razor_importer_new(void)
  34.522 -{
  34.523 -	struct razor_importer *importer;
  34.524 -
  34.525 -	importer = zalloc(sizeof *importer);
  34.526 -	importer->set = razor_set_create();
  34.527 -	hashtable_init(&importer->table, &importer->set->string_pool);
  34.528 -	hashtable_init(&importer->file_table, &importer->set->file_string_pool);
  34.529 -	hashtable_init(&importer->details_table, &importer->set->details_string_pool);
  34.530 -
  34.531 -	return importer;
  34.532 -}
  34.533 -
  34.534 -/* Destroy an importer without creating the set. */
  34.535 -void
  34.536 -razor_importer_destroy(struct razor_importer *importer)
  34.537 -{
  34.538 -	/* FIXME: write this */
  34.539 -}
  34.540 -
  34.541 -static int
  34.542 -versioncmp(const char *s1, const char *s2)
  34.543 -{
  34.544 -	const char *p1, *p2;
  34.545 -	long n1, n2;
  34.546 -	int res;
  34.547 -
  34.548 -	n1 = strtol(s1, (char **) &p1, 10);
  34.549 -	n2 = strtol(s2, (char **) &p2, 10);
  34.550 -
  34.551 -	/* Epoch; if one but not the other has an epoch set, default
  34.552 -	 * the epoch-less version to 0. */
  34.553 -	res = (*p1 == ':') - (*p2 == ':');
  34.554 -	if (res < 0) {
  34.555 -		n1 = 0;
  34.556 -		p1 = s1;
  34.557 -		p2++;
  34.558 -	} else if (res > 0) {
  34.559 -		p1++;
  34.560 -		n2 = 0;
  34.561 -		p2 = s2;
  34.562 -	}
  34.563 -
  34.564 -	if (n1 != n2)
  34.565 -		return n1 - n2;
  34.566 -	while (*p1 && *p2) {
  34.567 -		if (*p1 != *p2)
  34.568 -			return *p1 - *p2;
  34.569 -		p1++;
  34.570 -		p2++;
  34.571 -		if (isdigit(*p1) && isdigit(*p2))
  34.572 -			return versioncmp(p1, p2);
  34.573 -	}
  34.574 -
  34.575 -	return *p1 - *p2;
  34.576 -}
  34.577 -
  34.578 -static int
  34.579 -compare_packages(const void *p1, const void *p2, void *data)
  34.580 -{
  34.581 -	const struct razor_package *pkg1 = p1, *pkg2 = p2;
  34.582 -	struct razor_set *set = data;
  34.583 -	char *pool = set->string_pool.data;
  34.584 -
  34.585 -	/* FIXME: what if the flags are different? */
  34.586 -	if (pkg1->name == pkg2->name)
  34.587 -		return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
  34.588 -	else
  34.589 -		return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
  34.590 -}
  34.591 -
  34.592 -static int
  34.593 -compare_properties(const void *p1, const void *p2, void *data)
  34.594 -{
  34.595 -	const struct razor_property *prop1 = p1, *prop2 = p2;
  34.596 -	struct razor_set *set = data;
  34.597 -	char *pool = set->string_pool.data;
  34.598 -
  34.599 -	if (prop1->name != prop2->name) 
  34.600 -		return strcmp(&pool[prop1->name], &pool[prop2->name]);
  34.601 -	else if (prop1->type != prop2->type)
  34.602 -		return prop1->type - prop2->type;
  34.603 -	else if (prop1->relation != prop2->relation)
  34.604 -		return prop1->relation - prop2->relation;
  34.605 -	else
  34.606 -		return versioncmp(&pool[prop1->version], &pool[prop2->version]);
  34.607 -}
  34.608 -
  34.609 -static uint32_t *
  34.610 -uniqueify_properties(struct razor_set *set)
  34.611 -{
  34.612 -	struct razor_property *rp, *up, *rp_end;
  34.613 -	struct array *pkgs, *p;
  34.614 -	struct list_head *r;
  34.615 -	uint32_t *map, *rmap;
  34.616 -	int i, count, unique;
  34.617 -
  34.618 -	count = set->properties.size / sizeof(struct razor_property);
  34.619 -	map = razor_qsort_with_data(set->properties.data,
  34.620 -				    count,
  34.621 -				    sizeof(struct razor_property),
  34.622 -				    compare_properties,
  34.623 -				    set);
  34.624 -
  34.625 -	rp_end = set->properties.data + set->properties.size;
  34.626 -	rmap = malloc(count * sizeof *map);
  34.627 -	pkgs = zalloc(count * sizeof *pkgs);
  34.628 -	for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
  34.629 -		if (rp->name != up->name || rp->type != up->type ||
  34.630 -		    rp->relation != up->relation || rp->version != up->version) {
  34.631 -			up++;
  34.632 -			up->name = rp->name;
  34.633 -			up->flags = 0;
  34.634 -			up->type = rp->type;
  34.635 -			up->relation = rp->relation;
  34.636 -			up->version = rp->version;
  34.637 -		}
  34.638 -
  34.639 -		unique = up - (struct razor_property *) set->properties.data;
  34.640 -		rmap[map[i]] = unique;
  34.641 -		r = array_add(&pkgs[unique], sizeof *r);
  34.642 -		*r = rp->packages;
  34.643 -	}
  34.644 -	free(map);
  34.645 -
  34.646 -	if (up != rp)
  34.647 -		up++;
  34.648 -	set->properties.size = (void *) up - set->properties.data;
  34.649 -	rp_end = up;
  34.650 -	for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
  34.651 -		list_set_array(&rp->packages, &set->package_pool, p, 0);
  34.652 -		array_release(p);
  34.653 -	}
  34.654 -
  34.655 -	free(pkgs);
  34.656 -
  34.657 -	return rmap;
  34.658 -}
  34.659 -
  34.660 -static int
  34.661 -compare_filenames(const void *p1, const void *p2, void *data)
  34.662 -{
  34.663 -	const struct import_entry *e1 = p1;
  34.664 -	const struct import_entry *e2 = p2;
  34.665 -	const char *n1 = e1->name;
  34.666 -	const char *n2 = e2->name;
  34.667 -
  34.668 -	/* Need to make sure that the contents of a directory
  34.669 -	 * are sorted immediately after it. So "foo/bar" has to
  34.670 -	 * sort before "foo.conf"
  34.671 -	 *
  34.672 -	 * FIXME: this is about 60% slower than strcmp
  34.673 -	 */
  34.674 -	while (*n1 && *n2) {
  34.675 -		if (*n1 < *n2)
  34.676 -			return *n2 == '/' ? 1 : -1;
  34.677 -		else if (*n1 > *n2)
  34.678 -			return *n1 == '/' ? -1 : 1;
  34.679 -		n1++;
  34.680 -		n2++;
  34.681 -	}
  34.682 -	if (*n1)
  34.683 -		return 1;
  34.684 -	else if (*n2)
  34.685 -		return -1;
  34.686 -	else
  34.687 -		return 0;
  34.688 -}
  34.689 -
  34.690 -static void
  34.691 -count_entries(struct import_directory *d)
  34.692 -{
  34.693 -	struct import_directory *p, *end;
  34.694 -
  34.695 -	p = d->files.data;
  34.696 -	end = d->files.data + d->files.size;
  34.697 -	d->count = 0;
  34.698 -	while (p < end) {
  34.699 -		count_entries(p);
  34.700 -		d->count += p->count + 1;
  34.701 -		p++;
  34.702 -	}		
  34.703 -}
  34.704 -
  34.705 -static void
  34.706 -serialize_files(struct razor_set *set,
  34.707 -		struct import_directory *d, struct array *array)
  34.708 -{
  34.709 -	struct import_directory *p, *end;
  34.710 -	struct razor_entry *e = NULL;
  34.711 -	uint32_t s;
  34.712 -
  34.713 -	p = d->files.data;
  34.714 -	end = d->files.data + d->files.size;
  34.715 -	s = array->size / sizeof *e + d->files.size / sizeof *p;
  34.716 -	while (p < end) {
  34.717 -		e = array_add(array, sizeof *e);
  34.718 -		e->name = p->name;
  34.719 -		e->flags = 0;
  34.720 -		e->start = p->count > 0 ? s : 0;
  34.721 -		s += p->count;
  34.722 -
  34.723 -		list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
  34.724 -		array_release(&p->packages);
  34.725 -		p++;
  34.726 -	}		
  34.727 -	if (e != NULL)
  34.728 -		e->flags |= RAZOR_ENTRY_LAST;
  34.729 -
  34.730 -	p = d->files.data;
  34.731 -	end = d->files.data + d->files.size;
  34.732 -	while (p < end) {
  34.733 -		serialize_files(set, p, array);
  34.734 -		p++;
  34.735 -	}
  34.736 -}
  34.737 -
  34.738 -static void
  34.739 -remap_property_package_links(struct array *properties, uint32_t *rmap)
  34.740 -{
  34.741 -	struct razor_property *p, *end;
  34.742 -
  34.743 -	end = properties->data + properties->size;
  34.744 -	for (p = properties->data; p < end; p++)
  34.745 -		list_remap_head(&p->packages, rmap);
  34.746 -}
  34.747 -
  34.748 -static void
  34.749 -build_file_tree(struct razor_importer *importer)
  34.750 -{
  34.751 -	int count, i, length;
  34.752 -	struct import_entry *filenames;
  34.753 -	char *f, *end;
  34.754 -	uint32_t name, *r;
  34.755 -	char dirname[256];
  34.756 -	struct import_directory *d, root;
  34.757 -	struct razor_entry *e;
  34.758 -
  34.759 -	count = importer->files.size / sizeof (struct import_entry);
  34.760 -	razor_qsort_with_data(importer->files.data,
  34.761 -			      count,
  34.762 -			      sizeof (struct import_entry),
  34.763 -			      compare_filenames,
  34.764 -			      NULL);
  34.765 -
  34.766 -	root.name = hashtable_tokenize(&importer->file_table, "");
  34.767 -	array_init(&root.files);
  34.768 -	array_init(&root.packages);
  34.769 -	root.last = NULL;
  34.770 -
  34.771 -	filenames = importer->files.data;
  34.772 -	for (i = 0; i < count; i++) {
  34.773 -		f = filenames[i].name;
  34.774 -		if (*f != '/')
  34.775 -			continue;
  34.776 -		f++;
  34.777 -
  34.778 -		d = &root;
  34.779 -		while (*f) {
  34.780 -			end = strchr(f, '/');
  34.781 -			if (end == NULL)
  34.782 -				end = f + strlen(f);
  34.783 -			length = end - f;
  34.784 -			memcpy(dirname, f, length);
  34.785 -			dirname[length] ='\0';
  34.786 -			name = hashtable_tokenize(&importer->file_table, dirname);
  34.787 -			if (d->last == NULL || d->last->name != name) {
  34.788 -				d->last = array_add(&d->files, sizeof *d);
  34.789 -				d->last->name = name;
  34.790 -				d->last->last = NULL;
  34.791 -				array_init(&d->last->files);
  34.792 -				array_init(&d->last->packages);
  34.793 -			}
  34.794 -			d = d->last;				
  34.795 -			f = end + 1;
  34.796 -			if (*end == '\0')
  34.797 -				break;
  34.798 -		}
  34.799 -
  34.800 -		r = array_add(&d->packages, sizeof *r);
  34.801 -		*r = filenames[i].package;
  34.802 -		free(filenames[i].name);
  34.803 -	}
  34.804 -
  34.805 -	count_entries(&root);
  34.806 -	e = importer->set->files.data;
  34.807 -	e->name = root.name;
  34.808 -	e->flags = RAZOR_ENTRY_LAST;
  34.809 -	e->start = importer->files.size ? 1 : 0;
  34.810 -	list_set_empty(&e->packages);
  34.811 -
  34.812 -	serialize_files(importer->set, &root, &importer->set->files);
  34.813 -
  34.814 -	array_release(&importer->files);
  34.815 -}
  34.816 -
  34.817 -static struct razor_entry *
  34.818 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
  34.819 -
  34.820 -static void
  34.821 -list_to_array(struct list *list, struct array *array)
  34.822 -{
  34.823 -	uint32_t *item;
  34.824 -
  34.825 -	while (list) {
  34.826 -		 item = array_add(array, sizeof *item);
  34.827 -		 *item = list->data;
  34.828 -		 list = list_next(list);
  34.829 -	}
  34.830 -}
  34.831 -
  34.832 -static int
  34.833 -compare_file_requires(const void *p1, const void *p2, void *data)
  34.834 -{
  34.835 -	uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
  34.836 -	const char *pool = data;
  34.837 -
  34.838 -	return strcmp(&pool[*f1], &pool[*f2]);
  34.839 -}
  34.840 -
  34.841 -static void
  34.842 -find_file_provides(struct razor_importer *importer)
  34.843 -{
  34.844 -	struct razor_property *prop;
  34.845 -	struct razor_entry *top, *entry;
  34.846 -	struct razor_package *packages;
  34.847 -	struct array pkgprops;
  34.848 -	struct list *pkg;
  34.849 -	uint32_t *req, *req_start, *req_end;
  34.850 -	uint32_t *map, *newprop;
  34.851 -	char *pool;
  34.852 -
  34.853 -	pool = importer->set->string_pool.data;
  34.854 -	packages = importer->set->packages.data;
  34.855 -	top = importer->set->files.data;
  34.856 -
  34.857 -	req = req_start = importer->file_requires.data;
  34.858 -	req_end = importer->file_requires.data + importer->file_requires.size;
  34.859 -	map = razor_qsort_with_data(req, req_end - req, sizeof *req,
  34.860 -				    compare_file_requires, pool);
  34.861 -	free(map);
  34.862 -
  34.863 -	for (req = req_start; req < req_end; req++) {
  34.864 -		if (req > req_start && req[0] == req[-1])
  34.865 -			continue;
  34.866 -		entry = find_entry(importer->set, top, &pool[*req]);
  34.867 -		if (!entry)
  34.868 -			continue;
  34.869 -
  34.870 -		for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
  34.871 -			prop = array_add(&importer->set->properties, sizeof *prop);
  34.872 -			prop->name = *req;
  34.873 -			prop->type = RAZOR_PROPERTY_PROVIDES;
  34.874 -			prop->relation = RAZOR_VERSION_EQUAL;
  34.875 -			prop->version = hashtable_tokenize(&importer->table, "");
  34.876 -			list_set_ptr(&prop->packages, pkg->data);
  34.877 -
  34.878 -			/* Update property list of pkg */
  34.879 -			array_init(&pkgprops);
  34.880 -			list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
  34.881 -			newprop = array_add(&pkgprops, sizeof *newprop);
  34.882 -			*newprop = prop - (struct razor_property *)importer->set->properties.data;
  34.883 -			list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
  34.884 -			array_release(&pkgprops);
  34.885 -		}
  34.886 -	}
  34.887 -
  34.888 -	array_release(&importer->file_requires);
  34.889 -}
  34.890 -
  34.891 -static void
  34.892 -build_package_file_lists(struct razor_set *set, uint32_t *rmap)
  34.893 -{
  34.894 -	struct razor_package *p, *packages;
  34.895 -	struct array *pkgs;
  34.896 -	struct razor_entry *e, *end;
  34.897 -	struct list *r;
  34.898 -	uint32_t *q;
  34.899 -	int i, count;
  34.900 -
  34.901 -	count = set->packages.size / sizeof *p;
  34.902 -	pkgs = zalloc(count * sizeof *pkgs);
  34.903 -
  34.904 -	end = set->files.data + set->files.size;
  34.905 -	for (e = set->files.data; e < end; e++) {
  34.906 -		list_remap_head(&e->packages, rmap);
  34.907 -		r = list_first(&e->packages, &set->package_pool);
  34.908 -		while (r) {
  34.909 -			q = array_add(&pkgs[r->data], sizeof *q);
  34.910 -			*q = e - (struct razor_entry *) set->files.data;
  34.911 -			r = list_next(r);
  34.912 -		}
  34.913 -	}
  34.914 -
  34.915 -	packages = set->packages.data;
  34.916 -	for (i = 0; i < count; i++) {
  34.917 -		list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
  34.918 -		array_release(&pkgs[i]);
  34.919 -	}
  34.920 -	free(pkgs);
  34.921 -}
  34.922 -
  34.923 -struct razor_set *
  34.924 -razor_importer_finish(struct razor_importer *importer)
  34.925 -{
  34.926 -	struct razor_set *set;
  34.927 -	uint32_t *map, *rmap;
  34.928 -	int i, count;
  34.929 -
  34.930 -	build_file_tree(importer);
  34.931 -	find_file_provides(importer);
  34.932 -
  34.933 -	map = uniqueify_properties(importer->set);
  34.934 -	list_remap_pool(&importer->set->property_pool, map);
  34.935 -	free(map);
  34.936 -
  34.937 -	count = importer->set->packages.size / sizeof(struct razor_package);
  34.938 -	map = razor_qsort_with_data(importer->set->packages.data,
  34.939 -				    count,
  34.940 -				    sizeof(struct razor_package),
  34.941 -				    compare_packages,
  34.942 -				    importer->set);
  34.943 -
  34.944 -	rmap = malloc(count * sizeof *rmap);
  34.945 -	for (i = 0; i < count; i++)
  34.946 -		rmap[map[i]] = i;
  34.947 -	free(map);
  34.948 -
  34.949 -	list_remap_pool(&importer->set->package_pool, rmap);
  34.950 -	build_package_file_lists(importer->set, rmap);
  34.951 -	remap_property_package_links(&importer->set->properties, rmap);
  34.952 -	free(rmap);
  34.953 -
  34.954 -	set = importer->set;
  34.955 -	hashtable_release(&importer->table);
  34.956 -	hashtable_release(&importer->file_table);
  34.957 -	hashtable_release(&importer->details_table);
  34.958 -	free(importer);
  34.959 -
  34.960 -	return set;
  34.961 -}
  34.962 -
  34.963 -struct razor_package_iterator {
  34.964 -	struct razor_set *set;
  34.965 -	struct razor_package *package, *end;
  34.966 -	struct list *index;
  34.967 -	int free_index;
  34.968 -};
  34.969 -
  34.970 -static struct razor_package_iterator *
  34.971 -razor_package_iterator_create_with_index(struct razor_set *set,
  34.972 -					 struct list *index)
  34.973 -{
  34.974 -	struct razor_package_iterator *pi;
  34.975 -
  34.976 -	pi = zalloc(sizeof *pi);
  34.977 -	pi->set = set;
  34.978 -	pi->index = index;
  34.979 -
  34.980 -	return pi;
  34.981 -}
  34.982 -
  34.983 -struct razor_package_iterator *
  34.984 -razor_package_iterator_create(struct razor_set *set)
  34.985 -{
  34.986 -	struct razor_package_iterator *pi;
  34.987 -
  34.988 -	pi = zalloc(sizeof *pi);
  34.989 -	pi->set = set;
  34.990 -	pi->end = set->packages.data + set->packages.size;
  34.991 -	pi->package = set->packages.data;
  34.992 -
  34.993 -	return pi;
  34.994 -}
  34.995 -
  34.996 -struct razor_package_iterator *
  34.997 -razor_package_iterator_create_for_property(struct razor_set *set,
  34.998 -					   struct razor_property *property)
  34.999 -{
 34.1000 -	struct list *index;
 34.1001 -
 34.1002 -	index = list_first(&property->packages, &set->package_pool);
 34.1003 -	return razor_package_iterator_create_with_index(set, index);
 34.1004 -}
 34.1005 -
 34.1006 -int
 34.1007 -razor_package_iterator_next(struct razor_package_iterator *pi,
 34.1008 -			    struct razor_package **package,
 34.1009 -			    const char **name,
 34.1010 -			    const char **version,
 34.1011 -			    const char **arch)
 34.1012 -{
 34.1013 -	char *pool;
 34.1014 -	int valid;
 34.1015 -	struct razor_package *p, *packages;
 34.1016 -
 34.1017 -	if (pi->package) {
 34.1018 -		p = pi->package++;
 34.1019 -		valid = p < pi->end;
 34.1020 -	} else if (pi->index) {
 34.1021 -		packages = pi->set->packages.data;
 34.1022 -		p = &packages[pi->index->data];
 34.1023 -		pi->index = list_next(pi->index);
 34.1024 -		valid = 1;
 34.1025 -	} else
 34.1026 -		valid = 0;
 34.1027 -
 34.1028 -	if (valid) {
 34.1029 -		pool = pi->set->string_pool.data;
 34.1030 -		*package = p;
 34.1031 -		*name = &pool[p->name];
 34.1032 -		*version = &pool[p->version];
 34.1033 -		*arch = &pool[p->arch];
 34.1034 -	} else {
 34.1035 -		*package = NULL;
 34.1036 -	}
 34.1037 -
 34.1038 -	return valid;
 34.1039 -}
 34.1040 -
 34.1041 -void
 34.1042 -razor_package_iterator_destroy(struct razor_package_iterator *pi)
 34.1043 -{
 34.1044 -	if (pi->free_index)
 34.1045 -		free(pi->index);
 34.1046 -
 34.1047 -	free(pi);
 34.1048 -}
 34.1049 -
 34.1050 -struct razor_package *
 34.1051 -razor_set_get_package(struct razor_set *set, const char *package)
 34.1052 -{
 34.1053 -	struct razor_package_iterator *pi;
 34.1054 -	struct razor_package *p;
 34.1055 -	const char *name, *version, *arch;
 34.1056 -
 34.1057 -	pi = razor_package_iterator_create(set);
 34.1058 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 34.1059 -		if (strcmp(package, name) == 0)
 34.1060 -			break;
 34.1061 -	}
 34.1062 -	razor_package_iterator_destroy(pi);
 34.1063 -
 34.1064 -	return p;
 34.1065 -}
 34.1066 -
 34.1067 -void
 34.1068 -razor_package_get_details(struct razor_set *set, struct razor_package *package,
 34.1069 -			  const char **summary, const char **description,
 34.1070 -			  const char **url, const char **license)
 34.1071 -{
 34.1072 -	const char *pool = set->details_string_pool.data;
 34.1073 -
 34.1074 -	*summary = &pool[package->summary];
 34.1075 -	*description = &pool[package->description];
 34.1076 -	*url = &pool[package->url];
 34.1077 -	*license = &pool[package->license];
 34.1078 -}
 34.1079 -
 34.1080 -struct razor_property_iterator {
 34.1081 -	struct razor_set *set;
 34.1082 -	struct razor_property *property, *end;
 34.1083 -	struct list *index;
 34.1084 -};
 34.1085 -
 34.1086 -struct razor_property_iterator *
 34.1087 -razor_property_iterator_create(struct razor_set *set,
 34.1088 -			       struct razor_package *package)
 34.1089 -{
 34.1090 -	struct razor_property_iterator *pi;
 34.1091 -
 34.1092 -	pi = zalloc(sizeof *pi);
 34.1093 -	pi->set = set;
 34.1094 -
 34.1095 -	if (package) {
 34.1096 -		pi->index = list_first(&package->properties,
 34.1097 -				       &set->property_pool);
 34.1098 -	} else {
 34.1099 -		pi->property = set->properties.data;
 34.1100 -		pi->end = set->properties.data + set->properties.size;
 34.1101 -	}
 34.1102 -
 34.1103 -	return pi;
 34.1104 -}
 34.1105 -
 34.1106 -int
 34.1107 -razor_property_iterator_next(struct razor_property_iterator *pi,
 34.1108 -			     struct razor_property **property,
 34.1109 -			     const char **name,
 34.1110 -			     enum razor_version_relation *relation,
 34.1111 -			     const char **version,
 34.1112 -			     enum razor_property_type *type)
 34.1113 -{
 34.1114 -	char *pool;
 34.1115 -	int valid;
 34.1116 -	struct razor_property *p, *properties;
 34.1117 -
 34.1118 -	if (pi->property) {
 34.1119 -		p = pi->property++;
 34.1120 -		valid = p < pi->end;
 34.1121 -	} else if (pi->index) {
 34.1122 -		properties = pi->set->properties.data;
 34.1123 -		p = &properties[pi->index->data];
 34.1124 -		pi->index = list_next(pi->index);
 34.1125 -		valid = 1;
 34.1126 -	} else
 34.1127 -		valid = 0;
 34.1128 -
 34.1129 -	if (valid) {
 34.1130 -		pool = pi->set->string_pool.data;
 34.1131 -		*property = p;
 34.1132 -		*name = &pool[p->name];
 34.1133 -		*relation = p->relation;
 34.1134 -		*version = &pool[p->version];
 34.1135 -		*type = p->type;
 34.1136 -	} else {
 34.1137 -		*property = NULL;
 34.1138 -	}
 34.1139 -
 34.1140 -	return valid;
 34.1141 -}
 34.1142 -
 34.1143 -void
 34.1144 -razor_property_iterator_destroy(struct razor_property_iterator *pi)
 34.1145 -{
 34.1146 -	free(pi);
 34.1147 -}
 34.1148 -
 34.1149 -static struct razor_entry *
 34.1150 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
 34.1151 -{
 34.1152 -	struct razor_entry *e;
 34.1153 -	const char *n, *pool = set->file_string_pool.data;
 34.1154 -	int len;
 34.1155 -
 34.1156 -	e = (struct razor_entry *) set->files.data + dir->start;
 34.1157 -	do {
 34.1158 -		n = pool + e->name;
 34.1159 -		if (strcmp(pattern + 1, n) == 0)
 34.1160 -			return e;
 34.1161 -		len = strlen(n);
 34.1162 -		if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
 34.1163 -		    pattern[len + 1] == '/') {
 34.1164 -			return find_entry(set, e, pattern + len + 1);
 34.1165 -		}
 34.1166 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 34.1167 -
 34.1168 -	return NULL;
 34.1169 -}
 34.1170 -
 34.1171 -static void
 34.1172 -list_dir(struct razor_set *set, struct razor_entry *dir,
 34.1173 -	 char *prefix, const char *pattern)
 34.1174 -{
 34.1175 -	struct razor_entry *e;
 34.1176 -	const char *n, *pool = set->file_string_pool.data;
 34.1177 -
 34.1178 -	e = (struct razor_entry *) set->files.data + dir->start;
 34.1179 -	do {
 34.1180 -		n = pool + e->name;
 34.1181 -		if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
 34.1182 -			continue;
 34.1183 -		printf("%s/%s\n", prefix, n);
 34.1184 -		if (e->start) {
 34.1185 -			char *sub = prefix + strlen (prefix);
 34.1186 -			*sub = '/';
 34.1187 -			strcpy (sub + 1, n);
 34.1188 -			list_dir(set, e, prefix, pattern);
 34.1189 -			*sub = '\0';
 34.1190 -		}
 34.1191 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 34.1192 -}
 34.1193 -
 34.1194 -void
 34.1195 -razor_set_list_files(struct razor_set *set, const char *pattern)
 34.1196 -{
 34.1197 -	struct razor_entry *e;
 34.1198 -	char buffer[512], *p, *base;
 34.1199 -
 34.1200 -	if (pattern == NULL || !strcmp (pattern, "/")) {
 34.1201 -		buffer[0] = '\0';
 34.1202 -		list_dir(set, set->files.data, buffer, NULL);
 34.1203 -		return;
 34.1204 -	}
 34.1205 -
 34.1206 -	strcpy(buffer, pattern);
 34.1207 -	e = find_entry(set, set->files.data, buffer);
 34.1208 -	if (e && e->start > 0) {
 34.1209 -		base = NULL;
 34.1210 -	} else {
 34.1211 -		p = strrchr(buffer, '/');
 34.1212 -		if (p) {
 34.1213 -			*p = '\0';
 34.1214 -			base = p + 1;
 34.1215 -		} else {
 34.1216 -			base = NULL;
 34.1217 -		}
 34.1218 -	}
 34.1219 -	e = find_entry(set, set->files.data, buffer);
 34.1220 -	if (e->start != 0)
 34.1221 -		list_dir(set, e, buffer, base);
 34.1222 -}
 34.1223 -
 34.1224 -struct razor_package_iterator *
 34.1225 -razor_package_iterator_create_for_file(struct razor_set *set,
 34.1226 -				       const char *filename)
 34.1227 -{
 34.1228 -	struct razor_entry *entry;
 34.1229 -	struct list *index;
 34.1230 -
 34.1231 -	entry = find_entry(set, set->files.data, filename);
 34.1232 -	if (entry == NULL)
 34.1233 -		return NULL;
 34.1234 -	
 34.1235 -	index = list_first(&entry->packages, &set->package_pool);
 34.1236 -	return razor_package_iterator_create_with_index(set, index);
 34.1237 -}
 34.1238 -
 34.1239 -static struct list *
 34.1240 -list_package_files(struct razor_set *set, struct list *r,
 34.1241 -		   struct razor_entry *dir, uint32_t end,
 34.1242 -		   char *prefix)
 34.1243 -{
 34.1244 -	struct razor_entry *e, *f, *entries;
 34.1245 -	uint32_t next, file;
 34.1246 -	char *pool;
 34.1247 -	int len;
 34.1248 -	
 34.1249 -	entries = (struct razor_entry *) set->files.data;
 34.1250 -	pool = set->file_string_pool.data;
 34.1251 -
 34.1252 -	e = entries + dir->start;
 34.1253 -	do {
 34.1254 -		if (entries + r->data == e) {
 34.1255 -			printf("%s/%s\n", prefix, pool + e->name);
 34.1256 -			r = list_next(r);
 34.1257 -			if (!r)
 34.1258 -				return NULL;
 34.1259 -			if (r->data >= end)
 34.1260 -				return r;
 34.1261 -		}
 34.1262 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST));
 34.1263 -
 34.1264 -	e = entries + dir->start;
 34.1265 -	do {
 34.1266 -		if (e->start == 0)
 34.1267 -			continue;
 34.1268 -
 34.1269 -		if (e->flags & RAZOR_ENTRY_LAST)
 34.1270 -			next = end;
 34.1271 -		else {
 34.1272 -			f = e + 1; 
 34.1273 -			while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
 34.1274 -				f++;
 34.1275 -			if (f->start == 0)
 34.1276 -				next = end;
 34.1277 -			else
 34.1278 -				next = f->start;
 34.1279 -		}
 34.1280 -
 34.1281 -		file = r->data;
 34.1282 -		if (e->start <= file && file < next) {
 34.1283 -			len = strlen(prefix);
 34.1284 -			prefix[len] = '/';
 34.1285 -			strcpy(prefix + len + 1, pool + e->name);
 34.1286 -			r = list_package_files(set, r, e, next, prefix);
 34.1287 -			prefix[len] = '\0';
 34.1288 -		}
 34.1289 -	} while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
 34.1290 -
 34.1291 -	return r;
 34.1292 -}
 34.1293 -
 34.1294 -void
 34.1295 -razor_set_list_package_files(struct razor_set *set, const char *name)
 34.1296 -{
 34.1297 -	struct razor_package *package;
 34.1298 -	struct list *r;
 34.1299 -	uint32_t end;
 34.1300 -	char buffer[512];
 34.1301 -
 34.1302 -	package = razor_set_get_package(set, name);
 34.1303 -
 34.1304 -	r = list_first(&package->files, &set->file_pool);
 34.1305 -	end = set->files.size / sizeof (struct razor_entry);
 34.1306 -	buffer[0] = '\0';
 34.1307 -	list_package_files(set, r, set->files.data, end, buffer);
 34.1308 -}
 34.1309 -
 34.1310 -static void
 34.1311 -razor_set_validate(struct razor_set *set, struct array *unsatisfied)
 34.1312 -{
 34.1313 -	struct razor_property *r, *p, *end;
 34.1314 -	uint32_t *u;
 34.1315 -	char *pool;
 34.1316 -
 34.1317 -	end = set->properties.data + set->properties.size;
 34.1318 -	pool = set->string_pool.data;
 34.1319 -	
 34.1320 -	for (r = set->properties.data, p = r; r < end; r++) {
 34.1321 -		if (r->type != RAZOR_PROPERTY_REQUIRES)
 34.1322 -			continue;
 34.1323 -
 34.1324 -		p = r;
 34.1325 -		while (p < end && p->name == r->name &&
 34.1326 -		       p->type == r->type)
 34.1327 -			p++;
 34.1328 -
 34.1329 -		/* If there is more than one version of a provides,
 34.1330 -		 * seek to the end for the highest version. */
 34.1331 -		/* FIXME: This doesn't work if we have a series of
 34.1332 -		 * requires a = 1, provides a = 1, requires a = 2,
 34.1333 -		 * provides a = 2, as the kernel and kernel-devel
 34.1334 -		 * does.*/
 34.1335 -		while (p + 1 < end && p->name == (p + 1)->name &&
 34.1336 -		       p->type == (p + 1)->type)
 34.1337 -			p++;
 34.1338 -
 34.1339 -		/* FIXME: We need to track property flags (<, <=, =
 34.1340 -		 * etc) to properly determine if a requires is
 34.1341 -		 * satisfied.  The current code doesn't track that the
 34.1342 -		 * requires a = 1 isn't satisfied by a = 2 provides. */
 34.1343 -
 34.1344 -		if (p == end ||
 34.1345 -		    p->type != RAZOR_PROPERTY_PROVIDES ||
 34.1346 -		    r->name != p->name ||
 34.1347 -		    versioncmp(&pool[r->version], &pool[p->version]) > 0) {
 34.1348 -			/* FIXME: We ignore file requires for now. */
 34.1349 -			if (pool[r->name] == '/')
 34.1350 -				continue;
 34.1351 -			u = array_add(unsatisfied, sizeof *u);
 34.1352 -			*u = r - (struct razor_property *) set->properties.data;
 34.1353 -		}
 34.1354 -	}
 34.1355 -}
 34.1356 -
 34.1357 -void
 34.1358 -razor_set_list_unsatisfied(struct razor_set *set)
 34.1359 -{
 34.1360 -	struct array unsatisfied;
 34.1361 -	struct razor_property *properties, *r;
 34.1362 -	uint32_t *u, *end;
 34.1363 -	char *pool;
 34.1364 -
 34.1365 -	array_init(&unsatisfied);
 34.1366 -	razor_set_validate(set, &unsatisfied);
 34.1367 -
 34.1368 -	end = unsatisfied.data + unsatisfied.size;
 34.1369 -	properties = set->properties.data;
 34.1370 -	pool = set->string_pool.data;
 34.1371 -
 34.1372 -	for (u = unsatisfied.data; u < end; u++) {
 34.1373 -		r = properties + *u;
 34.1374 -		if (pool[r->version] == '\0')
 34.1375 -			printf("%s not satisfied\n",
 34.1376 -			       &pool[r->name]);
 34.1377 -		else
 34.1378 -			printf("%s-%s not satisfied\n",
 34.1379 -			       &pool[r->name],
 34.1380 -			       &pool[r->version]);
 34.1381 -	}
 34.1382 -
 34.1383 -	array_release(&unsatisfied);
 34.1384 -}
 34.1385 -
 34.1386 -#define UPSTREAM_SOURCE 0x80
 34.1387 -
 34.1388 -struct source {
 34.1389 -	struct razor_set *set;
 34.1390 -	uint32_t *property_map;
 34.1391 -	uint32_t *file_map;
 34.1392 -};
 34.1393 -
 34.1394 -struct razor_merger {
 34.1395 -	struct razor_set *set;
 34.1396 -	struct hashtable table;
 34.1397 -	struct hashtable file_table;
 34.1398 -	struct hashtable details_table;
 34.1399 -	struct source source1;
 34.1400 -	struct source source2;
 34.1401 -};
 34.1402 -
 34.1403 -static struct razor_merger *
 34.1404 -razor_merger_create(struct razor_set *set1, struct razor_set *set2)
 34.1405 -{
 34.1406 -	struct razor_merger *merger;
 34.1407 -	int count;
 34.1408 -	size_t size;
 34.1409 -
 34.1410 -	merger = zalloc(sizeof *merger);
 34.1411 -	merger->set = razor_set_create();
 34.1412 -	hashtable_init(&merger->table, &merger->set->string_pool);
 34.1413 -	hashtable_init(&merger->file_table, &merger->set->file_string_pool);
 34.1414 -	hashtable_init(&merger->details_table, &merger->set->details_string_pool);
 34.1415 -
 34.1416 -	merger->source1.set = set1;
 34.1417 -	count = set1->properties.size / sizeof (struct razor_property);
 34.1418 -	size = count * sizeof merger->source1.property_map[0];
 34.1419 -	merger->source1.property_map = zalloc(size);
 34.1420 -	count = set1->files.size / sizeof (struct razor_entry);
 34.1421 -	size = count * sizeof merger->source1.file_map[0];
 34.1422 -	merger->source1.file_map = zalloc(size);
 34.1423 -
 34.1424 -	merger->source2.set = set2;
 34.1425 -	count = set2->properties.size / sizeof (struct razor_property);
 34.1426 -	size = count * sizeof merger->source2.property_map[0];
 34.1427 -	merger->source2.property_map = zalloc(size);
 34.1428 -	count = set2->files.size / sizeof (struct razor_entry);
 34.1429 -	size = count * sizeof merger->source2.file_map[0];
 34.1430 -	merger->source2.file_map = zalloc(size);
 34.1431 -
 34.1432 -	return merger;
 34.1433 -}
 34.1434 -
 34.1435 -static void
 34.1436 -add_package(struct razor_merger *merger,
 34.1437 -	    struct razor_package *package, struct source *source,
 34.1438 -	    uint32_t flags)
 34.1439 -{
 34.1440 -	char *pool;
 34.1441 -	struct list *r;
 34.1442 -	struct razor_package *p;
 34.1443 -
 34.1444 -	pool = source->set->string_pool.data;
 34.1445 -	p = array_add(&merger->set->packages, sizeof *p);
 34.1446 -	p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
 34.1447 -	p->flags = flags;
 34.1448 -	p->version = hashtable_tokenize(&merger->table,
 34.1449 -					&pool[package->version]);
 34.1450 -	p->arch = hashtable_tokenize(&merger->table,
 34.1451 -				     &pool[package->arch]);
 34.1452 -
 34.1453 -	p->properties = package->properties;
 34.1454 -	r = list_first(&package->properties, &source->set->property_pool);
 34.1455 -	while (r) {
 34.1456 -		source->property_map[r->data] = 1;
 34.1457 -		r = list_next(r);
 34.1458 -	}
 34.1459 -
 34.1460 -	p->files = package->files;
 34.1461 -	r = list_first(&package->files, &source->set->file_pool);
 34.1462 -	while (r) {
 34.1463 -		source->file_map[r->data] = 1;
 34.1464 -		r = list_next(r);
 34.1465 -	}
 34.1466 -}
 34.1467 -
 34.1468 -static uint32_t
 34.1469 -add_property(struct razor_merger *merger,
 34.1470 -	     const char *name, enum razor_version_relation relation,
 34.1471 -	     const char *version, int type)
 34.1472 -{
 34.1473 -	struct razor_property *p;
 34.1474 -
 34.1475 -	p = array_add(&merger->set->properties, sizeof *p);
 34.1476 -	p->name = hashtable_tokenize(&merger->table, name);
 34.1477 -	p->flags = 0;
 34.1478 -	p->type = type;
 34.1479 -	p->relation = relation;
 34.1480 -	p->version = hashtable_tokenize(&merger->table, version);
 34.1481 -
 34.1482 -	return p - (struct razor_property *) merger->set->properties.data;
 34.1483 -}
 34.1484 -
 34.1485 -static void
 34.1486 -merge_properties(struct razor_merger *merger)
 34.1487 -{
 34.1488 -	struct razor_property *p1, *p2;
 34.1489 -	struct razor_set *set1, *set2;
 34.1490 -	uint32_t *map1, *map2;
 34.1491 -	int i, j, cmp, count1, count2;
 34.1492 -	char *pool1, *pool2;
 34.1493 -
 34.1494 -	set1 = merger->source1.set;
 34.1495 -	set2 = merger->source2.set;
 34.1496 -	map1 = merger->source1.property_map;
 34.1497 -	map2 = merger->source2.property_map;
 34.1498 -
 34.1499 -	i = 0;
 34.1500 -	j = 0;
 34.1501 -	pool1 = set1->string_pool.data;
 34.1502 -	pool2 = set2->string_pool.data;
 34.1503 -
 34.1504 -	count1 = set1->properties.size / sizeof *p1;
 34.1505 -	count2 = set2->properties.size / sizeof *p2;
 34.1506 -	while (i < count1 || j < count2) {
 34.1507 -		if (i < count1 && map1[i] == 0) {
 34.1508 -			i++;
 34.1509 -			continue;
 34.1510 -		}
 34.1511 -		if (j < count2 && map2[j] == 0) {
 34.1512 -			j++;
 34.1513 -			continue;
 34.1514 -		}
 34.1515 -		p1 = (struct razor_property *) set1->properties.data + i;
 34.1516 -		p2 = (struct razor_property *) set2->properties.data + j;
 34.1517 -		if (i < count1 && j < count2)
 34.1518 -			cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
 34.1519 -		else if (i < count1)
 34.1520 -			cmp = -1;
 34.1521 -		else
 34.1522 -			cmp = 1;
 34.1523 -		if (cmp == 0)
 34.1524 -			cmp = p1->type - p2->type;
 34.1525 -		if (cmp == 0)
 34.1526 -			cmp = p1->relation - p2->relation;
 34.1527 -		if (cmp == 0)
 34.1528 -			cmp = versioncmp(&pool1[p1->version],
 34.1529 -					 &pool2[p2->version]);
 34.1530 -		if (cmp < 0) {
 34.1531 -			map1[i++] = add_property(merger,
 34.1532 -						 &pool1[p1->name],
 34.1533 -						 p1->relation,
 34.1534 -						 &pool1[p1->version],
 34.1535 -						 p1->type);
 34.1536 -		} else if (cmp > 0) {
 34.1537 -			map2[j++] = add_property(merger,
 34.1538 -						 &pool2[p2->name],
 34.1539 -						 p2->relation,
 34.1540 -						 &pool2[p2->version],
 34.1541 -						 p2->type);
 34.1542 -		} else  {
 34.1543 -			map1[i++] = map2[j++] = add_property(merger,
 34.1544 -							     &pool1[p1->name],
 34.1545 -							     p1->relation,
 34.1546 -							     &pool1[p1->version],
 34.1547 -							     p1->type);
 34.1548 -		}
 34.1549 -	}
 34.1550 -}
 34.1551 -
 34.1552 -static void
 34.1553 -emit_properties(struct list_head *properties, struct array *source_pool,
 34.1554 -		uint32_t *map, struct array *pool)
 34.1555 -{
 34.1556 -	uint32_t r;
 34.1557 -	struct list *p, *q;
 34.1558 -
 34.1559 -	r = pool->size / sizeof *q;
 34.1560 -	p = list_first(properties, source_pool);
 34.1561 -	while (p) {
 34.1562 -		q = array_add(pool, sizeof *q);
 34.1563 -		q->data = map[p->data];
 34.1564 -		q->flags = p->flags;
 34.1565 -		p = list_next(p);
 34.1566 -	}
 34.1567 -
 34.1568 -	list_set_ptr(properties, r);
 34.1569 -}
 34.1570 -
 34.1571 -static uint32_t
 34.1572 -add_file(struct razor_merger *merger, const char *name)
 34.1573 -{
 34.1574 -	struct razor_entry *e;
 34.1575 -
 34.1576 -	e = array_add(&merger->set->files, sizeof *e);
 34.1577 -	e->name = hashtable_tokenize(&merger->file_table, name);
 34.1578 -	e->flags = 0;
 34.1579 -	e->start = 0;
 34.1580 -
 34.1581 -	return e - (struct razor_entry *)merger->set->files.data;
 34.1582 -}
 34.1583 -
 34.1584 -/* FIXME. Blah */
 34.1585 -static int
 34.1586 -fix_file_map(uint32_t *map,
 34.1587 -	     struct razor_entry *files,
 34.1588 -	     struct razor_entry *top)
 34.1589 -{
 34.1590 -	uint32_t e;
 34.1591 -	int found_file = 0;
 34.1592 -
 34.1593 -	e = top->start;
 34.1594 -	do {
 34.1595 -		if (files[e].start)
 34.1596 -			fix_file_map(map, files, &files[e]);
 34.1597 -		if (map[e])
 34.1598 -			found_file = 1;
 34.1599 -	} while (!(files[e++].flags & RAZOR_ENTRY_LAST));
 34.1600 -
 34.1601 -	if (found_file)
 34.1602 -		map[top - files] = 1;
 34.1603 -	return found_file;
 34.1604 -}
 34.1605 -
 34.1606 -struct merge_directory {
 34.1607 -	uint32_t merged, dir1, dir2;
 34.1608 -};
 34.1609 -
 34.1610 -static void
 34.1611 -merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
 34.1612 -{
 34.1613 -	struct razor_entry *root1, *root2, *mroot, *e1, *e2;
 34.1614 -	struct razor_set *set1, *set2;
 34.1615 -	struct array merge_stack;
 34.1616 -	struct merge_directory *child_md, *end_md;
 34.1617 -	uint32_t *map1, *map2, start, last;
 34.1618 -	int cmp;
 34.1619 -	char *pool1, *pool2;
 34.1620 -
 34.1621 -	set1 = merger->source1.set;
 34.1622 -	set2 = merger->source2.set;
 34.1623 -	map1 = merger->source1.file_map;
 34.1624 -	map2 = merger->source2.file_map;
 34.1625 -	pool1 = set1->string_pool.data;
 34.1626 -	pool2 = set2->string_pool.data;
 34.1627 -	root1 = (struct razor_entry *) set1->files.data;
 34.1628 -	root2 = (struct razor_entry *) set2->files.data;
 34.1629 -
 34.1630 -	array_init(&merge_stack);
 34.1631 -
 34.1632 -	start = merger->set->files.size / sizeof (struct razor_entry);
 34.1633 -	last = 0;
 34.1634 -	e1 = md->dir1 ? root1 + md->dir1 : NULL;
 34.1635 -	e2 = md->dir2 ? root2 + md->dir2 : NULL;
 34.1636 -	while (e1 || e2) {
 34.1637 -		if (!e2 && !map1[e1 - root1]) {
 34.1638 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 34.1639 -				e1 = NULL;
 34.1640 -			continue;
 34.1641 -		}
 34.1642 -		if (!e1 && !map2[e2 - root2]) {
 34.1643 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 34.1644 -				e2 = NULL;
 34.1645 -			continue;
 34.1646 -		}
 34.1647 -		if (e1 && !map1[e1 - root1] &&
 34.1648 -		    e2 && !map1[e2 - root2]) {
 34.1649 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 34.1650 -				e1 = NULL;
 34.1651 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 34.1652 -				e2 = NULL;
 34.1653 -			continue;
 34.1654 -		}
 34.1655 -
 34.1656 -		if (!e1)
 34.1657 -			cmp = 1;
 34.1658 -		else if (!e2)
 34.1659 -			cmp = -1;
 34.1660 -		else {
 34.1661 -			cmp = strcmp (&pool1[e1->name],
 34.1662 -				      &pool2[e2->name]);
 34.1663 -		}
 34.1664 -
 34.1665 -		if (cmp < 0) {
 34.1666 -			if (map1[e1 - root1]) {
 34.1667 -				map1[e1 - root1] = last =
 34.1668 -					add_file(merger, &pool1[e1->name]);
 34.1669 -				if (e1->start) {
 34.1670 -					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 34.1671 -					child_md->merged = last;
 34.1672 -					child_md->dir1 = e1->start;
 34.1673 -					child_md->dir2 = 0;
 34.1674 -				}
 34.1675 -			}
 34.1676 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 34.1677 -				e1 = NULL;
 34.1678 -		} else if (cmp > 0) {
 34.1679 -			if (map2[e2 - root2]) {
 34.1680 -				map2[e2 - root2] = last =
 34.1681 -					add_file(merger, &pool2[e2->name]);
 34.1682 -				if (e2->start) {
 34.1683 -					child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 34.1684 -					child_md->merged = last;
 34.1685 -					child_md->dir1 = 0;
 34.1686 -					child_md->dir2 = e2->start;
 34.1687 -				}
 34.1688 -			}
 34.1689 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 34.1690 -				e2 = NULL;
 34.1691 -		} else {
 34.1692 -			map1[e1 - root1] = map2[e2- root2] = last =
 34.1693 -				add_file(merger, &pool1[e1->name]);
 34.1694 -			if (e1->start || e2->start) {
 34.1695 -				child_md = array_add(&merge_stack, sizeof (struct merge_directory));
 34.1696 -				child_md->merged = last;
 34.1697 -				child_md->dir1 = e1->start;
 34.1698 -				child_md->dir2 = e2->start;
 34.1699 -			}
 34.1700 -			if ((e1++)->flags & RAZOR_ENTRY_LAST)
 34.1701 -				e1 = NULL;
 34.1702 -			if ((e2++)->flags & RAZOR_ENTRY_LAST)
 34.1703 -				e2 = NULL;
 34.1704 -		}
 34.1705 -	}
 34.1706 -
 34.1707 -	mroot = (struct razor_entry *)merger->set->files.data;
 34.1708 -	if (last) {
 34.1709 -		mroot[last].flags = RAZOR_ENTRY_LAST;
 34.1710 -		mroot[md->merged].start = start;
 34.1711 -	} else
 34.1712 -		mroot[md->merged].start = 0;
 34.1713 -
 34.1714 -	end_md = merge_stack.data + merge_stack.size;
 34.1715 -	for (child_md = merge_stack.data; child_md < end_md; child_md++)
 34.1716 -		merge_one_directory(merger, child_md);
 34.1717 -	array_release(&merge_stack);
 34.1718 -}
 34.1719 -
 34.1720 -static void
 34.1721 -merge_files(struct razor_merger *merger)
 34.1722 -{
 34.1723 -	struct razor_entry *root;
 34.1724 -	struct merge_directory md;
 34.1725 -	uint32_t *map1, *map2;
 34.1726 -
 34.1727 -	map1 = merger->source1.file_map;
 34.1728 -	map2 = merger->source2.file_map;
 34.1729 -
 34.1730 -	md.merged = 0;
 34.1731 -
 34.1732 -	if (merger->source1.set->files.size) {
 34.1733 -		root = (struct razor_entry *) merger->source1.set->files.data;
 34.1734 -		if (root->start)
 34.1735 -			fix_file_map(map1, root, root);
 34.1736 -		md.dir1 = root->start;
 34.1737 -	} else
 34.1738 -		md.dir1 = 0;
 34.1739 -
 34.1740 -	if (merger->source2.set->files.size) {
 34.1741 -		root = (struct razor_entry *) merger->source2.set->files.data;
 34.1742 -		if (root->start)
 34.1743 -			fix_file_map(map2, root, root);
 34.1744 -		md.dir2 = root->start;
 34.1745 -	} else
 34.1746 -		md.dir2 = 0;
 34.1747 -
 34.1748 -	merge_one_directory(merger, &md);
 34.1749 -}
 34.1750 -
 34.1751 -static void
 34.1752 -emit_files(struct list_head *files, struct array *source_pool,
 34.1753 -	   uint32_t *map, struct array *pool)
 34.1754 -{
 34.1755 -	uint32_t r;
 34.1756 -	struct list *p, *q;
 34.1757 -
 34.1758 -	r = pool->size / sizeof *q;
 34.1759 -	p = list_first(files, source_pool);
 34.1760 -	while (p) {
 34.1761 -		q = array_add(pool, sizeof *q);
 34.1762 -		q->data = map[p->data];
 34.1763 -		q->flags = p->flags;
 34.1764 -		p = list_next(p);
 34.1765 -	}
 34.1766 -
 34.1767 -	list_set_ptr(files, r);
 34.1768 -}
 34.1769 -
 34.1770 -/* Rebuild property->packages maps.  We can't just remap these, as a
 34.1771 - * property may have lost or gained a number of packages.  Allocate an
 34.1772 - * array per property and loop through the packages and add them to
 34.1773 - * the arrays for their properties. */
 34.1774 -static void
 34.1775 -rebuild_property_package_lists(struct razor_set *set)
 34.1776 -{
 34.1777 -	struct array *pkgs, *a;
 34.1778 -	struct razor_package *pkg, *pkg_end;
 34.1779 -	struct razor_property *prop, *prop_end;
 34.1780 -	struct list *r;
 34.1781 -	uint32_t *q;
 34.1782 -	int count;
 34.1783 -
 34.1784 -	count = set->properties.size / sizeof (struct razor_property);
 34.1785 -	pkgs = zalloc(count * sizeof *pkgs);
 34.1786 -	pkg_end = set->packages.data + set->packages.size;
 34.1787 -
 34.1788 -	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
 34.1789 -		r = list_first(&pkg->properties, &set->property_pool);
 34.1790 -		while (r) {
 34.1791 -			q = array_add(&pkgs[r->data], sizeof *q);
 34.1792 -			*q = pkg - (struct razor_package *) set->packages.data;
 34.1793 -			r = list_next(r);
 34.1794 -		}
 34.1795 -	}
 34.1796 -
 34.1797 -	prop_end = set->properties.data + set->properties.size;
 34.1798 -	a = pkgs;
 34.1799 -	for (prop = set->properties.data; prop < prop_end; prop++, a++) {
 34.1800 -		list_set_array(&prop->packages, &set->package_pool, a, 0);
 34.1801 -		array_release(a);
 34.1802 -	}
 34.1803 -	free(pkgs);
 34.1804 -}
 34.1805 -
 34.1806 -static void
 34.1807 -rebuild_file_package_lists(struct razor_set *set)
 34.1808 -{
 34.1809 -	struct array *pkgs, *a;
 34.1810 -	struct razor_package *pkg, *pkg_end;
 34.1811 -	struct razor_entry *entry, *entry_end;
 34.1812 -	struct list *r;
 34.1813 -	uint32_t *q;
 34.1814 -	int count;
 34.1815 -
 34.1816 -	count = set->files.size / sizeof (struct razor_entry);
 34.1817 -	pkgs = zalloc(count * sizeof *pkgs);
 34.1818 -	pkg_end = set->packages.data + set->packages.size;
 34.1819 -
 34.1820 -	for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
 34.1821 -		r = list_first(&pkg->files, &set->file_pool);
 34.1822 -		while (r) {
 34.1823 -			q = array_add(&pkgs[r->data], sizeof *q);
 34.1824 -			*q = pkg - (struct razor_package *) set->packages.data;
 34.1825 -			r = list_next(r);
 34.1826 -		}
 34.1827 -	}
 34.1828 -
 34.1829 -	entry_end = set->files.data + set->files.size;
 34.1830 -	a = pkgs;
 34.1831 -	for (entry = set->files.data; entry < entry_end; entry++, a++) {
 34.1832 -		list_set_array(&entry->packages, &set->package_pool, a, 0);
 34.1833 -		array_release(a);
 34.1834 -	}
 34.1835 -	free(pkgs);
 34.1836 -}
 34.1837 -
 34.1838 -static struct razor_set *
 34.1839 -razor_merger_finish(struct razor_merger *merger)
 34.1840 -{
 34.1841 -	struct razor_set *result;
 34.1842 -	struct razor_package *p, *pend;
 34.1843 -
 34.1844 -	/* As we built the package list, we filled out a bitvector of
 34.1845 -	 * the properties that are referenced by the packages in the
 34.1846 -	 * new set.  Now we do a parallel loop through the properties
 34.1847 -	 * and emit those marked in the bit vector to the new set.  In
 34.1848 -	 * the process, we update the bit vector to actually map from
 34.1849 -	 * indices in the old property list to indices in the new
 34.1850 -	 * property list for both sets. */
 34.1851 -
 34.1852 -	merge_properties(merger);
 34.1853 -	merge_files(merger);
 34.1854 -
 34.1855 -	/* Now we loop through the packages again and emit the
 34.1856 -	 * property lists, remapped to point to the new properties. */
 34.1857 -
 34.1858 -	pend = merger->set->packages.data + merger->set->packages.size;
 34.1859 -	for (p = merger->set->packages.data; p < pend; p++) {
 34.1860 -		struct source *src;
 34.1861 -
 34.1862 -		if (p->flags & UPSTREAM_SOURCE)
 34.1863 -			src = &merger->source2;
 34.1864 -		else
 34.1865 -			src = &merger->source1;
 34.1866 -
 34.1867 -		emit_properties(&p->properties,
 34.1868 -				&src->set->property_pool,
 34.1869 -				src->property_map,
 34.1870 -				&merger->set->property_pool);
 34.1871 -		emit_files(&p->files,
 34.1872 -			   &src->set->file_pool,
 34.1873 -			   src->file_map,
 34.1874 -			   &merger->set->file_pool);
 34.1875 -		p->flags &= ~UPSTREAM_SOURCE;
 34.1876 -	}
 34.1877 -
 34.1878 -	rebuild_property_package_lists(merger->set);
 34.1879 -	rebuild_file_package_lists(merger->set);
 34.1880 -
 34.1881 -	result = merger->set;
 34.1882 -	hashtable_release(&merger->table);
 34.1883 -	hashtable_release(&merger->file_table);
 34.1884 -	hashtable_release(&merger->details_table);
 34.1885 -	free(merger);
 34.1886 -
 34.1887 -	return result;
 34.1888 -}
 34.1889 -
 34.1890 -/* The diff order matters.  We should sort the packages so that a
 34.1891 - * REMOVE of a package comes before the INSTALL, and so that all
 34.1892 - * requires for a package have been installed before the package.
 34.1893 - **/
 34.1894 -
 34.1895 -void
 34.1896 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
 34.1897 -	       razor_package_callback_t callback, void *data)
 34.1898 -{
 34.1899 -	struct razor_package_iterator *pi1, *pi2;
 34.1900 -	struct razor_package *p1, *p2;
 34.1901 -	const char *name1, *name2, *version1, *version2, *arch1, *arch2;
 34.1902 -	int res;
 34.1903 -
 34.1904 -	pi1 = razor_package_iterator_create(set);
 34.1905 -	pi2 = razor_package_iterator_create(upstream);
 34.1906 -
 34.1907 -	razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
 34.1908 -	razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
 34.1909 -
 34.1910 -	while (p1 || p2) {
 34.1911 -		if (p1 && p2) {
 34.1912 -			res = strcmp(name1, name2);
 34.1913 -			if (res == 0)
 34.1914 -				res = versioncmp(version1, version2);
 34.1915 -		} else {
 34.1916 -			res = 0;
 34.1917 -		}
 34.1918 -
 34.1919 -		if (p2 == NULL || res < 0)
 34.1920 -			callback(name1, version1, NULL, arch1, data);
 34.1921 -		else if (p1 == NULL || res > 0)
 34.1922 -			callback(name2, NULL, version2, arch2, data);
 34.1923 -
 34.1924 -		if (p1 != NULL && res <= 0)
 34.1925 -			razor_package_iterator_next(pi1, &p1,
 34.1926 -						    &name1, &version1, &arch1);
 34.1927 -		if (p2 != NULL && res >= 0)
 34.1928 -			razor_package_iterator_next(pi2, &p2,
 34.1929 -						    &name2, &version2, &arch2);
 34.1930 -	}
 34.1931 -
 34.1932 -	razor_package_iterator_destroy(pi1);
 34.1933 -	razor_package_iterator_destroy(pi2);
 34.1934 -}
 34.1935 -
 34.1936 -struct razor_transaction;
 34.1937 -struct razor_transaction_package;
 34.1938 -struct razor_transaction_resolver;
 34.1939 -
 34.1940 -struct razor_transaction {
 34.1941 -	int package_count, errors;
 34.1942 -	struct razor_set *system, *upstream;
 34.1943 -
 34.1944 -	struct bitarray syspkgs, uppkgs;
 34.1945 -	struct array packages;
 34.1946 -};
 34.1947 -
 34.1948 -struct razor_transaction_package {
 34.1949 -	const char *name, *old_version, *new_version;
 34.1950 -	struct razor_package *old_package, *new_package;
 34.1951 -	enum razor_transaction_package_state state;
 34.1952 -
 34.1953 -	/* dep_package is the name of the package that resulted in
 34.1954 -	 * this entry being created (or NULL if the user requested the
 34.1955 -	 * install/remove), with the other dep_ fields providing
 34.1956 -	 * additional information.
 34.1957 -	 *
 34.1958 -	 * For INSTALL, if dep_type is REQUIRES, then dep_package
 34.1959 -	 * required something that this package provides. If dep_type
 34.1960 -	 * is CONFLICTS, then dep_package is a package that conflicted
 34.1961 -	 * with an older version of this package, forcing an upgrade.
 34.1962 -	 *
 34.1963 -	 * For REMOVE, if dep_type is REQUIRES, then dep_package is a
 34.1964 -	 * package that is being removed. If dep_type is OBSOLETES,
 34.1965 -	 * then dep_package is a package that obsoletes this one.
 34.1966 -	 *
 34.1967 -	 * For OLD_CONFLICT or NEW_CONFLICT, dep_package is an
 34.1968 -	 * existing package that conflicts with this one. The
 34.1969 -	 * conflicting property comes from the already-installed
 34.1970 -	 * package for OLD_CONFLICT, or the to-be-installed package
 34.1971 -	 * for NEW_CONFLICT.
 34.1972 -	 *
 34.1973 -	 * For UNSATISFIABLE, the dep_ fields are as for an INSTALL,
 34.1974 -	 * but the name field will be NULL.
 34.1975 -	 */
 34.1976 -	const char *dep_package;
 34.1977 -	enum razor_property_type dep_type;
 34.1978 -	const char *dep_property;
 34.1979 -	enum razor_version_relation dep_relation;
 34.1980 -	const char *dep_version;
 34.1981 -};
 34.1982 -
 34.1983 -static int
 34.1984 -package_in_set(void *package, struct razor_set *set)
 34.1985 -{
 34.1986 -	return package >= set->packages.data &&
 34.1987 -		package < set->packages.data + set->packages.size;
 34.1988 -}
 34.1989 -
 34.1990 -static int
 34.1991 -property_in_set(void *property, struct razor_set *set)
 34.1992 -{
 34.1993 -	return property >= set->properties.data &&
 34.1994 -		property < set->properties.data + set->properties.size;
 34.1995 -}
 34.1996 -
 34.1997 -static struct razor_package *
 34.1998 -property_provider_package(struct razor_transaction *trans,
 34.1999 -			  struct razor_property *prop,
 34.2000 -			  int installed)
 34.2001 -{
 34.2002 -	struct razor_set *set;
 34.2003 -	struct bitarray *pkgbits;
 34.2004 -	struct razor_package *pkgs;
 34.2005 -	struct list *p;
 34.2006 -
 34.2007 -	if (installed && prop->type != RAZOR_PROPERTY_PROVIDES)
 34.2008 -		return NULL;
 34.2009 -	else if (!installed &&
 34.2010 -		 prop->type != RAZOR_PROPERTY_PROVIDES &&
 34.2011 -		 prop->type != RAZOR_PROPERTY_OBSOLETES)
 34.2012 -		return NULL;
 34.2013 -
 34.2014 -	if (property_in_set(prop, trans->system)) {
 34.2015 -		set = trans->system;
 34.2016 -		pkgbits = &trans->syspkgs;
 34.2017 -	} else {
 34.2018 -		set = trans->upstream;
 34.2019 -		pkgbits = &trans->uppkgs;
 34.2020 -	}
 34.2021 -	pkgs = set->packages.data;
 34.2022 -
 34.2023 -	for (p = list_first(&prop->packages, &set->package_pool); p; p = list_next(p)) {
 34.2024 -		if (bitarray_get(pkgbits, p->data) != installed)
 34.2025 -			continue;
 34.2026 -		if (prop->type == RAZOR_PROPERTY_OBSOLETES ||
 34.2027 -		    pkgs[p->data].name == prop->name)
 34.2028 -			return &pkgs[p->data];
 34.2029 -	}
 34.2030 -	return NULL;
 34.2031 -}
 34.2032 -
 34.2033 -static int
 34.2034 -compare_transaction_packages(const void *one, const void *two)
 34.2035 -{
 34.2036 -	struct razor_transaction_package **tp1 = (void *)one;
 34.2037 -	struct razor_transaction_package **tp2 = (void *)two;
 34.2038 -
 34.2039 -	if (!(*tp1)->name)
 34.2040 -		return 1;
 34.2041 -	else if (!(*tp2)->name)
 34.2042 -		return -1;
 34.2043 -	else
 34.2044 -		return strcmp((*tp1)->name, (*tp2)->name);
 34.2045 -}
 34.2046 -
 34.2047 -/* FIXME: merge this into the other property loop in razor_transaction_satisfy */
 34.2048 -static void
 34.2049 -resolve_new_packages(struct razor_transaction *trans,
 34.2050 -		     int start, int end)
 34.2051 -{
 34.2052 -	struct razor_property *sp, *up, *sp_end, *up_end;
 34.2053 -	struct razor_package *spkg, *spkgs, *upkg, *upkgs;
 34.2054 -	struct razor_transaction_package **packages;
 34.2055 -	const char *spool, *upool;
 34.2056 -	int i;
 34.2057 -
 34.2058 -	sp_end = trans->system->properties.data + trans->system->properties.size;
 34.2059 -	spool = trans->system->string_pool.data;
 34.2060 -	spkgs = trans->system->packages.data;
 34.2061 -	up_end = trans->upstream->properties.data + trans->upstream->properties.size;
 34.2062 -	upool = trans->upstream->string_pool.data;
 34.2063 -	upkgs = trans->upstream->packages.data;
 34.2064 -
 34.2065 -	/* FIXME, check if sorting the packages directly (rather than
 34.2066 -	 * sorting pointers-to-packages) still results in confusing
 34.2067 -	 * descriptions.
 34.2068 -	 */
 34.2069 -	packages = calloc(end - start, sizeof *packages);
 34.2070 -	for (i = start; i < end; i++)
 34.2071 -		packages[i - start] = ((struct razor_transaction_package *)trans->packages.data) + i;
 34.2072 -	qsort(packages, end - start, sizeof *packages,
 34.2073 -	      compare_transaction_packages);
 34.2074 -
 34.2075 -	sp = trans->system->properties.data;
 34.2076 -	up = trans->upstream->properties.data;
 34.2077 -	for (i = 0; i < end - start; i++) {
 34.2078 -		if (!packages[i]->name ||
 34.2079 -		    packages[i]->state >= RAZOR_PACKAGE_FIRST_ERROR_STATE)
 34.2080 -			continue;
 34.2081 -
 34.2082 -		spkg = NULL;
 34.2083 -		while (sp < sp_end &&
 34.2084 -		       strcmp(&spool[sp->name], packages[i]->name) < 0)
 34.2085 -			sp++;
 34.2086 -		while (sp < sp_end &&
 34.2087 -		       strcmp(&spool[sp->name], packages[i]->name) == 0 &&
 34.2088 -		       !(spkg = property_provider_package(trans, sp, 1)))
 34.2089 -			sp++;
 34.2090 -
 34.2091 -		upkg = NULL;
 34.2092 -		while (up < up_end &&
 34.2093 -		       strcmp(&upool[up->name], packages[i]->name) < 0)
 34.2094 -			up++;
 34.2095 -		while (up < up_end &&
 34.2096 -		       strcmp(&upool[up->name], packages[i]->name) == 0 &&
 34.2097 -		       !(upkg = property_provider_package(trans, up, 0)))
 34.2098 -			up++;
 34.2099 -
 34.2100 -		if (packages[i]->state == RAZOR_PACKAGE_REMOVE ||
 34.2101 -		    packages[i]->state == RAZOR_PACKAGE_OBSOLETED) {
 34.2102 -			if (spkg) {
 34.2103 -				packages[i]->old_package = spkg;
 34.2104 -				packages[i]->name = &spool[spkg->name];
 34.2105 -				packages[i]->old_version = &spool[spkg->version];
 34.2106 -				bitarray_set(&trans->syspkgs, spkg - spkgs, 0);
 34.2107 -			}
 34.2108 -			if (!packages[i]->old_package) {
 34.2109 -				packages[i]->name = strdup(packages[i]->name);
 34.2110 -				packages[i]->state |= RAZOR_PACKAGE_UNAVAILABLE_FLAG;
 34.2111 -				trans->errors++;
 34.2112 -			}
 34.2113 -		} else {
 34.2114 -			if (upkg) {
 34.2115 -				packages[i]->new_package = upkg;
 34.2116 -				packages[i]->name = &upool[upkg->name];
 34.2117 -				packages[i]->new_version = &upool[upkg->version];
 34.2118 -
 34.2119 -				if (up->name != upkg->name) {
 34.2120 -					packages[i]->dep_package = &upool[upkg->name];
 34.2121 -					packages[i]->dep_type = up->type;
 34.2122 -					packages[i]->dep_property = &upool[up->name];
 34.2123 -					packages[i]->dep_relation = up->relation;
 34.2124 -					packages[i]->dep_version = &upool[up->version];
 34.2125 -				}
 34.2126 -
 34.2127 -				if (spkg) {
 34.2128 -					packages[i]->old_package = spkg;
 34.2129 -					packages[i]->old_version = &spool[spkg->version];
 34.2130 -					if (versioncmp(&spool[spkg->version], &upool[up->version]) >= 0) {
 34.2131 -						packages[i]->state = RAZOR_PACKAGE_UP_TO_DATE;
 34.2132 -						trans->errors++;
 34.2133 -						continue;
 34.2134 -					}
 34.2135 -					bitarray_set(&trans->syspkgs, spkg - spkgs, 0);
 34.2136 -				}
 34.2137 -				bitarray_set(&trans->uppkgs, upkg - upkgs, 1);
 34.2138 -			}
 34.2139 -			if (!packages[i]->new_package) {
 34.2140 -				packages[i]->name = strdup(packages[i]->name);
 34.2141 -				packages[i]->state |= RAZOR_PACKAGE_UNAVAILABLE_FLAG;
 34.2142 -				trans->errors++;
 34.2143 -			}
 34.2144 -		}
 34.2145 -	}
 34.2146 -}
 34.2147 -
 34.2148 -static int
 34.2149 -provider_satisfies_requirement(struct razor_property *provider,
 34.2150 -			       const char *provider_strings,
 34.2151 -			       struct razor_property *requirement,
 34.2152 -			       const char *requirement_strings)
 34.2153 -{
 34.2154 -	int cmp, len;
 34.2155 -	const char *provided = &provider_strings[provider->version];
 34.2156 -	const char *required = &requirement_strings[requirement->version];
 34.2157 -
 34.2158 -	if (!*required)
 34.2159 -		return 1;
 34.2160 -	if (!*provided) {
 34.2161 -		if (requirement->relation >= RAZOR_VERSION_EQUAL)
 34.2162 -			return 1;
 34.2163 -		else
 34.2164 -			return 0;
 34.2165 -	}
 34.2166 -
 34.2167 -	cmp = versioncmp(provided, required);
 34.2168 -
 34.2169 -	switch (requirement->relation) {
 34.2170 -	case RAZOR_VERSION_LESS:
 34.2171 -		return cmp < 0;
 34.2172 -
 34.2173 -	case RAZOR_VERSION_LESS_OR_EQUAL:
 34.2174 -		if (cmp <= 0)
 34.2175 -			return 1;
 34.2176 -		/* fall through: FIXME, make sure this is correct */
 34.2177 -
 34.2178 -	case RAZOR_VERSION_EQUAL:
 34.2179 -		if (cmp == 0)
 34.2180 -			return 1;
 34.2181 -
 34.2182 -		/* "foo == 1.1" is satisfied by "foo 1.1-2" */
 34.2183 -		len = strlen(required);
 34.2184 -		if (!strncmp(required, provided, len) && provided[len] == '-')
 34.2185 -			return 1;
 34.2186 -		return 0;
 34.2187 -
 34.2188 -	case RAZOR_VERSION_GREATER_OR_EQUAL:
 34.2189 -		return cmp >= 0;
 34.2190 -
 34.2191 -	case RAZOR_VERSION_GREATER:
 34.2192 -		return cmp > 0;
 34.2193 -	}
 34.2194 -
 34.2195 -	/* shouldn't happen */
 34.2196 -	return 0;
 34.2197 -}
 34.2198 -
 34.2199 -static struct razor_package *
 34.2200 -find_package_for_file(struct razor_set *set, struct bitarray *pkgbits,
 34.2201 -		      const char *filename, int installed)
 34.2202 -{
 34.2203 -	struct razor_package *pkgs = set->packages.data;
 34.2204 -	struct razor_entry *entry;
 34.2205 -	struct list *p;
 34.2206 -
 34.2207 -	if (filename[0] != '/')
 34.2208 -		return 0;
 34.2209 -
 34.2210 -	entry = find_entry(set, set->files.data, filename);
 34.2211 -	if (!entry)
 34.2212 -		return 0;
 34.2213 -
 34.2214 -	for (p = list_first(&entry->packages, &set->package_pool); p; p = list_next(p)) {
 34.2215 -		if (bitarray_get(pkgbits, p->data) == installed)
 34.2216 -			return &pkgs[p->data];
 34.2217 -	}
 34.2218 -	return NULL;
 34.2219 -}
 34.2220 -
 34.2221 -static struct razor_package *
 34.2222 -find_installed_package_for_file(struct razor_transaction *trans,
 34.2223 -				const char *filename)
 34.2224 -{
 34.2225 -	struct razor_package *pkg;
 34.2226 -
 34.2227 -	pkg = find_package_for_file(trans->system, &trans->syspkgs,
 34.2228 -				    filename, 1);
 34.2229 -	if (!pkg)
 34.2230 -		pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
 34.2231 -					    filename, 1);
 34.2232 -	return pkg;
 34.2233 -}
 34.2234 -
 34.2235 -static struct razor_package *
 34.2236 -find_uninstalled_package_for_file(struct razor_transaction *trans,
 34.2237 -				  const char *filename)
 34.2238 -{
 34.2239 -	struct razor_package *pkg;
 34.2240 -
 34.2241 -	pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
 34.2242 -				    filename, 0);
 34.2243 -	if (!pkg)
 34.2244 -		pkg = find_package_for_file(trans->system, &trans->syspkgs,
 34.2245 -					    filename, 0);
 34.2246 -	return pkg;
 34.2247 -}
 34.2248 -
 34.2249 -static struct razor_property *
 34.2250 -skip_to_matching_property(struct razor_transaction *trans,
 34.2251 -			  struct razor_property *match,
 34.2252 -			  struct razor_property *prop)
 34.2253 -{
 34.2254 -	struct razor_set *mset, *pset;
 34.2255 -	const char *ppool, *mpool;
 34.2256 -	struct razor_property *prop_end;
 34.2257 -
 34.2258 -	if (property_in_set(match, trans->system))
 34.2259 -		mset = trans->system;
 34.2260 -	else
 34.2261 -		mset = trans->upstream;
 34.2262 -
 34.2263 -	if (property_in_set(prop, trans->system))
 34.2264 -		pset = trans->system;
 34.2265 -	else if (property_in_set(prop, trans->upstream))
 34.2266 -		pset = trans->upstream;
 34.2267 -	else
 34.2268 -		return prop;
 34.2269 -
 34.2270 -	prop_end = pset->properties.data + pset->properties.size;
 34.2271 -	ppool = pset->string_pool.data;
 34.2272 -	mpool = mset->string_pool.data;
 34.2273 -
 34.2274 -	while (prop < prop_end &&
 34.2275 -	       strcmp(&ppool[prop->name], &mpool[match->name]) < 0)
 34.2276 -		prop++;
 34.2277 -	return prop;
 34.2278 -}
 34.2279 -
 34.2280 -static struct razor_package *
 34.2281 -find_package_matching(struct razor_transaction *trans, int installed,
 34.2282 -		      struct razor_property *prop,
 34.2283 -		      struct razor_property *req,
 34.2284 -		      struct razor_set *req_set)
 34.2285 -{
 34.2286 -	struct razor_set *set;
 34.2287 -	struct bitarray *pkgbits;
 34.2288 -	struct razor_package *pkgs;
 34.2289 -	struct razor_property *props, *prop_end;
 34.2290 -	enum razor_property_type match_type;
 34.2291 -	const char *pool;
 34.2292 -	const char *rpool;
 34.2293 -	int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES);
 34.2294 -	int match;
 34.2295 -
 34.2296 -	if (property_in_set(prop, trans->system)) {
 34.2297 -		set = trans->system;
 34.2298 -		pkgbits = &trans->syspkgs;
 34.2299 -	} else if (property_in_set(prop, trans->upstream)) {
 34.2300 -		set = trans->upstream;
 34.2301 -		pkgbits = &trans->uppkgs;
 34.2302 -	} else
 34.2303 -		return NULL;
 34.2304 -
 34.2305 -	if (!req_set) {
 34.2306 -		if (property_in_set(req, trans->system))
 34.2307 -			req_set = trans->system;
 34.2308 -		else
 34.2309 -			req_set = trans->upstream;
 34.2310 -	}
 34.2311 -	rpool = req_set->string_pool.data;
 34.2312 -
 34.2313 -	if (req->type == RAZOR_PROPERTY_PROVIDES)
 34.2314 -		match_type = RAZOR_PROPERTY_CONFLICTS;
 34.2315 -	else
 34.2316 -		match_type = RAZOR_PROPERTY_PROVIDES;
 34.2317 -
 34.2318 -	pkgs = set->packages.data;
 34.2319 -	props = set->properties.data;
 34.2320 -	prop_end = set->properties.data + set->properties.size;
 34.2321 -	pool = set->string_pool.data;
 34.2322 -
 34.2323 -	/* Find first matching property */
 34.2324 -	while (prop < prop_end &&
 34.2325 -	       strcmp(&pool[prop->name], &rpool[req->name]) < 0)
 34.2326 -		prop++;
 34.2327 -	if (prop == prop_end ||
 34.2328 -	    strcmp(&pool[prop->name], &rpool[req->name]) > 0)
 34.2329 -		return NULL;
 34.2330 -
 34.2331 -	if (prop->type < match_type) {
 34.2332 -		while (prop < prop_end && prop->type != match_type)
 34.2333 -			prop++;
 34.2334 -	} else {
 34.2335 -		while (prop >= props && prop->type != match_type)
 34.2336 -			prop--;
 34.2337 -		while (prop > props + 1 && (prop - 1)->name == prop->name &&
 34.2338 -		       (prop - 1)->type == match_type)
 34.2339 -			prop--;
 34.2340 -	}
 34.2341 -
 34.2342 -	/* Scan matching properties */
 34.2343 -	while (prop < prop_end && prop->type == match_type &&
 34.2344 -	       strcmp(&pool[prop->name], &rpool[req->name]) == 0) {
 34.2345 -		if (match_type == RAZOR_PROPERTY_PROVIDES)
 34.2346 -			match = provider_satisfies_requirement(prop, pool, req, rpool);
 34.2347 -		else
 34.2348 -			match = provider_satisfies_requirement(req, rpool, prop, pool);
 34.2349 -		if (match) {
 34.2350 -			struct list *pkg;
 34.2351 -
 34.2352 -			for (pkg = list_first(&prop->packages, &set->package_pool); pkg; pkg = list_next(pkg)) {
 34.2353 -				if (bitarray_get(pkgbits, pkg->data) != installed)
 34.2354 -					continue;
 34.2355 -				if (!match_name ||
 34.2356 -				    strcmp(&pool[pkgs[pkg->data].name],
 34.2357 -					   &rpool[req->name]) == 0)
 34.2358 -					return &pkgs[pkg->data];
 34.2359 -			}
 34.2360 -		}
 34.2361 -		prop++;
 34.2362 -	}
 34.2363 -
 34.2364 -	return NULL;
 34.2365 -}
 34.2366 -
 34.2367 -static struct razor_package *
 34.2368 -find_installed_package_for_property(struct razor_transaction *trans,
 34.2369 -				    struct razor_property *sys_start,
 34.2370 -				    struct razor_property *up_start,
 34.2371 -				    struct razor_property *req)
 34.2372 -{
 34.2373 -	struct razor_package *pkg;
 34.2374 -
 34.2375 -	pkg = find_package_matching(trans, 1, sys_start, req, NULL);
 34.2376 -	if (!pkg)
 34.2377 -		pkg = find_package_matching(trans, 1, up_start, req, NULL);
 34.2378 -	return pkg;
 34.2379 -}
 34.2380 -
 34.2381 -static struct razor_package *
 34.2382 -find_uninstalled_package_for_property(struct razor_transaction *trans,
 34.2383 -				      struct razor_property *sys_start,
 34.2384 -				      struct razor_property *up_start,
 34.2385 -				      struct razor_property *req)
 34.2386 -{
 34.2387 -	struct razor_package *pkg;
 34.2388 -
 34.2389 -	pkg = find_package_matching(trans, 0, up_start, req, NULL);
 34.2390 -	if (!pkg)
 34.2391 -		pkg = find_package_matching(trans, 0, sys_start, req, NULL);
 34.2392 -	return pkg;
 34.2393 -}
 34.2394 -
 34.2395 -static struct razor_transaction_package *
 34.2396 -find_transaction_package(struct razor_transaction *trans, const char *name)
 34.2397 -{
 34.2398 -	struct razor_transaction_package *packages;
 34.2399 -	int count, i;
 34.2400 -
 34.2401 -	packages = trans->packages.data;
 34.2402 -	count = trans->packages.size / sizeof *packages;
 34.2403 -	for (i = 0; i < count; i++) {
 34.2404 -		if (packages[i].name && !strcmp(packages[i].name, name))
 34.2405 -			return &packages[i];
 34.2406 -	}
 34.2407 -	return NULL;
 34.2408 -}
 34.2409 -
 34.2410 -/* FIXME? */
 34.2411 -static int
 34.2412 -prop_is_being_installed(struct razor_transaction *trans,
 34.2413 -			struct razor_property *prop)
 34.2414 -{
 34.2415 -	struct list *pkg;
 34.2416 -
 34.2417 -	for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
 34.2418 -		if (bitarray_get(&trans->uppkgs, pkg->data))
 34.2419 -			return 1;
 34.2420 -	}
 34.2421 -	return 0;
 34.2422 -}
 34.2423 -
 34.2424 -static int
 34.2425 -prop_is_being_removed(struct razor_transaction *trans,
 34.2426 -		      struct razor_property *prop)
 34.2427 -{
 34.2428 -	struct list *pkg;
 34.2429 -
 34.2430 -	for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
 34.2431 -		if (bitarray_get(&trans->syspkgs, pkg->data))
 34.2432 -			return 0;
 34.2433 -	}
 34.2434 -	return 1;
 34.2435 -}
 34.2436 -
 34.2437 -static int
 34.2438 -prop_is_being_updated(struct razor_transaction *trans,
 34.2439 -		      struct razor_property *prop)
 34.2440 -{
 34.2441 -	struct razor_package *packages = trans->system->packages.data;
 34.2442 -	const char *pool = trans->system->string_pool.data;
 34.2443 -	struct razor_transaction_package *tp;
 34.2444 -	struct list *pkg;
 34.2445 -
 34.2446 -	/* Assumes prop_is_being_removed returns true */
 34.2447 -
 34.2448 -	for (pkg = list_first(&prop->packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
 34.2449 -		tp = find_transaction_package(trans, &pool[packages[pkg->data].name]);
 34.2450 -		if (tp && tp->state == RAZOR_PACKAGE_REMOVE)
 34.2451 -			return 0;
 34.2452 -	}
 34.2453 -	return 1;
 34.2454 -}
 34.2455 -
 34.2456 -static void
 34.2457 -add_transaction_package(struct razor_transaction *trans,
 34.2458 -			struct razor_package *new_package,
 34.2459 -			struct razor_package *old_package,
 34.2460 -			enum razor_transaction_package_state state,
 34.2461 -			const char *req_package,
 34.2462 -			struct razor_property *req_prop)
 34.2463 -{
 34.2464 -	struct razor_set *new_package_set, *old_package_set, *req_set;
 34.2465 -	struct bitarray *reqpkgbits;
 34.2466 -	struct razor_transaction_package *tp, *already;
 34.2467 -	const char *pool;
 34.2468 -	struct razor_package *pkgs;
 34.2469 -	struct list *pkg;
 34.2470 -	int contradiction = 0;
 34.2471 -
 34.2472 -	if (package_in_set(new_package, trans->system))
 34.2473 -		new_package_set = trans->system;
 34.2474 -	else
 34.2475 -		new_package_set = trans->upstream;
 34.2476 -	if (package_in_set(old_package, trans->system))
 34.2477 -		old_package_set = trans->system;
 34.2478 -	else
 34.2479 -		old_package_set = trans->upstream;
 34.2480 -	if (property_in_set(req_prop, trans->system)) {
 34.2481 -		req_set = trans->system;
 34.2482 -		reqpkgbits = &trans->syspkgs;
 34.2483 -	} else {
 34.2484 -		req_set = trans->upstream;
 34.2485 -		reqpkgbits = &trans->uppkgs;
 34.2486 -	}
 34.2487 -
 34.2488 -	if (new_package) {
 34.2489 -		pool = new_package_set->string_pool.data;
 34.2490 -		already = find_transaction_package(trans, &pool[new_package->name]);
 34.2491 -		if (already) {
 34.2492 -			if (already->new_package == new_package) {
 34.2493 -				/* Already taken care of */
 34.2494 -				return;
 34.2495 -			} else if (new_package_set == trans->upstream &&
 34.2496 -				   already->state == RAZOR_PACKAGE_FORCED_UPDATE) {
 34.2497 -				already->new_package = new_package;
 34.2498 -				return;
 34.2499 -			} else if (new_package_set == trans->upstream) {
 34.2500 -				return;
 34.2501 -			}
 34.2502 -
 34.2503 -			/* Oops. We lose */
 34.2504 -			if (state != RAZOR_PACKAGE_CONTRADICTION)
 34.2505 -				contradiction = 1;
 34.2506 -		}
 34.2507 -	} else if (old_package) {
 34.2508 -		pool = old_package_set->string_pool.data;
 34.2509 -		already = find_transaction_package(trans, &pool[old_package->name]);
 34.2510 -		if (already) {
 34.2511 -			if (already->old_package == old_package) {
 34.2512 -				/* Already taken care of */
 34.2513 -				return;
 34.2514 -			} else if (old_package_set == trans->system) {
 34.2515 -				already->old_package = old_package;
 34.2516 -				return;
 34.2517 -			}
 34.2518 -
 34.2519 -			/* Oops. We lose */
 34.2520 -			if (state != RAZOR_PACKAGE_CONTRADICTION)
 34.2521 -				contradiction = 1;
 34.2522 -		}
 34.2523 -	} else
 34.2524 -		state = RAZOR_PACKAGE_UNSATISFIABLE;
 34.2525 -
 34.2526 -	tp = array_add(&trans->packages, sizeof *tp);
 34.2527 -	memset(tp, 0, sizeof *tp);
 34.2528 -
 34.2529 -	if (new_package) {
 34.2530 -		pool = new_package_set->string_pool.data;
 34.2531 -		tp->new_package = new_package;
 34.2532 -		tp->name = &pool[new_package->name];
 34.2533 -		tp->new_version = &pool[new_package->version];
 34.2534 -
 34.2535 -		pkgs = new_package_set->packages.data;
 34.2536 -	}
 34.2537 -	if (old_package) {
 34.2538 -		pool = old_package_set->string_pool.data;
 34.2539 -		tp->old_package = old_package;
 34.2540 -		tp->name = &pool[old_package->name];
 34.2541 -		tp->old_version = &pool[old_package->version];
 34.2542 -
 34.2543 -		pkgs = old_package_set->packages.data;
 34.2544 -	}
 34.2545 -
 34.2546 -	tp->state = state;
 34.2547 -	if (state != RAZOR_PACKAGE_INSTALL &&
 34.2548 -	    state != RAZOR_PACKAGE_FORCED_UPDATE &&
 34.2549 -	    state != RAZOR_PACKAGE_REMOVE &&
 34.2550 -	    state != RAZOR_PACKAGE_OBSOLETED)
 34.2551 -		trans->errors++;
 34.2552 -
 34.2553 -	if (contradiction) {
 34.2554 -		/* Do this now, after adding tp, so that it ends up
 34.2555 -		 * after both the INSTALL and the REMOVE in the array.
 34.2556 -		 */
 34.2557 -		add_transaction_package(trans, new_package, old_package,
 34.2558 -					RAZOR_PACKAGE_CONTRADICTION,
 34.2559 -					NULL, NULL);
 34.2560 -	}
 34.2561 -
 34.2562 -	if (req_package)
 34.2563 -		tp->dep_package = req_package;
 34.2564 -	if (!req_prop)
 34.2565 -		return;
 34.2566 -
 34.2567 -	pool = req_set->string_pool.data;
 34.2568 -	pkgs = req_set->packages.data;
 34.2569 -	if (!req_package) {
 34.2570 -		for (pkg = list_first(&req_prop->packages, &req_set->package_pool); pkg; pkg = list_next(pkg)) {
 34.2571 -			if (bitarray_get(reqpkgbits, pkg->data))
 34.2572 -				break;
 34.2573 -		}
 34.2574 -		if (pkg)
 34.2575 -			tp->dep_package = &pool[pkgs[pkg->data].name];
 34.2576 -	}
 34.2577 -
 34.2578 -	tp->dep_type = req_prop->type;
 34.2579 -	tp->dep_property = &pool[req_prop->name];
 34.2580 -	tp->dep_relation = req_prop->relation;
 34.2581 -	tp->dep_version = &pool[req_prop->version];
 34.2582 -}
 34.2583 -
 34.2584 -static void
 34.2585 -razor_transaction_satisfy(struct razor_transaction *trans)
 34.2586 -{
 34.2587 -	struct razor_package *spkgs, *upkgs, *pkg;
 34.2588 -	struct razor_property *sp, *sprops, *sprop_end;
 34.2589 -	struct razor_property *up, *uprops, *uprop_end;
 34.2590 -	struct razor_property *sr, *ur, *first_up;
 34.2591 -	const char *spool, *upool, *removed_package;
 34.2592 -	struct list *reqpkg;
 34.2593 -
 34.2594 -	spkgs = trans->system->packages.data;
 34.2595 -	sprops = trans->system->properties.data;
 34.2596 -	sprop_end = trans->system->properties.data + trans->system->properties.size;
 34.2597 -	spool = trans->system->string_pool.data;
 34.2598 -	upkgs = trans->upstream->packages.data;
 34.2599 -	uprops = trans->upstream->properties.data;
 34.2600 -	uprop_end = trans->upstream->properties.data + trans->upstream->properties.size;
 34.2601 -	upool = trans->upstream->string_pool.data;
 34.2602 -
 34.2603 -	sp = sprops;
 34.2604 -	for (up = uprops; up < uprop_end; up++) {
 34.2605 -		/* Skip 'up' ahead to a property of a package which is
 34.2606 -		 * to-be-installed.
 34.2607 -		 */
 34.2608 -		while (up < uprop_end &&
 34.2609 -		       !prop_is_being_installed(trans, up))
 34.2610 -			up++;
 34.2611 -		if (up == uprop_end)
 34.2612 -			break;
 34.2613 -		sp = skip_to_matching_property(trans, up, sp);
 34.2614 -
 34.2615 -		switch (up->type) {
 34.2616 -		case RAZOR_PROPERTY_REQUIRES:
 34.2617 -			if (!strncmp(&upool[up->name], "rpmlib(", 7))
 34.2618 -				break;
 34.2619 -
 34.2620 -			if (find_installed_package_for_property(trans, sp, up, up) ||
 34.2621 -			    find_installed_package_for_file(trans, &upool[up->name])) {
 34.2622 -				/* Requires something that is either installed
 34.2623 -				 * or to-be-installed.
 34.2624 -				 */
 34.2625 -				break;
 34.2626 -			}
 34.2627 -
 34.2628 -			/* See if we can install a new upstream provider */
 34.2629 -			pkg = find_uninstalled_package_for_property(trans, sp, up, up);
 34.2630 -			if (!pkg)
 34.2631 -				pkg = find_uninstalled_package_for_file(trans, &upool[up->name]);
 34.2632 -			add_transaction_package(trans, pkg, NULL,
 34.2633 -						RAZOR_PACKAGE_INSTALL,
 34.2634 -						NULL, up);
 34.2635 -			break;
 34.2636 -
 34.2637 -		case RAZOR_PROPERTY_PROVIDES:
 34.2638 -			/* find_installed_package_for_property works backwards
 34.2639 -			 * here, finding a *conflicting* installed package.
 34.2640 -			 */
 34.2641 -			pkg = find_installed_package_for_property(trans, sp, up, up);
 34.2642 -			if (!pkg)
 34.2643 -				break;
 34.2644 -
 34.2645 -			if (package_in_set(pkg, trans->system)) {
 34.2646 -				/* pkg CONFLICTS with what 'up' PROVIDES. Try
 34.2647 -				 * finding an upgrade
 34.2648 -				 */
 34.2649 -				add_transaction_package(trans, NULL, pkg,
 34.2650 -							RAZOR_PACKAGE_FORCED_UPDATE,
 34.2651 -							&upool[up->name], sp);
 34.2652 -			} else {
 34.2653 -				add_transaction_package(trans, NULL, pkg,
 34.2654 -							RAZOR_PACKAGE_CONTRADICTION,
 34.2655 -							NULL, up);
 34.2656 -			}
 34.2657 -			break;
 34.2658 -
 34.2659 -		case RAZOR_PROPERTY_CONFLICTS:
 34.2660 -			pkg = find_installed_package_for_property(trans, sp, up, up);
 34.2661 -			if (!pkg)
 34.2662 -				break;
 34.2663 -
 34.2664 -			if (package_in_set(pkg, trans->system)) {
 34.2665 -				/* Conflicts with something already installed.
 34.2666 -				 * Try to upgrade out.
 34.2667 -				 */
 34.2668 -				add_transaction_package(trans, NULL, pkg,
 34.2669 -							RAZOR_PACKAGE_FORCED_UPDATE,
 34.2670 -							NULL, up);
 34.2671 -			} else {
 34.2672 -				add_transaction_package(trans, pkg, NULL,
 34.2673 -							RAZOR_PACKAGE_CONTRADICTION,
 34.2674 -							NULL, up);
 34.2675 -			}
 34.2676 -			break;
 34.2677 -
 34.2678 -		case RAZOR_PROPERTY_OBSOLETES:
 34.2679 -			pkg = find_installed_package_for_property(trans, sp, up, up);
 34.2680 -			if (pkg) {
 34.2681 -				/* If pkg is to-be-installed, this
 34.2682 -				 * will add a CONTRADICTION error as well.
 34.2683 -				 */
 34.2684 -				add_transaction_package(trans, NULL, pkg,
 34.2685 -							RAZOR_PACKAGE_OBSOLETED,
 34.2686 -							NULL, up);
 34.2687 -			}
 34.2688 -			break;
 34.2689 -
 34.2690 -		default:
 34.2691 -			/* can't happen */
 34.2692 -			break;
 34.2693 -		}
 34.2694 -	}
 34.2695 -
 34.2696 -	up = uprops;
 34.2697 -	for (sp = sprops; sp < sprop_end; sp++) {
 34.2698 -		/* Skip 'sp' ahead to a PROVIDES of a package which is
 34.2699 -		 * to-be-removed.
 34.2700 -		 */
 34.2701 -		while (sp < sprop_end &&
 34.2702 -		       (sp->type != RAZOR_PROPERTY_PROVIDES ||
 34.2703 -			!prop_is_being_removed(trans, sp)))
 34.2704 -			sp++;
 34.2705 -		if (sp == sprop_end)
 34.2706 -			break;
 34.2707 -
 34.2708 -		removed_package = &spool[spkgs[list_first(&sp->packages, &trans->system->package_pool)->data].name];
 34.2709 -
 34.2710 -		/* Skip 'up' to match */
 34.2711 -		up = skip_to_matching_property(trans, sp, up);
 34.2712 -		ur = first_up = up;
 34.2713 -
 34.2714 -		/* If the package is just being upgraded, we may
 34.2715 -		 * already be installing an identical PROVIDES, so
 34.2716 -		 * check for that.
 34.2717 -		 */
 34.2718 -		while (up < uprop_end &&
 34.2719 -		       strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
 34.2720 -		       (up->type != RAZOR_PROPERTY_PROVIDES || 
 34.2721 -			sp->relation != up->relation ||
 34.2722 -			strcmp(&spool[sp->name], &upool[up->name]) != 0))
 34.2723 -			up++;
 34.2724 -		if (up < uprop_end &&
 34.2725 -		    up->type == RAZOR_PROPERTY_PROVIDES &&
 34.2726 -		    strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
 34.2727 -		    sp->relation == up->relation &&
 34.2728 -		    strcmp(&spool[sp->version], &upool[up->version]) == 0 &&
 34.2729 -		    prop_is_being_installed(trans, up)) {
 34.2730 -			up = first_up;
 34.2731 -			continue;
 34.2732 -		}
 34.2733 -		up = first_up;
 34.2734 -
 34.2735 -		/* For all still-installed packages that require
 34.2736 -		 * sp->name, see if they are satisfied by any other
 34.2737 -		 * still-installed or to-be-installed property. If
 34.2738 -		 * not, either remove or attempt to update the
 34.2739 -		 * package, depending on why the required property has
 34.2740 -		 * disappeared
 34.2741 -		 */
 34.2742 -		sr = sp;
 34.2743 -		while (sr > sprops + 1 && (sr - 1)->name == sr->name)
 34.2744 -			sr--;
 34.2745 -		for (; sr->type == RAZOR_PROPERTY_REQUIRES; sr++) {
 34.2746 -			if (prop_is_being_removed(trans, sr))
 34.2747 -				continue;
 34.2748 -			if (find_installed_package_for_property(trans, sp, up, sr))
 34.2749 -				continue;
 34.2750 -
 34.2751 -			for (reqpkg = list_first(&sr->packages, &trans->system->package_pool); reqpkg; reqpkg = list_next(reqpkg)) {
 34.2752 -				if (!bitarray_get(&trans->syspkgs, reqpkg->data))
 34.2753 -					continue;
 34.2754 -				pkg = &spkgs[reqpkg->data];
 34.2755 -				if (prop_is_being_updated(trans, sp)) {
 34.2756 -					add_transaction_package(trans, NULL, pkg,
 34.2757 -								RAZOR_PACKAGE_FORCED_UPDATE,
 34.2758 -								removed_package, NULL);
 34.2759 -				} else {
 34.2760 -					add_transaction_package(trans, NULL, pkg,
 34.2761 -								RAZOR_PACKAGE_REMOVE,
 34.2762 -								removed_package, sr);
 34.2763 -				}
 34.2764 -			}
 34.2765 -		}
 34.2766 -	}
 34.2767 -}
 34.2768 -
 34.2769 -void
 34.2770 -razor_transaction_install_package(struct razor_transaction *transaction,
 34.2771 -				  struct razor_package *package)
 34.2772 -{
 34.2773 -	add_transaction_package(transaction, package, NULL,
 34.2774 -				RAZOR_PACKAGE_INSTALL, NULL, NULL);
 34.2775 -}
 34.2776 -
 34.2777 -void
 34.2778 -razor_transaction_remove_package(struct razor_transaction *transaction,
 34.2779 -				 struct razor_package *package)
 34.2780 -{
 34.2781 -	add_transaction_package(transaction, NULL, package,
 34.2782 -				RAZOR_PACKAGE_REMOVE, NULL, NULL);
 34.2783 -}
 34.2784 -
 34.2785 -void
 34.2786 -razor_transaction_update_all(struct razor_transaction *trans)
 34.2787 -{
 34.2788 -	struct razor_package *sp, *spkgs, *send, *up, *upkgs, *uend;
 34.2789 -	const char *spool, *upool;
 34.2790 -
 34.2791 -	spkgs = trans->system->packages.data;
 34.2792 -	send = trans->system->packages.data + trans->system->packages.size;
 34.2793 -	spool = trans->system->string_pool.data;
 34.2794 -	up = upkgs = trans->upstream->packages.data;
 34.2795 -	uend = trans->upstream->packages.data + trans->upstream->packages.size;
 34.2796 -	upool = trans->upstream->string_pool.data;
 34.2797 -
 34.2798 -	for (sp = spkgs; sp < send; sp++) {
 34.2799 -		while (up < uend && strcmp(&spool[sp->name], &upool[up->name]) > 0)
 34.2800 -			up++;
 34.2801 -		if (strcmp(&spool[sp->name], &upool[up->name]) == 0 &&
 34.2802 -		    versioncmp(&spool[sp->version], &upool[up->version]) < 0) {
 34.2803 -			add_transaction_package(trans, up, sp,
 34.2804 -						RAZOR_PACKAGE_INSTALL,
 34.2805 -						NULL, NULL);
 34.2806 -		}
 34.2807 -	}
 34.2808 -}
 34.2809 -
 34.2810 -struct razor_transaction *
 34.2811 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
 34.2812 -{
 34.2813 -	struct razor_transaction *trans;
 34.2814 -	int count;
 34.2815 -
 34.2816 -	trans = zalloc(sizeof *trans);
 34.2817 -
 34.2818 -	trans->system = system;
 34.2819 -	trans->upstream = upstream ? upstream : razor_set_create();
 34.2820 -	array_init(&trans->packages);
 34.2821 -	count = trans->system->packages.size / sizeof (struct razor_package);
 34.2822 -	bitarray_init(&trans->syspkgs, count, 1);
 34.2823 -	count = trans->upstream->packages.size / sizeof (struct razor_package);
 34.2824 -	bitarray_init(&trans->uppkgs, count, 0);
 34.2825 -
 34.2826 -	return trans;
 34.2827 -}
 34.2828 -
 34.2829 -static void
 34.2830 -resolve_transaction(struct razor_transaction *trans)
 34.2831 -{
 34.2832 -	int start, end;
 34.2833 -
 34.2834 -	if (trans->package_count > 0)
 34.2835 -		/* Already did this, return. */
 34.2836 -		return;
 34.2837 -
 34.2838 -	start = 0;
 34.2839 -	end = trans->packages.size / sizeof (struct razor_transaction_package);
 34.2840 -
 34.2841 -	while (start != end) {
 34.2842 -		resolve_new_packages(trans, start, end);
 34.2843 -		if (trans->errors)
 34.2844 -			break;
 34.2845 -
 34.2846 -		razor_transaction_satisfy(trans);
 34.2847 -
 34.2848 -		start = end;
 34.2849 -		end = trans->packages.size / sizeof (struct razor_transaction_package);
 34.2850 -	}
 34.2851 -
 34.2852 -	trans->package_count = end;
 34.2853 -}
 34.2854 -
 34.2855 -const char * const razor_version_relations[] = {
 34.2856 -	/* same order as enum razor_version_relation */
 34.2857 -	"<", "<=", "=", ">=", ">"
 34.2858 -};
 34.2859 -
 34.2860 -const char * const razor_property_types[] = {
 34.2861 -	/* same order as enum razor_property_type */
 34.2862 -	"requires", "provides", "conflicts with", "obsoletes"
 34.2863 -};
 34.2864 -
 34.2865 -static void
 34.2866 -print_requirement(struct razor_transaction_package *p)
 34.2867 -{
 34.2868 -	if (p->dep_type == RAZOR_PROPERTY_CONFLICTS &&
 34.2869 -	    !strcmp(p->dep_package, p->name)) {
 34.2870 -		printf(" because %s %s conflicts with %s",
 34.2871 -		       p->name, p->old_version, p->dep_property);
 34.2872 -		if (*p->dep_version) {
 34.2873 -			printf(" %s %s",
 34.2874 -			       razor_version_relations[p->dep_relation],
 34.2875 -			       p->dep_version);
 34.2876 -		}
 34.2877 -	} else {
 34.2878 -		if (strcmp(p->name, p->dep_package) != 0)
 34.2879 -			printf(" for %s", p->dep_package);
 34.2880 -		if (*p->dep_version) {
 34.2881 -			printf(", which %s %s %s %s",
 34.2882 -			       razor_property_types[p->dep_type],
 34.2883 -			       p->dep_property,
 34.2884 -			       razor_version_relations[p->dep_relation],
 34.2885 -			       p->dep_version);
 34.2886 -		} else if (strcmp(p->dep_property, p->name) != 0) {
 34.2887 -			printf(", which %s %s",
 34.2888 -			       razor_property_types[p->dep_type],
 34.2889 -			       p->dep_property);
 34.2890 -		}
 34.2891 -	}
 34.2892 -}
 34.2893 -
 34.2894 -int
 34.2895 -razor_transaction_resolve(struct razor_transaction *trans)
 34.2896 -{
 34.2897 -	struct razor_transaction_package *p, *pend, *tps;
 34.2898 -	int errors_only = 0;
 34.2899 -
 34.2900 -	resolve_transaction(trans);
 34.2901 -
 34.2902 -	tps = trans->packages.data;
 34.2903 -	pend = trans->packages.data + trans->packages.size;
 34.2904 -	for (p = trans->packages.data; p < pend; p++) {
 34.2905 -		switch (p->state) {
 34.2906 -		case RAZOR_PACKAGE_INSTALL:
 34.2907 -			if (errors_only)
 34.2908 -				break;
 34.2909 -
 34.2910 -			printf("Installing %s %s", p->name, p->new_version);
 34.2911 -			if (p->dep_package)
 34.2912 -				print_requirement(p);
 34.2913 -			printf("\n");
 34.2914 -			break;
 34.2915 -
 34.2916 -		case RAZOR_PACKAGE_FORCED_UPDATE:
 34.2917 -			if (errors_only)
 34.2918 -				break;
 34.2919 -
 34.2920 -			printf("Updating %s to %s due to update of %s\n",
 34.2921 -			       p->name, p->new_version, p->dep_package);
 34.2922 -			break;
 34.2923 -
 34.2924 -		case RAZOR_PACKAGE_REMOVE:
 34.2925 -			if (errors_only)
 34.2926 -				break;
 34.2927 -			printf("Removing %s %s", p->name, p->old_version);
 34.2928 -			if (p->dep_package) {
 34.2929 -				printf(" which required %s",
 34.2930 -				       p->dep_package);
 34.2931 -				if (strcmp(p->dep_property, p->dep_package) != 0)
 34.2932 -					printf(" for %s", p->dep_property);
 34.2933 -			}
 34.2934 -			printf("\n");
 34.2935 -			break;
 34.2936 -
 34.2937 -		case RAZOR_PACKAGE_OBSOLETED:
 34.2938 -			if (errors_only)
 34.2939 -				break;
 34.2940 -			printf("Removing %s %s", p->name, p->old_version);
 34.2941 -			if (p->dep_package) {
 34.2942 -				printf(" which is obsoleted by %s",
 34.2943 -				       p->dep_package);
 34.2944 -			}
 34.2945 -			printf("\n");
 34.2946 -			break;
 34.2947 -
 34.2948 -		case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
 34.2949 -			printf("Error: can't find %s", p->name);
 34.2950 -			if (p->dep_package) {
 34.2951 -				printf(" (which is required");
 34.2952 -				print_requirement(p);
 34.2953 -				printf(")");
 34.2954 -			}
 34.2955 -			printf("\n");
 34.2956 -			errors_only = 1;
 34.2957 -			break;
 34.2958 -
 34.2959 -		case RAZOR_PACKAGE_UPDATE_UNAVAILABLE:
 34.2960 -			printf("Error: can't find an updated version of %s (which must be updated due to update of %s)\n",
 34.2961 -			       p->name, p->dep_package);
 34.2962 -			errors_only = 1;
 34.2963 -			break;
 34.2964 -
 34.2965 -		case RAZOR_PACKAGE_REMOVE_NOT_INSTALLED:
 34.2966 -			printf("Error: can't remove %s: not installed\n", p->name);
 34.2967 -			errors_only = 1;
 34.2968 -			break;
 34.2969 -
 34.2970 -		case RAZOR_PACKAGE_UP_TO_DATE:
 34.2971 -			printf("Error: can't update %s", p->name);
 34.2972 -			if (p->dep_package)
 34.2973 -				printf(" (which must be updated due to update of %s)", p->dep_package);
 34.2974 -			printf(": %s is most recent version\n", p->old_version);
 34.2975 -			errors_only = 1;
 34.2976 -			break;
 34.2977 -
 34.2978 -		case RAZOR_PACKAGE_CONTRADICTION:
 34.2979 -			printf("Error: package %s is marked for both installation and removal\n", p->name);
 34.2980 -			errors_only = 1;
 34.2981 -			break;
 34.2982 -
 34.2983 -		case RAZOR_PACKAGE_OLD_CONFLICT:
 34.2984 -			printf("Error: can't install %s, because installed package %s conflicts with ",
 34.2985 -			       p->name, p->dep_package);
 34.2986 -			if (*p->dep_version) {
 34.2987 -				printf("%s %s %s",
 34.2988 -				       p->dep_property,
 34.2989 -				       razor_version_relations[p->dep_relation],
 34.2990 -				       p->dep_version);
 34.2991 -			} else
 34.2992 -				printf("it");
 34.2993 -			printf("\n");
 34.2994 -
 34.2995 -			errors_only = 1;
 34.2996 -			break;
 34.2997 -
 34.2998 -		case RAZOR_PACKAGE_NEW_CONFLICT:
 34.2999 -			printf("Error: can't install %s, because it conflicts with %s",
 34.3000 -			       p->name, p->dep_package);
 34.3001 -			if (*p->dep_version) {
 34.3002 -				printf(" %s %s",
 34.3003 -				       razor_version_relations[p->dep_relation],
 34.3004 -				       p->dep_version);
 34.3005 -			}
 34.3006 -			printf("\n");
 34.3007 -
 34.3008 -			errors_only = 1;
 34.3009 -			break;
 34.3010 -
 34.3011 -		case RAZOR_PACKAGE_UNSATISFIABLE:
 34.3012 -			printf("Error: can't find package for %s", p->dep_property);
 34.3013 -			if (*p->dep_version) {
 34.3014 -				printf(" %s %s",
 34.3015 -					razor_version_relations[p->dep_relation],
 34.3016 -					p->dep_version);
 34.3017 -			}
 34.3018 -			printf(" which is required by %s\n",
 34.3019 -				p->dep_package);
 34.3020 -			errors_only = 1;
 34.3021 -			break;
 34.3022 -
 34.3023 -		default:
 34.3024 -			/* Shouldn't actually happen */
 34.3025 -			break;
 34.3026 -		}
 34.3027 -	}
 34.3028 -
 34.3029 -	return trans->errors;
 34.3030 -}
 34.3031 -
 34.3032 -int
 34.3033 -razor_transaction_unsatisfied_property(struct razor_transaction *trans,
 34.3034 -				       const char *name,
 34.3035 -				       enum razor_version_relation rel,
 34.3036 -				       const char *version)
 34.3037 -{
 34.3038 -	struct razor_transaction_package *p, *end;
 34.3039 -
 34.3040 -	end = trans->packages.data + trans->packages.size;
 34.3041 -	for (p = trans->packages.data; p < end; p++) {
 34.3042 -		if (p->state != RAZOR_PACKAGE_UNSATISFIABLE)
 34.3043 -			continue;
 34.3044 -		if (strcmp(name, p->dep_property) != 0 ||
 34.3045 -		    rel != p->dep_relation ||
 34.3046 -		    strcmp(version, p->dep_version) != 0)
 34.3047 -			continue;
 34.3048 -
 34.3049 -		return 1;
 34.3050 -	}
 34.3051 -
 34.3052 -	return 0;
 34.3053 -}
 34.3054 -
 34.3055 -struct razor_set *
 34.3056 -razor_transaction_finish(struct razor_transaction *trans)
 34.3057 -{
 34.3058 -	struct array install_packages, remove_packages;
 34.3059 -	struct razor_merger *merger;
 34.3060 -	struct razor_package *pkg, *i, *iend, *r, *rend, *s, *send;
 34.3061 -	struct razor_set *set;
 34.3062 -	struct source *source1, *source2;
 34.3063 -	char *spool, *ipool, *rpool;
 34.3064 -	uint32_t *map;
 34.3065 -	struct razor_transaction_package *p, *end;
 34.3066 -	int cmp;
 34.3067 -
 34.3068 -	/* FIXME */
 34.3069 -	if (trans->errors)
 34.3070 -		return NULL;
 34.3071 -
 34.3072 -	/* Sort the transaction packages into two arrays */
 34.3073 -	array_init(&install_packages);
 34.3074 -	array_init(&remove_packages);
 34.3075 -
 34.3076 -	end = trans->packages.data + trans->packages.size;
 34.3077 -	for (p = trans->packages.data; p < end; p++) {
 34.3078 -		if (p->new_package) {
 34.3079 -			pkg = array_add(&install_packages, sizeof *pkg);
 34.3080 -			*pkg = *p->new_package;
 34.3081 -		} else {
 34.3082 -			pkg = array_add(&remove_packages, sizeof *pkg);
 34.3083 -			*pkg = *p->old_package;
 34.3084 -		}
 34.3085 -	}
 34.3086 -	map = razor_qsort_with_data(install_packages.data,
 34.3087 -				    install_packages.size / sizeof *pkg,
 34.3088 -				    sizeof *pkg,
 34.3089 -				    compare_packages,
 34.3090 -				    trans->upstream);
 34.3091 -	free(map);
 34.3092 -	map = razor_qsort_with_data(remove_packages.data,
 34.3093 -				    remove_packages.size / sizeof *pkg,
 34.3094 -				    sizeof *pkg,
 34.3095 -				    compare_packages,
 34.3096 -				    trans->system);
 34.3097 -	free(map);
 34.3098 -
 34.3099 -	merger = razor_merger_create(trans->system, trans->upstream);
 34.3100 -
 34.3101 -	source1 = &merger->source1;
 34.3102 -	source2 = &merger->source2;
 34.3103 -
 34.3104 -	i = install_packages.data;
 34.3105 -	iend = install_packages.data + install_packages.size;
 34.3106 -	ipool = trans->upstream->string_pool.data;
 34.3107 -
 34.3108 -	r = remove_packages.data;
 34.3109 -	rend = remove_packages.data + remove_packages.size;
 34.3110 -	rpool = trans->system->string_pool.data;
 34.3111 -
 34.3112 -	s = trans->system->packages.data;
 34.3113 -	send = trans->system->packages.data + trans->system->packages.size;
 34.3114 -	spool = trans->system->string_pool.data;
 34.3115 -
 34.3116 -	while (s < send || i < iend) {
 34.3117 -		/* Check if s is being removed */
 34.3118 -		if (s < send && r < rend &&
 34.3119 -		    s->name == r->name && s->version && r->version) {
 34.3120 -			s++;
 34.3121 -			r++;
 34.3122 -			continue;
 34.3123 -		}
 34.3124 -
 34.3125 -		if (s < send && i < iend)
 34.3126 -			cmp = strcmp(&spool[s->name], &ipool[i->name]);
 34.3127 -		else if (s < send)
 34.3128 -			cmp = -1;
 34.3129 -		else
 34.3130 -			cmp = 1;
 34.3131 -		if (cmp < 0) {
 34.3132 -			add_package(merger, s, source1, 0);
 34.3133 -			s++;
 34.3134 -		} else if (cmp == 0) {
 34.3135 -			add_package(merger, i, source2, UPSTREAM_SOURCE);
 34.3136 -			s++;
 34.3137 -			i++;
 34.3138 -		} else {
 34.3139 -			add_package(merger, i, source2, UPSTREAM_SOURCE);
 34.3140 -			i++;
 34.3141 -		}
 34.3142 -	}
 34.3143 -
 34.3144 -	array_release(&install_packages);
 34.3145 -	array_release(&remove_packages);
 34.3146 -
 34.3147 -	set = razor_merger_finish(merger);
 34.3148 -	razor_transaction_destroy(trans);
 34.3149 -
 34.3150 -	return set;
 34.3151 -}
 34.3152 -
 34.3153 -void
 34.3154 -razor_transaction_destroy(struct razor_transaction *trans)
 34.3155 -{
 34.3156 -	struct razor_transaction_package *p, *end;
 34.3157 -
 34.3158 -	end = trans->packages.data + trans->packages.size;
 34.3159 -	for (p = trans->packages.data; p < end; p++) {
 34.3160 -		if (!p->dep_package &&
 34.3161 -		    (p->state == RAZOR_PACKAGE_INSTALL_UNAVAILABLE ||
 34.3162 -		     p->state == RAZOR_PACKAGE_REMOVE_NOT_INSTALLED))
 34.3163 -			free((char *)p->name);
 34.3164 -	}
 34.3165 -
 34.3166 -	array_release(&trans->packages);
 34.3167 -	bitarray_release(&trans->syspkgs);
 34.3168 -	bitarray_release(&trans->uppkgs);
 34.3169 -	free(trans);
 34.3170 -
 34.3171 -	/* FIXME: free upstream if it was created as an empty set */
 34.3172 -}
 34.3173 -
 34.3174 -struct razor_package_query {
 34.3175 -	struct razor_set *set;
 34.3176 -	char *vector;
 34.3177 -	int count;
 34.3178 -};
 34.3179 -
 34.3180 -struct razor_package_query *
 34.3181 -razor_package_query_create(struct razor_set *set)
 34.3182 -{
 34.3183 -	struct razor_package_query *pq;
 34.3184 -	int count;
 34.3185 -
 34.3186 -	pq = zalloc(sizeof *pq);
 34.3187 -	pq->set = set;
 34.3188 -	count = set->packages.size / sizeof(struct razor_package);
 34.3189 -	pq->vector = zalloc(count * sizeof(char));
 34.3190 -
 34.3191 -	return pq;
 34.3192 -}
 34.3193 -
 34.3194 -void
 34.3195 -razor_package_query_add_package(struct razor_package_query *pq,
 34.3196 -				struct razor_package *p)
 34.3197 -{
 34.3198 -	struct razor_package *packages;
 34.3199 -
 34.3200 -	packages = pq->set->packages.data;
 34.3201 -	pq->count += pq->vector[p - packages] ^ 1;
 34.3202 -	pq->vector[p - packages] = 1;
 34.3203 -}
 34.3204 -
 34.3205 -void
 34.3206 -razor_package_query_add_iterator(struct razor_package_query *pq,
 34.3207 -				 struct razor_package_iterator *pi)
 34.3208 -{
 34.3209 -	struct razor_package *packages, *p;
 34.3210 -	const char *name, *version, *arch;
 34.3211 -
 34.3212 -	packages = pq->set->packages.data;
 34.3213 -	while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
 34.3214 -		pq->count += pq->vector[p - packages] ^ 1;
 34.3215 -		pq->vector[p - packages] = 1;
 34.3216 -	}
 34.3217 -}
 34.3218 -
 34.3219 -struct razor_package_iterator *
 34.3220 -razor_package_query_finish(struct razor_package_query *pq)
 34.3221 -{
 34.3222 -	struct razor_package_iterator *pi;
 34.3223 -	struct razor_set *set;
 34.3224 -	struct list *index;
 34.3225 -	int i, j, count;
 34.3226 -
 34.3227 -	set = pq->set;
 34.3228 -	count = set->packages.size / sizeof(struct razor_package);
 34.3229 -	index = zalloc(pq->count * sizeof *index);
 34.3230 -
 34.3231 -	for (i = 0, j = 0; i < count; i++) {
 34.3232 -		if (!pq->vector[i])
 34.3233 -			continue;
 34.3234 -
 34.3235 -		index[j].data = i;
 34.3236 -		if (j == pq->count - 1)
 34.3237 -			index[j].flags = 0x80;
 34.3238 -		j++;
 34.3239 -	}
 34.3240 -
 34.3241 -	free(pq);
 34.3242 -
 34.3243 -	pi = razor_package_iterator_create_with_index(set, index);
 34.3244 -	pi->free_index = 1;
 34.3245 -
 34.3246 -	return pi;
 34.3247 -}
    35.1 --- a/razor.h	Sun Jun 15 18:16:20 2008 -0400
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,220 +0,0 @@
    35.4 -/*
    35.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    35.6 - * Copyright (C) 2008  Red Hat, Inc
    35.7 - *
    35.8 - * This program is free software; you can redistribute it and/or modify
    35.9 - * it under the terms of the GNU General Public License as published by
   35.10 - * the Free Software Foundation; either version 2 of the License, or
   35.11 - * (at your option) any later version.
   35.12 - *
   35.13 - * This program is distributed in the hope that it will be useful,
   35.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.16 - * GNU General Public License for more details.
   35.17 - *
   35.18 - * You should have received a copy of the GNU General Public License along
   35.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   35.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   35.21 - */
   35.22 -
   35.23 -#ifndef _RAZOR_H_
   35.24 -#define _RAZOR_H_
   35.25 -
   35.26 -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
   35.27 -
   35.28 -struct razor_set;
   35.29 -struct razor_package;
   35.30 -struct razor_property;
   35.31 -
   35.32 -enum razor_repo_file_type {
   35.33 -	RAZOR_REPO_FILE_MAIN,
   35.34 -	RAZOR_REPO_FILE_DETAILS,
   35.35 -	RAZOR_REPO_FILE_FILES
   35.36 -};
   35.37 -
   35.38 -enum razor_property_type {
   35.39 -	RAZOR_PROPERTY_REQUIRES,
   35.40 -	RAZOR_PROPERTY_PROVIDES,
   35.41 -	RAZOR_PROPERTY_CONFLICTS,
   35.42 -	RAZOR_PROPERTY_OBSOLETES
   35.43 -};
   35.44 -
   35.45 -enum razor_version_relation {
   35.46 -	RAZOR_VERSION_LESS,
   35.47 -	RAZOR_VERSION_LESS_OR_EQUAL,
   35.48 -	RAZOR_VERSION_EQUAL,
   35.49 -	RAZOR_VERSION_GREATER_OR_EQUAL,
   35.50 -	RAZOR_VERSION_GREATER
   35.51 -};
   35.52 -extern const char * const razor_version_relations[];
   35.53 -
   35.54 -struct razor_set *razor_set_create(void);
   35.55 -struct razor_set *razor_set_open(const char *filename);
   35.56 -void razor_set_destroy(struct razor_set *set);
   35.57 -int razor_set_write_to_fd(struct razor_set *set, int fd,
   35.58 -			  enum razor_repo_file_type type);
   35.59 -int razor_set_write(struct razor_set *set, const char *filename,
   35.60 -		    enum razor_repo_file_type type);
   35.61 -
   35.62 -void razor_set_open_details(struct razor_set *set, const char *filename);
   35.63 -void razor_set_open_files(struct razor_set *set, const char *filename);
   35.64 -
   35.65 -struct razor_package *
   35.66 -razor_set_get_package(struct razor_set *set, const char *package);
   35.67 -
   35.68 -void
   35.69 -razor_package_get_details(struct razor_set *set, struct razor_package *package,
   35.70 -			  const char **summary, const char **description,
   35.71 -			  const char **url, const char **license);
   35.72 -
   35.73 -struct razor_package_iterator;
   35.74 -struct razor_package_iterator *
   35.75 -razor_package_iterator_create(struct razor_set *set);
   35.76 -struct razor_package_iterator *
   35.77 -razor_package_iterator_create_for_property(struct razor_set *set,
   35.78 -					   struct razor_property *property);
   35.79 -struct razor_package_iterator *
   35.80 -razor_package_iterator_create_for_file(struct razor_set *set,
   35.81 -				       const char *filename);
   35.82 -
   35.83 -int razor_package_iterator_next(struct razor_package_iterator *pi,
   35.84 -				struct razor_package **package,
   35.85 -				const char **name,
   35.86 -				const char **version,
   35.87 -				const char **arch);
   35.88 -void razor_package_iterator_destroy(struct razor_package_iterator *pi);
   35.89 -
   35.90 -struct razor_package_query *
   35.91 -razor_package_query_create(struct razor_set *set);
   35.92 -void
   35.93 -razor_package_query_add_package(struct razor_package_query *pq,
   35.94 -				struct razor_package *p);
   35.95 -void
   35.96 -razor_package_query_add_iterator(struct razor_package_query *pq,
   35.97 -				 struct razor_package_iterator *pi);
   35.98 -struct razor_package_iterator *
   35.99 -razor_package_query_finish(struct razor_package_query *pq);
  35.100 -
  35.101 -struct razor_property_iterator;
  35.102 -struct razor_property_iterator *
  35.103 -razor_property_iterator_create(struct razor_set *set,
  35.104 -			       struct razor_package *package);
  35.105 -int razor_property_iterator_next(struct razor_property_iterator *pi,
  35.106 -				 struct razor_property **property,
  35.107 -				 const char **name,
  35.108 -				 enum razor_version_relation *relation,
  35.109 -				 const char **version,
  35.110 -				 enum razor_property_type *type);
  35.111 -void
  35.112 -razor_property_iterator_destroy(struct razor_property_iterator *pi);
  35.113 -
  35.114 -void razor_set_list_files(struct razor_set *set, const char *prefix);
  35.115 -void razor_set_list_package_files(struct razor_set *set, const char *name);
  35.116 -
  35.117 -void razor_set_list_unsatisfied(struct razor_set *set);
  35.118 -
  35.119 -typedef void (*razor_package_callback_t)(const char *name,
  35.120 -					 const char *old_version,
  35.121 -					 const char *new_version,
  35.122 -					 const char *arch,
  35.123 -					 void *data);
  35.124 -void
  35.125 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
  35.126 -	       razor_package_callback_t callback, void *data);
  35.127 -
  35.128 -/* Package transactions */
  35.129 -
  35.130 -enum razor_transaction_package_state {
  35.131 -	/* Basic states */
  35.132 -	RAZOR_PACKAGE_INSTALL,
  35.133 -	RAZOR_PACKAGE_FORCED_UPDATE,
  35.134 -	RAZOR_PACKAGE_REMOVE,
  35.135 -	RAZOR_PACKAGE_OBSOLETED,
  35.136 -
  35.137 -	/* Error states */
  35.138 -
  35.139 -	RAZOR_PACKAGE_FIRST_ERROR_STATE = 0x4,
  35.140 -	RAZOR_PACKAGE_UNAVAILABLE_FLAG = 0x4,
  35.141 -
  35.142 -	/* Package requested for install does not exist */
  35.143 -	RAZOR_PACKAGE_INSTALL_UNAVAILABLE = RAZOR_PACKAGE_INSTALL | RAZOR_PACKAGE_UNAVAILABLE_FLAG,
  35.144 -	/* Package requiring update does not have any update */
  35.145 -	RAZOR_PACKAGE_UPDATE_UNAVAILABLE = RAZOR_PACKAGE_FORCED_UPDATE | RAZOR_PACKAGE_UNAVAILABLE_FLAG,
  35.146 -	/* Package requested for removal does not exist */
  35.147 -	RAZOR_PACKAGE_REMOVE_NOT_INSTALLED = RAZOR_PACKAGE_REMOVE | RAZOR_PACKAGE_UNAVAILABLE_FLAG,
  35.148 -	/* (not used) */
  35.149 -	RAZOR_PACKAGE_OBSOLETE_UNAVAILABLE = RAZOR_PACKAGE_OBSOLETED | RAZOR_PACKAGE_UNAVAILABLE_FLAG,
  35.150 -
  35.151 -	/* No newer version of package is available */
  35.152 -	RAZOR_PACKAGE_UP_TO_DATE,
  35.153 -	/* Package marked for both install and remove */
  35.154 -	RAZOR_PACKAGE_CONTRADICTION,
  35.155 -	/* Package would add a conflict with an already-installed package */
  35.156 -	RAZOR_PACKAGE_NEW_CONFLICT,
  35.157 -	/* Already-installed package has a conflict against this package */
  35.158 -	RAZOR_PACKAGE_OLD_CONFLICT,
  35.159 -	/* Requirement of to-be-installed package can't be satisfied */
  35.160 -	RAZOR_PACKAGE_UNSATISFIABLE,
  35.161 -};
  35.162 -
  35.163 -struct razor_transaction *
  35.164 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
  35.165 -void razor_transaction_install_package(struct razor_transaction *transaction,
  35.166 -				       struct razor_package *package);
  35.167 -void razor_transaction_remove_package(struct razor_transaction *transaction,
  35.168 -				      struct razor_package *package);
  35.169 -void razor_transaction_update_all(struct razor_transaction *transaction);
  35.170 -int razor_transaction_resolve(struct razor_transaction *trans);
  35.171 -struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
  35.172 -void razor_transaction_destroy(struct razor_transaction *trans);
  35.173 -
  35.174 -/* Temporary helper for test suite. */
  35.175 -int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
  35.176 -					   const char *name,
  35.177 -					   enum razor_version_relation rel,
  35.178 -					   const char *version);
  35.179 -
  35.180 -/* Importer interface; for building a razor set from external sources,
  35.181 - * like yum, rpmdb or razor package files. */
  35.182 -
  35.183 -struct razor_importer;
  35.184 -struct razor_rpm;
  35.185 -
  35.186 -struct razor_importer *razor_importer_new(void);
  35.187 -void razor_importer_destroy(struct razor_importer *importer);
  35.188 -void razor_importer_begin_package(struct razor_importer *importer,
  35.189 -				  const char *name,
  35.190 -				  const char *version,
  35.191 -				  const char *arch);
  35.192 -void razor_importer_add_details(struct razor_importer *importer,
  35.193 -				const char *summary,
  35.194 -				const char *description,
  35.195 -				const char *url,
  35.196 -				const char *license);
  35.197 -void razor_importer_add_property(struct razor_importer *importer,
  35.198 -				 const char *name,
  35.199 -				 enum razor_version_relation relation,
  35.200 -				 const char *version,
  35.201 -				 enum razor_property_type type);
  35.202 -void razor_importer_add_file(struct razor_importer *importer,
  35.203 -			     const char *name);
  35.204 -void razor_importer_finish_package(struct razor_importer *importer);
  35.205 -
  35.206 -int razor_importer_add_rpm(struct razor_importer *importer,
  35.207 -			   struct razor_rpm *rpm);
  35.208 -
  35.209 -struct razor_set *razor_importer_finish(struct razor_importer *importer);
  35.210 -
  35.211 -void razor_build_evr(char *evr_buf, int size, const char *epoch,
  35.212 -		     const char *version, const char *release);
  35.213 -
  35.214 -struct razor_set *razor_set_create_from_yum(void);
  35.215 -struct razor_set *razor_set_create_from_rpmdb(void);
  35.216 -
  35.217 -/* RPM functions */
  35.218 -
  35.219 -struct razor_rpm *razor_rpm_open(const char *filename);
  35.220 -int razor_rpm_install(struct razor_rpm *rpm, const char *root);
  35.221 -int razor_rpm_close(struct razor_rpm *rpm);
  35.222 -
  35.223 -#endif /* _RAZOR_H_ */
    36.1 --- a/rpm-razor.c	Sun Jun 15 18:16:20 2008 -0400
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,789 +0,0 @@
    36.4 -/*
    36.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    36.6 - * Copyright (C) 2008  Red Hat, Inc
    36.7 - *
    36.8 - * This program is free software; you can redistribute it and/or modify
    36.9 - * it under the terms of the GNU General Public License as published by
   36.10 - * the Free Software Foundation; either version 2 of the License, or
   36.11 - * (at your option) any later version.
   36.12 - *
   36.13 - * This program is distributed in the hope that it will be useful,
   36.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   36.16 - * GNU General Public License for more details.
   36.17 - *
   36.18 - * You should have received a copy of the GNU General Public License along
   36.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   36.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   36.21 - */
   36.22 -
   36.23 -#include <stdlib.h>
   36.24 -#include <string.h>
   36.25 -#include <stdio.h>
   36.26 -#include "razor.h"
   36.27 -
   36.28 -enum option_type {
   36.29 -	OPTION_LAST,
   36.30 -	OPTION_GROUP,
   36.31 -	OPTION_BOOL,
   36.32 -	OPTION_STRING
   36.33 -};
   36.34 -
   36.35 -struct option {
   36.36 -	enum option_type type;
   36.37 -	const char *name;
   36.38 -	char short_name;
   36.39 -	const char *arg_name;
   36.40 -	const char *description;
   36.41 -	void *data;
   36.42 -};
   36.43 -
   36.44 -/* A note about all these options: rpm allows options to mean
   36.45 - * different things depending on what other options are present on the
   36.46 - * command line.  For example, if -q or --query is present, -i no
   36.47 - * longer means install, but info.  The way we handle this is by
   36.48 - * setting all the options that may match (ie if -i is given we set
   36.49 - * install and info), and then look at the relevent one depending on
   36.50 - * what else in on the command line. */
   36.51 -
   36.52 -static int option_all, option_whatrequires, option_whatprovides;
   36.53 -static int option_package;
   36.54 -
   36.55 -static const struct option query_options[] = {
   36.56 -	{ OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
   36.57 -	{ OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
   36.58 -	{ OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
   36.59 -	{ OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
   36.60 -	{ OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
   36.61 -	{ OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
   36.62 -	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   36.63 -	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   36.64 -	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   36.65 -	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   36.66 -	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   36.67 -	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   36.68 -	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   36.69 -	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   36.70 -	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
   36.71 -	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   36.72 -	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   36.73 -	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   36.74 -	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   36.75 -	{ }
   36.76 -};
   36.77 -
   36.78 -static const struct option verify_options[] = {
   36.79 -	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
   36.80 -	{ OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
   36.81 -	{ OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", NULL },
   36.82 -	{ OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
   36.83 -	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   36.84 -	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   36.85 -	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   36.86 -	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   36.87 -	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   36.88 -	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   36.89 -	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   36.90 -	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   36.91 -	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
   36.92 -	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   36.93 -	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   36.94 -	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   36.95 -	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   36.96 -	{ }
   36.97 -};
   36.98 -
   36.99 -static const struct option ftw_options[] = {
  36.100 -	{ OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
  36.101 -	{ OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
  36.102 -	{ OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
  36.103 -	{ OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
  36.104 -	{ OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
  36.105 -	{ OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
  36.106 -	{ OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
  36.107 -	{ OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
  36.108 -	{ }
  36.109 -};
  36.110 -
  36.111 -static const struct option signature_options[] = {
  36.112 -	{ OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
  36.113 -	{ OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
  36.114 -	{ OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
  36.115 -	{ OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
  36.116 -	{ OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
  36.117 -	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  36.118 -	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
  36.119 -	{ }
  36.120 -};
  36.121 -
  36.122 -static const struct option database_options[] = {
  36.123 -	{ OPTION_BOOL, "initdb", 0, NULL, "initialize database", NULL },
  36.124 -	{ OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
  36.125 -	{ }
  36.126 -};
  36.127 -
  36.128 -static int option_erase, option_install, option_upgrade;
  36.129 -
  36.130 -static const struct option install_options[] = {
  36.131 -	{ OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
  36.132 -	{ OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
  36.133 -	{ OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
  36.134 -	{ OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
  36.135 -	{ OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
  36.136 -	{ OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
  36.137 -	{ OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
  36.138 -	{ OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
  36.139 -	{ OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
  36.140 -	{ OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
  36.141 -	{ OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
  36.142 -	{ OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
  36.143 -	{ OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
  36.144 -	{ OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
  36.145 -	{ OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
  36.146 -	{ OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", NULL, },
  36.147 -	{ OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", NULL, },
  36.148 -	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
  36.149 -	{ OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
  36.150 -	{ OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
  36.151 -	{ OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
  36.152 -	{ OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
  36.153 -	{ OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
  36.154 -	{ OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
  36.155 -	{ OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
  36.156 -	{ OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
  36.157 -	{ OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
  36.158 -	{ OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
  36.159 -	{ OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
  36.160 -	{ OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
  36.161 -	{ OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", NULL },
  36.162 -	{ OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
  36.163 -	{ }
  36.164 -};
  36.165 -
  36.166 -static int option_version;
  36.167 -
  36.168 -static const struct option common_options[] = {
  36.169 -	{ OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
  36.170 -	{ OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
  36.171 -	{ OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  36.172 -	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  36.173 -	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
  36.174 -	{ OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  36.175 -	{ OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", NULL },
  36.176 -	{ OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
  36.177 -	{ OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
  36.178 -	{ OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
  36.179 -	{ OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
  36.180 -	{ OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
  36.181 -	{ }
  36.182 -};
  36.183 -
  36.184 -static int option_conflicts, option_obsoletes, option_requires;
  36.185 -static int option_provides, option_info, option_changelog;
  36.186 -
  36.187 -static const struct option alias_options[] = {
  36.188 -	{ OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
  36.189 -	{ OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
  36.190 -	{ OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
  36.191 -	{ OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
  36.192 -	{ OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
  36.193 -	{ OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
  36.194 -	{ OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
  36.195 -	{ OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
  36.196 -	{ OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
  36.197 -	{ OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
  36.198 -	{ OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
  36.199 -	{ OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
  36.200 -	{ OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
  36.201 -	{ OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
  36.202 -	{ OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
  36.203 -	{ OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
  36.204 -	{ OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
  36.205 -	{ OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
  36.206 -	{ OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
  36.207 -	{ OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
  36.208 -	{ OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
  36.209 -	{ OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
  36.210 -	{ OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
  36.211 -	{ OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
  36.212 -	{ OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
  36.213 -	{ OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
  36.214 -	{ }
  36.215 -};
  36.216 -
  36.217 -static int option_help, option_usage;
  36.218 -
  36.219 -static const struct option help_options[] = {
  36.220 -	{ OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
  36.221 -	{ OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
  36.222 -	{ }
  36.223 -};
  36.224 -
  36.225 -static int option_query, option_verify;
  36.226 -
  36.227 -static const struct option rpm_options[] = {
  36.228 -	{ OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
  36.229 -	{ OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
  36.230 -	{ OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
  36.231 -	{ OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
  36.232 -	{ OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
  36.233 -	{ OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
  36.234 -	{ OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
  36.235 -	{ OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
  36.236 -	{ OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
  36.237 -	{ OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
  36.238 -	{ OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
  36.239 -	{ }
  36.240 -};
  36.241 -
  36.242 -static const char system_repo_filename[] = "system.repo";
  36.243 -static const char *repo_filename = system_repo_filename;
  36.244 -
  36.245 -static struct razor_property *
  36.246 -add_property_packages(struct razor_set *set, 
  36.247 -		      struct razor_package_query *query,
  36.248 -		      const char *ref_name,
  36.249 -		      const char *ref_version,
  36.250 -		      enum razor_property_type ref_type)
  36.251 -{
  36.252 -	struct razor_property *property;
  36.253 -	struct razor_property_iterator *pi;
  36.254 -	struct razor_package_iterator *pkgi;
  36.255 -	const char *name, *version;
  36.256 -	enum razor_property_type type;
  36.257 -	enum razor_version_relation relation;
  36.258 -
  36.259 -	pi = razor_property_iterator_create(set, NULL);
  36.260 -	while (razor_property_iterator_next(pi, &property, &name,
  36.261 -					    &relation, &version, &type)) {
  36.262 -		if (strcmp(ref_name, name) != 0)
  36.263 -			continue;
  36.264 -		if (ref_version && relation == RAZOR_VERSION_EQUAL &&
  36.265 -		    strcmp(ref_version, version) != 0)
  36.266 -			continue;
  36.267 -		if (ref_type != type)
  36.268 -			continue;
  36.269 -
  36.270 -		pkgi = razor_package_iterator_create_for_property(set,
  36.271 -								  property);
  36.272 -		razor_package_query_add_iterator(query, pkgi);
  36.273 -		razor_package_iterator_destroy(pkgi);
  36.274 -	}
  36.275 -	razor_property_iterator_destroy(pi);
  36.276 -
  36.277 -	return property;
  36.278 -}
  36.279 -
  36.280 -static int
  36.281 -strcmpp(const void *p1, const void *p2)
  36.282 -{
  36.283 -	return strcmp(*(char * const *) p1, *(char * const *) p2);
  36.284 -}
  36.285 -
  36.286 -static void
  36.287 -add_command_line_packages(struct razor_set *set,
  36.288 -			  struct razor_package_query *query,
  36.289 -			  int argc, const char **argv)
  36.290 -{
  36.291 -	struct razor_package *package;
  36.292 -	struct razor_package_iterator *pi;
  36.293 -	const char *name, *version, *arch;
  36.294 -	int i, cmp;
  36.295 -
  36.296 -	qsort(argv, argc, sizeof(*argv), strcmpp);
  36.297 -	i = 0;
  36.298 -
  36.299 -	pi = razor_package_iterator_create(set);
  36.300 -
  36.301 -	while (razor_package_iterator_next(pi, &package,
  36.302 -					   &name, &version, &arch)) {
  36.303 -		while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
  36.304 -			printf("package %s is not installed\n", argv[i]);
  36.305 -			i++;
  36.306 -		}
  36.307 -
  36.308 -		if (cmp == 0) {
  36.309 -			razor_package_query_add_package(query, package);
  36.310 -			i++;
  36.311 -		}
  36.312 -	}
  36.313 -
  36.314 -	razor_package_iterator_destroy(pi);
  36.315 -}
  36.316 -
  36.317 -static struct razor_package_iterator *
  36.318 -get_query_packages(struct razor_set *set, int argc, const char *argv[])
  36.319 -{
  36.320 -	struct razor_package_query *query;
  36.321 -	struct razor_package_iterator *pi;
  36.322 -	int i;
  36.323 -
  36.324 -	if (option_all + option_whatprovides + option_whatrequires > 1) {
  36.325 -		printf("only one type of query/verify "
  36.326 -		       "may be performed at a time\n");
  36.327 -		exit(1);
  36.328 -	}
  36.329 -
  36.330 -	query = razor_package_query_create(set);
  36.331 -
  36.332 -	if (option_all) {
  36.333 -		pi = razor_package_iterator_create(set);
  36.334 -		razor_package_query_add_iterator(query, pi);
  36.335 -		razor_package_iterator_destroy(pi);
  36.336 -	} else if (option_whatrequires) {
  36.337 -		for (i = 0; i < argc; i++)
  36.338 -			add_property_packages(set, query,
  36.339 -					      argv[i], NULL,
  36.340 -					      RAZOR_PROPERTY_REQUIRES);
  36.341 -	} else if (option_whatprovides) {
  36.342 -		for (i = 0; i < argc; i++)
  36.343 -			add_property_packages(set, query,
  36.344 -					      argv[i], NULL,
  36.345 -					      RAZOR_PROPERTY_PROVIDES);
  36.346 -	} else if (argc > 0) {
  36.347 -		add_command_line_packages(set, query, argc, argv);
  36.348 -	} else {
  36.349 -		printf("no arguments given for query/verify\n");
  36.350 -		exit(1);
  36.351 -	}
  36.352 -
  36.353 -	return razor_package_query_finish(query);
  36.354 -}
  36.355 -
  36.356 -static void
  36.357 -print_package_properties(struct razor_set *set,
  36.358 -			 struct razor_package *package,
  36.359 -			 enum razor_property_type ref_type)
  36.360 -{
  36.361 -	struct razor_property *property;
  36.362 -	struct razor_property_iterator *pi;
  36.363 -	const char *name, *version;
  36.364 -	enum razor_property_type type;
  36.365 -	enum razor_version_relation relation;
  36.366 -
  36.367 -	pi = razor_property_iterator_create(set, package);
  36.368 -	while (razor_property_iterator_next(pi, &property,
  36.369 -					    &name, &relation, &version,
  36.370 -					    &type)) {
  36.371 -		if (type != ref_type)
  36.372 -			continue;
  36.373 -		if (version[0] == '\0')
  36.374 -			printf("%s\n", name);
  36.375 -		else
  36.376 -			printf("%s %s %s\n", name,
  36.377 -			       razor_version_relations[relation], version);
  36.378 -	}
  36.379 -	razor_property_iterator_destroy(pi);
  36.380 -}
  36.381 -
  36.382 -static void
  36.383 -print_package_info(struct razor_set *set, struct razor_package *package)
  36.384 -{
  36.385 -	printf("FIXME: Package info not tracked.\n");
  36.386 -}
  36.387 -
  36.388 -static void
  36.389 -print_package_changelog(struct razor_set *set, struct razor_package *package)
  36.390 -{
  36.391 -	printf("FIXME: Package changelog not tracked.\n");
  36.392 -}
  36.393 -
  36.394 -static struct razor_set *
  36.395 -create_set_from_command_line(int argc, const char *argv[])
  36.396 -{
  36.397 -	struct razor_importer *importer;
  36.398 -	struct razor_rpm *rpm;
  36.399 -	int i;
  36.400 -
  36.401 -	importer = razor_importer_new();
  36.402 -
  36.403 -	for (i = 0; i < argc; i++) {
  36.404 -		rpm = razor_rpm_open(argv[i]);
  36.405 -		if (rpm == NULL)
  36.406 -			continue;
  36.407 -		if (razor_importer_add_rpm(importer, rpm))
  36.408 -			printf("couldn't import %s\n", argv[i]);
  36.409 -
  36.410 -		razor_rpm_close(rpm);
  36.411 -	}
  36.412 -
  36.413 -	return razor_importer_finish(importer);
  36.414 -}
  36.415 -
  36.416 -static void
  36.417 -command_query(int argc, const char *argv[])
  36.418 -{
  36.419 -	struct razor_set *set;
  36.420 -	struct razor_package_iterator *pi;
  36.421 -	struct razor_package *package;
  36.422 -	const char *name, *version, *arch;
  36.423 -
  36.424 -	if (option_package) {
  36.425 -		set = create_set_from_command_line(argc, argv);
  36.426 -		argc = 0;
  36.427 -		option_all = 1;
  36.428 -	} else {
  36.429 -		set = razor_set_open(repo_filename);
  36.430 -	}
  36.431 -
  36.432 -	pi = get_query_packages(set, argc, argv);
  36.433 -
  36.434 -	while (razor_package_iterator_next(pi, &package,
  36.435 -					   &name, &version, &arch)) {
  36.436 -		if (option_conflicts)
  36.437 -			print_package_properties(set, package,
  36.438 -						 RAZOR_PROPERTY_CONFLICTS);
  36.439 -		if (option_obsoletes)
  36.440 -			print_package_properties(set, package,
  36.441 -						 RAZOR_PROPERTY_OBSOLETES);
  36.442 -		if (option_requires)
  36.443 -			print_package_properties(set, package,
  36.444 -						 RAZOR_PROPERTY_REQUIRES);
  36.445 -		if (option_provides)
  36.446 -			print_package_properties(set, package,
  36.447 -						 RAZOR_PROPERTY_PROVIDES);
  36.448 -		if (option_info)
  36.449 -			print_package_info(set, package);
  36.450 -		if (option_changelog)
  36.451 -			print_package_changelog(set, package);
  36.452 -
  36.453 -		if (option_conflicts + option_obsoletes +
  36.454 -		    option_requires + option_provides +
  36.455 -		    option_info + option_changelog == 0)
  36.456 -			printf("%s-%s.%s\n", name, version, arch);
  36.457 -	}
  36.458 -
  36.459 -	razor_package_iterator_destroy(pi);
  36.460 -
  36.461 -	razor_set_destroy(set);
  36.462 -
  36.463 -	return;
  36.464 -}
  36.465 -
  36.466 -static void
  36.467 -command_verify(int argc, const char *argv[])
  36.468 -{
  36.469 -	struct razor_set *set;
  36.470 -	struct razor_package_iterator *pi;
  36.471 -	struct razor_package *package;
  36.472 -	const char *name, *version, *arch;
  36.473 -
  36.474 -	if (option_package) {
  36.475 -		set = create_set_from_command_line(argc, argv);
  36.476 -		argc = 0;
  36.477 -		option_all = 1;
  36.478 -	} else {
  36.479 -		set = razor_set_open(repo_filename);
  36.480 -	}
  36.481 -
  36.482 -	pi = get_query_packages(set, argc, argv);
  36.483 -
  36.484 -	while (razor_package_iterator_next(pi, &package,
  36.485 -					   &name, &version, &arch)) {
  36.486 -		printf("verify %s-%s.%s - not implemented\n",
  36.487 -		       name, version, arch);
  36.488 -	}
  36.489 -
  36.490 -	razor_package_iterator_destroy(pi);
  36.491 -}
  36.492 -
  36.493 -static void
  36.494 -command_erase(int argc, const char *argv[])
  36.495 -{
  36.496 -	struct razor_set *set, *next;
  36.497 -	struct razor_transaction *trans;
  36.498 -	struct razor_package_query *query;
  36.499 -	struct razor_package_iterator *pi;
  36.500 -	struct razor_package *package;
  36.501 -	const char *name, *version, *arch;
  36.502 -
  36.503 -	if (argc == 0) {
  36.504 -		printf("no packages given for erase\n");
  36.505 -		exit(1);
  36.506 -	}
  36.507 -
  36.508 -	set = razor_set_open(repo_filename);
  36.509 -
  36.510 -	trans = razor_transaction_create(set, NULL);
  36.511 -
  36.512 -	query = razor_package_query_create(set);
  36.513 -	add_command_line_packages(set, query, argc, argv);
  36.514 -
  36.515 -	pi = razor_package_query_finish(query);
  36.516 -	while (razor_package_iterator_next(pi, &package,
  36.517 -					   &name, &version, &arch))
  36.518 -		razor_transaction_remove_package(trans, package);
  36.519 -	razor_package_iterator_destroy(pi);
  36.520 -
  36.521 -	next = razor_transaction_finish(trans);
  36.522 -	razor_set_destroy(set);
  36.523 -
  36.524 -	razor_set_list_unsatisfied(next);
  36.525 -	razor_set_destroy(next);
  36.526 -}
  36.527 -
  36.528 -static void
  36.529 -command_install(int argc, const char *argv[])
  36.530 -{
  36.531 -	struct razor_set *set, *upstream, *next;
  36.532 -	struct razor_transaction *trans;
  36.533 -	struct razor_package_iterator *pi;
  36.534 -	struct razor_package *package;
  36.535 -	const char *name, *version, *arch;
  36.536 -
  36.537 -	if (argc == 0) {
  36.538 -		printf("no packages given for install\n");
  36.539 -		exit(1);
  36.540 -	}
  36.541 -
  36.542 -	set = razor_set_open(repo_filename);
  36.543 -	upstream = create_set_from_command_line(argc, argv);
  36.544 -
  36.545 -	trans = razor_transaction_create(set, upstream);
  36.546 -
  36.547 -	pi = razor_package_iterator_create(upstream);
  36.548 -	while (razor_package_iterator_next(pi, &package,
  36.549 -					   &name, &version, &arch))
  36.550 -		razor_transaction_install_package(trans, package);
  36.551 -	razor_package_iterator_destroy(pi);
  36.552 -
  36.553 -	next = razor_transaction_finish(trans);
  36.554 -	razor_set_destroy(set);
  36.555 -	razor_set_destroy(upstream);
  36.556 -
  36.557 -	razor_set_list_unsatisfied(next);
  36.558 -
  36.559 -	razor_set_destroy(next);
  36.560 -}
  36.561 -
  36.562 -static void
  36.563 -command_update(int argc, const char *argv[])
  36.564 -{
  36.565 -	if (argc == 0) {
  36.566 -		printf("no packages given for update\n");
  36.567 -		exit(1);
  36.568 -	}
  36.569 -
  36.570 -	printf("command update - not implemented\n");
  36.571 -}
  36.572 -
  36.573 -static int
  36.574 -for_each_option(const struct option *options,
  36.575 -		const char *name, char short_name,
  36.576 -		void (*fn)(const struct option *o,
  36.577 -			   const char *name, char short_name,
  36.578 -			   void *data), void *data)
  36.579 -{
  36.580 -	int i, count = 0;
  36.581 -
  36.582 -	for (i = 0; options[i].type != OPTION_LAST; i++) {
  36.583 -		switch (options[i].type) {
  36.584 -		case OPTION_GROUP:
  36.585 -			count += for_each_option(options[i].data,
  36.586 -						 name, short_name, fn, data);
  36.587 -			break;
  36.588 -
  36.589 -		case OPTION_BOOL:
  36.590 -		case OPTION_STRING:
  36.591 -			if (name && strcmp(options[i].name, name) == 0) {
  36.592 -				fn(&options[i], name, 0, data);
  36.593 -				count++;
  36.594 -				break;
  36.595 -			}
  36.596 -
  36.597 -			if (short_name &&
  36.598 -			    short_name == options[i].short_name) {
  36.599 -				fn(&options[i], NULL, short_name, data);
  36.600 -				count++;
  36.601 -				break;
  36.602 -			}
  36.603 -			break;
  36.604 -
  36.605 -		case OPTION_LAST:
  36.606 -			break;
  36.607 -		}
  36.608 -	}
  36.609 -
  36.610 -	return count;
  36.611 -}
  36.612 -
  36.613 -static void
  36.614 -handle_option(const struct option *o,
  36.615 -	      const char *name, char short_name, void *data)
  36.616 -{
  36.617 -	if (o->data == NULL) {
  36.618 -		if (name)
  36.619 -			printf("option --%s not supported\n", name);
  36.620 -		else
  36.621 -			printf("option -%c not supported\n", short_name);
  36.622 -		return;
  36.623 -	}
  36.624 -
  36.625 -	switch (o->type) {
  36.626 -	case OPTION_BOOL:
  36.627 -		*(int *) o->data = 1;
  36.628 -		break;
  36.629 -
  36.630 -	case OPTION_STRING:
  36.631 -		*(const char **) o->data = name + strlen(o->name) + 1;
  36.632 -		break;
  36.633 -
  36.634 -	case OPTION_LAST:
  36.635 -	case OPTION_GROUP:
  36.636 -		/* Shouldn't happen. */
  36.637 -		break;
  36.638 -	}
  36.639 -}
  36.640 -
  36.641 -static int
  36.642 -parse_options(const struct option *options, int argc, const char **argv)
  36.643 -{
  36.644 -	int i, j, k;
  36.645 -
  36.646 -	for (i = 1, j = 0; i < argc; i++) {
  36.647 -		if (argv[i][0] != '-') {
  36.648 -			argv[j++] = argv[i];
  36.649 -			continue;
  36.650 -		}
  36.651 -
  36.652 -		if (argv[i][1] == '-') {
  36.653 -			if (for_each_option(options, &argv[i][2], 0,
  36.654 -					    handle_option, NULL) == 0) {
  36.655 -				printf("unknown option: %s\n", argv[i]);
  36.656 -				exit(1);
  36.657 -			}
  36.658 -			continue;
  36.659 -		}
  36.660 -
  36.661 -		for (k = 1; argv[i][k]; k++) {
  36.662 -			if (for_each_option(options, NULL, argv[i][k],
  36.663 -					    handle_option, NULL) == 0) {
  36.664 -				printf("unknown option: -%c\n", argv[i][k]);
  36.665 -				exit(1);
  36.666 -			}
  36.667 -		}
  36.668 -	}
  36.669 -
  36.670 -	return j;
  36.671 -}
  36.672 -
  36.673 -static void
  36.674 -print_options_help(const struct option *options)
  36.675 -{
  36.676 -	int i;
  36.677 -
  36.678 -	for (i = 0; options[i].type != OPTION_LAST; i++) {
  36.679 -		switch (options[i].type) {
  36.680 -		case OPTION_GROUP:
  36.681 -			printf("%s\n", options[i].description);
  36.682 -			print_options_help(options[i].data);
  36.683 -			printf("\n");
  36.684 -			break;
  36.685 -
  36.686 -		case OPTION_BOOL:
  36.687 -		case OPTION_STRING:
  36.688 -			printf("  ");
  36.689 -			if (options[i].short_name)
  36.690 -				printf("-%c", options[i].short_name);
  36.691 -			if (options[i].short_name && options[i].name)
  36.692 -				printf(", ");
  36.693 -			if (options[i].name)
  36.694 -				printf("--%s", options[i].name);
  36.695 -			if (options[i].arg_name)
  36.696 -				printf("=%s", options[i].arg_name);
  36.697 -			if (options[i].description)
  36.698 -				printf("\t\t%s", options[i].description);
  36.699 -			printf("\n");
  36.700 -			break;
  36.701 -
  36.702 -		case OPTION_LAST:
  36.703 -			break;
  36.704 -		}
  36.705 -	}
  36.706 -}
  36.707 -
  36.708 -static void
  36.709 -print_options_usage(const struct option *options)
  36.710 -{
  36.711 -	int i;
  36.712 -
  36.713 -	for (i = 0; options[i].type != OPTION_LAST; i++) {
  36.714 -		switch (options[i].type) {
  36.715 -		case OPTION_GROUP:
  36.716 -			print_options_usage(options[i].data);
  36.717 -			break;
  36.718 -
  36.719 -		case OPTION_BOOL:
  36.720 -			printf("[");
  36.721 -			if (options[i].short_name)
  36.722 -				printf("-%c", options[i].short_name);
  36.723 -			if (options[i].short_name && options[i].name)
  36.724 -				printf("|");
  36.725 -			if (options[i].name)
  36.726 -				printf("--%s", options[i].name);
  36.727 -			printf("] ");
  36.728 -			break;
  36.729 -
  36.730 -		case OPTION_STRING:
  36.731 -			printf("[");
  36.732 -			if (options[i].short_name)
  36.733 -				printf("-%c", options[i].short_name);
  36.734 -			if (options[i].short_name && options[i].name)
  36.735 -				printf("|");
  36.736 -			if (options[i].name)
  36.737 -				printf("--%s", options[i].name);
  36.738 -			if (options[i].arg_name)
  36.739 -				printf("=%s", options[i].arg_name);
  36.740 -			printf("] ");
  36.741 -			break;
  36.742 -
  36.743 -
  36.744 -			break;
  36.745 -
  36.746 -		case OPTION_LAST:
  36.747 -			break;
  36.748 -		}
  36.749 -	}
  36.750 -}
  36.751 -
  36.752 -int
  36.753 -main(int argc, const char *argv[])
  36.754 -{
  36.755 -	argc = parse_options(rpm_options, argc, argv);
  36.756 -
  36.757 -	if (option_version) {
  36.758 -		printf("razor rpm version hoopla.\n");
  36.759 -		exit(0);
  36.760 -	}
  36.761 -
  36.762 -	if (option_help) {
  36.763 -		printf("Usage: rpm [OPTION...]\n");
  36.764 -		print_options_help(rpm_options);
  36.765 -		exit(0);
  36.766 -	}
  36.767 -
  36.768 -	if (option_usage) {
  36.769 -		printf("Usage: rpm [OPTION...]\n");
  36.770 -		print_options_usage(rpm_options);
  36.771 -		printf("\n");
  36.772 -		exit(0);
  36.773 -	}
  36.774 -
  36.775 -	if (option_verify) {
  36.776 -		command_verify(argc, argv);
  36.777 -	} else if (option_query) {
  36.778 -		command_query(argc, argv);
  36.779 -	} else if (option_install) {
  36.780 -		command_install(argc, argv);
  36.781 -	} else if (option_upgrade) {
  36.782 -		command_update(argc, argv);
  36.783 -	} else if (option_erase) {
  36.784 -		command_erase(argc, argv);
  36.785 -	} else {
  36.786 -		print_options_usage(rpm_options);
  36.787 -		printf("\n");
  36.788 -		exit(0);
  36.789 -	}
  36.790 -
  36.791 -	return 0;
  36.792 -}
    37.1 --- a/rpm.c	Sun Jun 15 18:16:20 2008 -0400
    37.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3 @@ -1,757 +0,0 @@
    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 <errno.h>
   37.27 -#include <sys/stat.h>
   37.28 -#include <sys/mman.h>
   37.29 -#include <sys/types.h>
   37.30 -#include <sys/wait.h>
   37.31 -#include <fcntl.h>
   37.32 -#include <unistd.h>
   37.33 -#include <arpa/inet.h>
   37.34 -#include <rpm/rpmlib.h>
   37.35 -#include <rpm/rpmdb.h>
   37.36 -#include <zlib.h>
   37.37 -
   37.38 -#include "razor.h"
   37.39 -#include "razor-internal.h"
   37.40 -
   37.41 -#define	RPM_LEAD_SIZE 96
   37.42 -
   37.43 -struct rpm_header {
   37.44 -	unsigned char magic[4];
   37.45 -	unsigned char reserved[4];
   37.46 -	int nindex;
   37.47 -	int hsize;
   37.48 -};
   37.49 -
   37.50 -struct rpm_header_index {
   37.51 -	int tag;
   37.52 -	int type;
   37.53 -	int offset;
   37.54 -	int count;
   37.55 -};
   37.56 -
   37.57 -struct razor_rpm {
   37.58 -	struct rpm_header *signature;
   37.59 -	struct rpm_header *header;
   37.60 -	const char **dirs;
   37.61 -	const char *pool;
   37.62 -	void *map;
   37.63 -	size_t size;
   37.64 -	void *payload;
   37.65 -};
   37.66 -
   37.67 -static struct rpm_header_index *
   37.68 -razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
   37.69 -{
   37.70 -	struct rpm_header_index *index, *end;
   37.71 -
   37.72 -	index = (struct rpm_header_index *) (rpm->header + 1);
   37.73 -	end = index + ntohl(rpm->header->nindex);
   37.74 -	while (index < end) {
   37.75 -		if (ntohl(index->tag) == tag)
   37.76 -			return index;
   37.77 -		index++;
   37.78 -	}
   37.79 -
   37.80 -	return NULL;
   37.81 -}
   37.82 -
   37.83 -static const void *
   37.84 -razor_rpm_get_indirect(struct razor_rpm *rpm,
   37.85 -		       unsigned int tag, unsigned int *count)
   37.86 -{
   37.87 -	struct rpm_header_index *index;
   37.88 -
   37.89 -	index = razor_rpm_get_header(rpm, tag);
   37.90 -	if (index != NULL) {
   37.91 -		if (count)
   37.92 -			*count = ntohl(index->count);
   37.93 -
   37.94 -		return rpm->pool + ntohl(index->offset);
   37.95 -	}
   37.96 -
   37.97 -	return NULL;
   37.98 -}
   37.99 -
  37.100 -static enum razor_version_relation
  37.101 -rpm_to_razor_flags (uint_32 flags)
  37.102 -{
  37.103 -	switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
  37.104 -	case RPMSENSE_LESS:
  37.105 -		return RAZOR_VERSION_LESS;
  37.106 -	case RPMSENSE_LESS|RPMSENSE_EQUAL:
  37.107 -		return RAZOR_VERSION_LESS_OR_EQUAL;
  37.108 -	case RPMSENSE_EQUAL:
  37.109 -		return RAZOR_VERSION_EQUAL;
  37.110 -	case RPMSENSE_GREATER|RPMSENSE_EQUAL:
  37.111 -		return RAZOR_VERSION_GREATER_OR_EQUAL;
  37.112 -	case RPMSENSE_GREATER:
  37.113 -		return RAZOR_VERSION_GREATER;
  37.114 -	}
  37.115 -
  37.116 -	/* FIXME? */
  37.117 -	return RAZOR_VERSION_EQUAL;
  37.118 -}
  37.119 -
  37.120 -static void
  37.121 -import_properties(struct razor_importer *importer, unsigned long type,
  37.122 -		  struct razor_rpm *rpm,
  37.123 -		  int name_tag, int version_tag, int flags_tag)
  37.124 -{
  37.125 -	const char *name, *version;
  37.126 -	const uint_32 *flags;
  37.127 -	uint_32 f;
  37.128 -	unsigned int i, count;
  37.129 -
  37.130 -	name = razor_rpm_get_indirect(rpm, name_tag, &count);
  37.131 -	if (name == NULL)
  37.132 -		return;
  37.133 -
  37.134 -	flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
  37.135 -
  37.136 -	version = razor_rpm_get_indirect(rpm, version_tag, &count);
  37.137 -	for (i = 0; i < count; i++) {
  37.138 -		f = rpm_to_razor_flags(ntohl(flags[i]));
  37.139 -		razor_importer_add_property(importer, name, f, version, type);
  37.140 -		name += strlen(name) + 1;
  37.141 -		version += strlen(version) + 1;
  37.142 -	}
  37.143 -}
  37.144 -
  37.145 -static void
  37.146 -import_files(struct razor_importer *importer, struct razor_rpm *rpm)
  37.147 -{
  37.148 -	const char *name;
  37.149 -	const uint32_t *index;
  37.150 -	unsigned int i, count;
  37.151 -	char buffer[256];
  37.152 -
  37.153 -	/* assert: count is the same for all arrays */
  37.154 -
  37.155 -	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
  37.156 -	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
  37.157 -	for (i = 0; i < count; i++) {
  37.158 -		snprintf(buffer, sizeof buffer,
  37.159 -			 "%s%s", rpm->dirs[ntohl(*index)], name);
  37.160 -		razor_importer_add_file(importer, buffer);
  37.161 -		name += strlen(name) + 1;
  37.162 -		index++;
  37.163 -	}
  37.164 -}
  37.165 -
  37.166 -struct razor_rpm *
  37.167 -razor_rpm_open(const char *filename)
  37.168 -{
  37.169 -	struct razor_rpm *rpm;
  37.170 -	struct rpm_header_index *base, *index;
  37.171 -	struct stat buf;
  37.172 -	unsigned int count, i, nindex, hsize;
  37.173 -	const char *name;
  37.174 -	int fd;
  37.175 -
  37.176 -	rpm = malloc(sizeof *rpm);
  37.177 -	memset(rpm, 0, sizeof *rpm);
  37.178 -
  37.179 -	fd = open(filename, O_RDONLY);
  37.180 -	if (fd < 0) {
  37.181 -		fprintf(stderr, "couldn't open %s\n", filename);
  37.182 -		return NULL;
  37.183 -	}
  37.184 -
  37.185 -	if (fstat(fd, &buf) < 0) {
  37.186 -		fprintf(stderr, "failed to stat %s (%m)\n", filename);
  37.187 -		return NULL;
  37.188 -	}
  37.189 -
  37.190 -	rpm->size = buf.st_size;
  37.191 -	rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
  37.192 -	if (rpm->map == MAP_FAILED) {
  37.193 -		fprintf(stderr, "couldn't mmap %s\n", filename);
  37.194 -		return NULL;
  37.195 -	}
  37.196 -	close(fd);
  37.197 -
  37.198 -	rpm->signature = rpm->map + RPM_LEAD_SIZE;
  37.199 -	nindex = ntohl(rpm->signature->nindex);
  37.200 -	hsize = ntohl(rpm->signature->hsize);
  37.201 -	rpm->header = (void *) (rpm->signature + 1) +
  37.202 -		ALIGN(nindex * sizeof *index + hsize, 8);
  37.203 -	nindex = ntohl(rpm->header->nindex);
  37.204 -	hsize = ntohl(rpm->header->hsize);
  37.205 -	rpm->payload = (void *) (rpm->header + 1) +
  37.206 -		nindex * sizeof *index + hsize;
  37.207 -
  37.208 -	base = (struct rpm_header_index *) (rpm->header + 1);
  37.209 -	rpm->pool = (void *) base + nindex * sizeof *index;
  37.210 -
  37.211 -	/* Look up dir names now so we can index them directly. */
  37.212 -	name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
  37.213 -	if (name) {
  37.214 -		rpm->dirs = calloc(count, sizeof *rpm->dirs);
  37.215 -		for (i = 0; i < count; i++) {
  37.216 -			rpm->dirs[i] = name;
  37.217 -			name += strlen(name) + 1;
  37.218 -		}
  37.219 -	} else {
  37.220 -		name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
  37.221 -					      &count);
  37.222 -		if (name) {
  37.223 -			fprintf(stderr, "old filenames not supported\n");
  37.224 -			return NULL;
  37.225 -		}
  37.226 -	}
  37.227 -
  37.228 -	return rpm;
  37.229 -}
  37.230 -
  37.231 -struct cpio_file_header {
  37.232 -	char magic[6];
  37.233 -	char inode[8];
  37.234 -	char mode[8];
  37.235 -	char uid[8];
  37.236 -	char gid[8];
  37.237 -	char nlink[8];
  37.238 -	char mtime[8];
  37.239 -	char filesize[8];
  37.240 -	char devmajor[8];
  37.241 -	char devminor[8];
  37.242 -	char rdevmajor[8];
  37.243 -	char rdevminor[8];
  37.244 -	char namesize[8];
  37.245 -	char checksum[8];
  37.246 -	char filename[0];
  37.247 -};
  37.248 -
  37.249 -/* gzip flags */
  37.250 -#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
  37.251 -#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
  37.252 -#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
  37.253 -#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
  37.254 -#define COMMENT      0x10 /* bit 4 set: file comment present */
  37.255 -#define RESERVED     0xE0 /* bits 5..7: reserved */
  37.256 -
  37.257 -struct installer {
  37.258 -	const char *root;
  37.259 -	struct razor_rpm *rpm;
  37.260 -	z_stream stream;
  37.261 -	unsigned char buffer[32768];
  37.262 -	size_t rest, length;
  37.263 -};
  37.264 -
  37.265 -static int
  37.266 -installer_inflate(struct installer *installer)
  37.267 -{
  37.268 -	size_t length;
  37.269 -	int err;
  37.270 -
  37.271 -	if (installer->rest > sizeof installer->buffer)
  37.272 -		length = sizeof installer->buffer;
  37.273 -	else
  37.274 -		length = installer->rest;
  37.275 -
  37.276 -	installer->stream.next_out = installer->buffer;
  37.277 -	installer->stream.avail_out = length;
  37.278 -	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  37.279 -	if (err != Z_OK && err != Z_STREAM_END) {
  37.280 -		fprintf(stderr, "inflate error: %d (%m)\n", err);
  37.281 -		return -1;
  37.282 -	}
  37.283 -
  37.284 -	installer->rest -= length;
  37.285 -	installer->length = length;
  37.286 -
  37.287 -	return 0;
  37.288 -}
  37.289 -
  37.290 -static int
  37.291 -installer_align(struct installer *installer, size_t size)
  37.292 -{
  37.293 -	unsigned char buffer[4];
  37.294 -	int err;
  37.295 -
  37.296 -	installer->stream.next_out = buffer;
  37.297 -	installer->stream.avail_out =
  37.298 -		(size - installer->stream.total_out) & (size - 1);
  37.299 -
  37.300 -	if (installer->stream.avail_out == 0)
  37.301 -		return 0;
  37.302 -
  37.303 -	err = inflate(&installer->stream, Z_SYNC_FLUSH);
  37.304 -	if (err != Z_OK && err != Z_STREAM_END) {
  37.305 -		fprintf(stderr, "inflate error: %d (%m)\n", err);
  37.306 -		return -1;
  37.307 -	}
  37.308 -
  37.309 -	return 0;
  37.310 -}
  37.311 -
  37.312 -static int
  37.313 -create_path(struct installer *installer, const char *path, unsigned int mode)
  37.314 -{
  37.315 -	char buffer[PATH_MAX];
  37.316 -	struct stat buf;
  37.317 -	int fd, ret;
  37.318 -
  37.319 -	if (razor_create_dir(installer->root, path) < 0)
  37.320 -		return -1;
  37.321 -
  37.322 -	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
  37.323 -
  37.324 -	switch (mode >> 12) {
  37.325 -	case REG:
  37.326 -		/* FIXME: handle the case where a file is already there. */
  37.327 -		fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, mode & 0x1ff);
  37.328 -		if (fd < 0){
  37.329 -			fprintf(stderr, "failed to create file %s\n", buffer);
  37.330 -			return -1;
  37.331 -		}
  37.332 -		while (installer->rest > 0) {
  37.333 -			if (installer_inflate(installer)) {
  37.334 -				fprintf(stderr, "failed to inflate\n");
  37.335 -				return -1;
  37.336 -			}
  37.337 -			if (razor_write(fd, installer->buffer,
  37.338 -					installer->length)) {
  37.339 -				fprintf(stderr, "failed to write payload\n");
  37.340 -				return -1;
  37.341 -			}
  37.342 -		}
  37.343 -		if (close(fd) < 0) {
  37.344 -			fprintf(stderr, "failed to close %s: %m\n", buffer);
  37.345 -			return -1;
  37.346 -		}
  37.347 -		return 0;
  37.348 -	case XDIR:
  37.349 -		ret = mkdir(buffer, mode & 0x1ff);
  37.350 -		if (ret == 0 || errno != EEXIST)
  37.351 -			return ret;
  37.352 -		if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
  37.353 -			/* FIXME: also check that mode match. */
  37.354 -			fprintf(stderr,
  37.355 -				"%s exists but is not a directory\n", buffer);
  37.356 -			return -1;
  37.357 -		}
  37.358 -		return 0;
  37.359 -	case PIPE:
  37.360 -	case CDEV:
  37.361 -	case BDEV:
  37.362 -	case SOCK:
  37.363 -		printf("%s: unhandled file type %d\n", buffer, mode >> 12);
  37.364 -		return 0;
  37.365 -	case LINK:
  37.366 -		if (installer_inflate(installer)) {
  37.367 -			fprintf(stderr, "failed to inflate\n");
  37.368 -			return -1;
  37.369 -		}
  37.370 -		if (installer->length >= sizeof installer->buffer) {
  37.371 -			fprintf(stderr, "link name too long\n");
  37.372 -			return -1;
  37.373 -		}
  37.374 -		installer->buffer[installer->length] = '\0';
  37.375 -		if (symlink((const char *) installer->buffer, buffer)) {
  37.376 -			fprintf(stderr, "failed to create symlink, %m\n");
  37.377 -			return -1;
  37.378 -		}
  37.379 -		return 0;
  37.380 -	default:
  37.381 -		printf("%s: unknown file type %d\n", buffer, mode >> 12);
  37.382 -		return 0;
  37.383 -	}
  37.384 -}
  37.385 -
  37.386 -static int
  37.387 -run_script(struct installer *installer,
  37.388 -	   unsigned int program_tag, unsigned int script_tag)
  37.389 -{
  37.390 -	int pid, status, fd[2];
  37.391 -	const char *script = NULL, *program = NULL;
  37.392 -
  37.393 -	program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
  37.394 -	script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
  37.395 -	if (program == NULL && script == NULL) {
  37.396 -		return 0;
  37.397 -	} else if (program == NULL) {
  37.398 -		program = "/bin/sh";
  37.399 -	}
  37.400 -
  37.401 -	if (pipe(fd) < 0) {
  37.402 -		fprintf(stderr, "failed to create pipe\n");
  37.403 -		return -1;
  37.404 -	}
  37.405 -	pid = fork();
  37.406 -	if (pid < 0) {
  37.407 -		fprintf(stderr, "failed to fork, %m\n");
  37.408 -	} else if (pid == 0) {
  37.409 -		if (dup2(fd[0], STDIN_FILENO) < 0) {
  37.410 -			fprintf(stderr, "failed redirect stdin, %m\n");
  37.411 -			return -1;
  37.412 -		}
  37.413 -		if (close(fd[0]) < 0 || close(fd[1]) < 0) {
  37.414 -			fprintf(stderr, "failed to close pipe, %m\n");
  37.415 -			return -1;
  37.416 -		}
  37.417 -		if (chroot(installer->root) < 0) {
  37.418 -			fprintf(stderr, "failed to chroot to %s, %m\n",
  37.419 -				installer->root);
  37.420 -			return -1;
  37.421 -		}
  37.422 -		printf("executing program %s in chroot %s\n",
  37.423 -		       program, installer->root);
  37.424 -		if (execl(program, program, NULL)) {
  37.425 -			fprintf(stderr, "failed to exec %s, %m\n", program);
  37.426 -			exit(-1);
  37.427 -		}
  37.428 -	} else {
  37.429 -		if (script && razor_write(fd[1], script, strlen(script)) < 0) {
  37.430 -			fprintf(stderr, "failed to pipe script, %m\n");
  37.431 -			return -1;
  37.432 -		}
  37.433 -		if (close(fd[0]) || close(fd[1])) {
  37.434 -			fprintf(stderr, "failed to close pipe, %m\n");
  37.435 -			return -1;
  37.436 -		}
  37.437 -		if (wait(&status) < 0) {
  37.438 -			fprintf(stderr, "wait for child failed, %m");
  37.439 -			return -1;
  37.440 -		}
  37.441 -		if (status)
  37.442 -			printf("script exited with status %d\n", status);
  37.443 -	}
  37.444 -
  37.445 -	return 0;
  37.446 -}
  37.447 -
  37.448 -static int
  37.449 -installer_init(struct installer *installer)
  37.450 -{
  37.451 -	unsigned char *gz_header;
  37.452 -	int method, flags, err;
  37.453 -
  37.454 -	gz_header = installer->rpm->payload;
  37.455 -	if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
  37.456 -		fprintf(stderr, "payload section doesn't have gz header\n");
  37.457 -		return -1;
  37.458 -	}
  37.459 -
  37.460 -	method = gz_header[2];
  37.461 -	flags = gz_header[3];
  37.462 -
  37.463 -	if (method != Z_DEFLATED || flags != 0) {
  37.464 -		fprintf(stderr,
  37.465 -			"unknown payload compression method or flags set\n");
  37.466 -		return -1;
  37.467 -	}
  37.468 -
  37.469 -	installer->stream.zalloc = NULL;
  37.470 -	installer->stream.zfree = NULL;
  37.471 -	installer->stream.opaque = NULL;
  37.472 -
  37.473 -	installer->stream.next_in  = gz_header + 10;
  37.474 -	installer->stream.avail_in =
  37.475 -		(installer->rpm->map + installer->rpm->size) -
  37.476 -		(void *) installer->stream.next_in;
  37.477 -	installer->stream.next_out = NULL;
  37.478 -	installer->stream.avail_out = 0;
  37.479 -
  37.480 -	err = inflateInit2(&installer->stream, -MAX_WBITS);
  37.481 -	if (err != Z_OK) {
  37.482 -		fprintf(stderr, "inflateInit error: %d\n", err);
  37.483 -		return -1;
  37.484 -	}
  37.485 -
  37.486 -	return 0;
  37.487 -}
  37.488 -
  37.489 -static int
  37.490 -installer_finish(struct installer *installer)
  37.491 -{
  37.492 -	int err;
  37.493 -
  37.494 -	err = inflateEnd(&installer->stream);
  37.495 -
  37.496 -	if (err != Z_OK) {
  37.497 -		fprintf(stderr, "inflateEnd error: %d\n", err);
  37.498 -		return -1;
  37.499 -	}	    
  37.500 -
  37.501 -	return 0;
  37.502 -}
  37.503 -
  37.504 -static unsigned long
  37.505 -fixed_hex_to_ulong(const char *hex, int length)
  37.506 -{
  37.507 -	long l;
  37.508 -	int i;
  37.509 -
  37.510 -	for (i = 0, l = 0; i < length; i++) {
  37.511 -		if (hex[i] < 'a')
  37.512 -			l = l * 16 + hex[i] - '0';
  37.513 -		else
  37.514 -			l = l * 16 + hex[i] - 'a' + 10;
  37.515 -	}
  37.516 -
  37.517 -	return l;
  37.518 -}
  37.519 -
  37.520 -int
  37.521 -razor_rpm_install(struct razor_rpm *rpm, const char *root)
  37.522 -{
  37.523 -	struct installer installer;
  37.524 -	struct cpio_file_header *header;
  37.525 -	struct stat buf;
  37.526 -	unsigned int mode;
  37.527 -	char *path;
  37.528 -	size_t filesize;
  37.529 -
  37.530 -	installer.rpm = rpm;
  37.531 -	installer.root = root;
  37.532 -
  37.533 -	/* FIXME: Only do this before a transaction, not per rpm. */
  37.534 -	if (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
  37.535 -		fprintf(stderr,
  37.536 -			"root installation directory \"%s\" does not exist\n",
  37.537 -			root);
  37.538 -		return -1;
  37.539 -	}
  37.540 -
  37.541 -	if (installer_init(&installer))
  37.542 -		return -1;
  37.543 -
  37.544 -	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
  37.545 -
  37.546 -	while (installer.stream.avail_in > 0) {
  37.547 -		installer.rest = sizeof *header;
  37.548 -		if (installer_inflate(&installer))
  37.549 -			return -1;
  37.550 -		
  37.551 -		header = (struct cpio_file_header *) installer.buffer;
  37.552 -		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
  37.553 -		filesize = fixed_hex_to_ulong(header->filesize,
  37.554 -					      sizeof header->filesize);
  37.555 -
  37.556 -		installer.rest = fixed_hex_to_ulong(header->namesize,
  37.557 -						    sizeof header->namesize);
  37.558 -
  37.559 -		if (installer_inflate(&installer) ||
  37.560 -		    installer_align(&installer, 4))
  37.561 -			return -1;
  37.562 -
  37.563 -		path = (char *) installer.buffer;
  37.564 -		/* This convention is so lame... */
  37.565 -		if (strcmp(path, "TRAILER!!!") == 0)
  37.566 -			break;
  37.567 -
  37.568 -		installer.rest = filesize;
  37.569 -		if (create_path(&installer, path + 1, mode) < 0)
  37.570 -			return -1;
  37.571 -		if (installer_align(&installer, 4))
  37.572 -			return -1;
  37.573 -	}
  37.574 -
  37.575 -	if (installer_finish(&installer))
  37.576 -		return -1;
  37.577 -
  37.578 -	run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
  37.579 -
  37.580 -	return 0;
  37.581 -}
  37.582 -
  37.583 -int
  37.584 -razor_rpm_close(struct razor_rpm *rpm)
  37.585 -{
  37.586 -	int err;
  37.587 -
  37.588 -	free(rpm->dirs);
  37.589 -	err = munmap(rpm->map, rpm->size);
  37.590 -	free(rpm);
  37.591 -
  37.592 -	return err;
  37.593 -}
  37.594 -
  37.595 -int
  37.596 -razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
  37.597 -{
  37.598 -	const char *name, *version, *release, *arch, *summary;
  37.599 -	const uint_32 *epoch;
  37.600 -	char evr[128], buf[16];
  37.601 -
  37.602 -	name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
  37.603 -	epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
  37.604 -	version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
  37.605 -	release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
  37.606 -	arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
  37.607 -	summary = razor_rpm_get_indirect(rpm, RPMTAG_SUMMARY, NULL);
  37.608 -
  37.609 -	if (epoch) {
  37.610 -		snprintf(buf, sizeof buf, "%u", ntohl(*epoch));
  37.611 -		razor_build_evr(evr, sizeof evr, buf, version, release);
  37.612 -	} else {
  37.613 -		razor_build_evr(evr, sizeof evr, NULL, version, release);
  37.614 -	}
  37.615 -	razor_importer_begin_package(importer, name, evr, arch);
  37.616 -
  37.617 -	import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
  37.618 -			  RPMTAG_REQUIRENAME,
  37.619 -			  RPMTAG_REQUIREVERSION,
  37.620 -			  RPMTAG_REQUIREFLAGS);
  37.621 -
  37.622 -	import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
  37.623 -			  RPMTAG_PROVIDENAME,
  37.624 -			  RPMTAG_PROVIDEVERSION,
  37.625 -			  RPMTAG_PROVIDEFLAGS);
  37.626 -
  37.627 -	import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
  37.628 -			  RPMTAG_OBSOLETENAME,
  37.629 -			  RPMTAG_OBSOLETEVERSION,
  37.630 -			  RPMTAG_OBSOLETEFLAGS);
  37.631 -
  37.632 -	import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
  37.633 -			  RPMTAG_CONFLICTNAME,
  37.634 -			  RPMTAG_CONFLICTVERSION,
  37.635 -			  RPMTAG_CONFLICTFLAGS);
  37.636 -
  37.637 -	import_files(importer, rpm);
  37.638 -
  37.639 -	razor_importer_finish_package(importer);
  37.640 -
  37.641 -	return 0;
  37.642 -}
  37.643 -
  37.644 -union rpm_entry {
  37.645 -	void *p;
  37.646 -	char *string;
  37.647 -	char **list;
  37.648 -	uint_32 *flags;
  37.649 -	uint_32 integer;
  37.650 -};
  37.651 -
  37.652 -static void
  37.653 -add_properties(struct razor_importer *importer,
  37.654 -	       enum razor_property_type property_type,
  37.655 -	       Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
  37.656 -{
  37.657 -	union rpm_entry names, versions, flags;
  37.658 -	int_32 i, type, count;
  37.659 -
  37.660 -	headerGetEntry(h, name_tag, &type, &names.p, &count);
  37.661 -	headerGetEntry(h, version_tag, &type, &versions.p, &count);
  37.662 -	headerGetEntry(h, flags_tag, &type, &flags.p, &count);
  37.663 -
  37.664 -	for (i = 0; i < count; i++)
  37.665 -		razor_importer_add_property(importer,
  37.666 -					    names.list[i],
  37.667 -					    rpm_to_razor_flags (flags.flags[i]),
  37.668 -					    versions.list[i],
  37.669 -					    property_type);
  37.670 -}
  37.671 -
  37.672 -struct razor_set *
  37.673 -razor_set_create_from_rpmdb(void)
  37.674 -{
  37.675 -	struct razor_importer *importer;
  37.676 -	rpmdbMatchIterator iter;
  37.677 -	Header h;
  37.678 -	int_32 type, count, i;
  37.679 -	union rpm_entry name, epoch, version, release, arch;
  37.680 -	union rpm_entry summary, description, url, license;
  37.681 -	union rpm_entry basenames, dirnames, dirindexes;
  37.682 -	char filename[PATH_MAX], evr[128], buf[16];
  37.683 -	rpmdb db;
  37.684 -
  37.685 -	rpmReadConfigFiles(NULL, NULL);
  37.686 -
  37.687 -	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
  37.688 -		fprintf(stderr, "cannot open rpm database\n");
  37.689 -		exit(1);
  37.690 -	}
  37.691 -
  37.692 -	importer = razor_importer_new();
  37.693 -
  37.694 -	iter = rpmdbInitIterator(db, 0, NULL, 0);
  37.695 -	while (h = rpmdbNextIterator(iter), h != NULL) {
  37.696 -		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
  37.697 -		headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
  37.698 -		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
  37.699 -		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
  37.700 -		headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
  37.701 -		headerGetEntry(h, RPMTAG_SUMMARY, &type, &summary.p, &count);
  37.702 -		headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &description.p, &count);
  37.703 -		headerGetEntry(h, RPMTAG_URL, &type, &url.p, &count);
  37.704 -		headerGetEntry(h, RPMTAG_LICENSE, &type, &license.p, &count);
  37.705 -
  37.706 -		if (epoch.flags != NULL) {
  37.707 -			snprintf(buf, sizeof buf, "%u", *epoch.flags);
  37.708 -			razor_build_evr(evr, sizeof evr,
  37.709 -					buf, version.string, release.string);
  37.710 -		} else {
  37.711 -			razor_build_evr(evr, sizeof evr,
  37.712 -					NULL, version.string, release.string);
  37.713 -		}
  37.714 -
  37.715 -		razor_importer_begin_package(importer,
  37.716 -					     name.string, evr, arch.string);
  37.717 -		razor_importer_add_details(importer, summary.string,
  37.718 -					   description.string, url.string,
  37.719 -					   license.string);
  37.720 -
  37.721 -		add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
  37.722 -			       RPMTAG_REQUIRENAME,
  37.723 -			       RPMTAG_REQUIREVERSION,
  37.724 -			       RPMTAG_REQUIREFLAGS);
  37.725 -
  37.726 -		add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
  37.727 -			       RPMTAG_PROVIDENAME,
  37.728 -			       RPMTAG_PROVIDEVERSION,
  37.729 -			       RPMTAG_PROVIDEFLAGS);
  37.730 -
  37.731 -		add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
  37.732 -			       RPMTAG_OBSOLETENAME,
  37.733 -			       RPMTAG_OBSOLETEVERSION,
  37.734 -			       RPMTAG_OBSOLETEFLAGS);
  37.735 -
  37.736 -		add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
  37.737 -			       RPMTAG_CONFLICTNAME,
  37.738 -			       RPMTAG_CONFLICTVERSION,
  37.739 -			       RPMTAG_CONFLICTFLAGS);
  37.740 -
  37.741 -		headerGetEntry(h, RPMTAG_BASENAMES, &type,
  37.742 -			       &basenames.p, &count);
  37.743 -		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
  37.744 -			       &dirnames.p, &count);
  37.745 -		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
  37.746 -			       &dirindexes.p, &count);
  37.747 -		for (i = 0; i < count; i++) {
  37.748 -			snprintf(filename, sizeof filename, "%s%s",
  37.749 -				 dirnames.list[dirindexes.flags[i]],
  37.750 -				 basenames.list[i]);
  37.751 -			razor_importer_add_file(importer, filename);
  37.752 -		}
  37.753 -
  37.754 -		razor_importer_finish_package(importer);
  37.755 -	}
  37.756 -
  37.757 -	rpmdbClose(db);
  37.758 -
  37.759 -	return razor_importer_finish(importer);
  37.760 -}
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/src/.gitignore	Fri Jun 20 19:04:47 2008 -0400
    38.3 @@ -0,0 +1,8 @@
    38.4 +.deps
    38.5 +.libs
    38.6 +razor
    38.7 +rpm
    38.8 +*.repo
    38.9 +*.xml.gz
   38.10 +install
   38.11 +rpms
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/src/Makefile.am	Fri Jun 20 19:04:47 2008 -0400
    39.3 @@ -0,0 +1,26 @@
    39.4 +## Process this file with automake to produce Makefile.in
    39.5 +
    39.6 +INCLUDES = \
    39.7 +	$(CURL_CFLAGS) \
    39.8 +	$(EXPAT_CFLAGS) \
    39.9 +	$(RPM_CFLAGS) \
   39.10 +	-I$(top_builddir)/src -I$(top_srcdir)/src \
   39.11 +	-I$(top_srcdir)/librazor \
   39.12 +	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
   39.13 +	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
   39.14 +	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
   39.15 +	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
   39.16 +	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
   39.17 +	-DPACKAGE_LOCALE_DIR=\""$(localedir)"\"
   39.18 +
   39.19 +bin_PROGRAMS = razor rpm
   39.20 +
   39.21 +razor_SOURCES = main.c import-rpmdb.c import-yum.c
   39.22 +razor_LDADD = $(RPM_LIBS) $(EXPAT_LIBS) $(CURL_LIBS) $(top_builddir)/librazor/librazor.la
   39.23 +
   39.24 +rpm_SOURCES = rpm.c
   39.25 +rpm_LDADD = $(top_builddir)/librazor/librazor.la
   39.26 +
   39.27 +clean-local :
   39.28 +	rm -f *~
   39.29 +
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/src/import-rpmdb.c	Fri Jun 20 19:04:47 2008 -0400
    40.3 @@ -0,0 +1,170 @@
    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 <stdio.h>
   40.24 +#include <stddef.h>
   40.25 +#include <string.h>
   40.26 +#include <fcntl.h>
   40.27 +#include <rpm/rpmlib.h>
   40.28 +#include <rpm/rpmdb.h>
   40.29 +
   40.30 +#include "razor.h"
   40.31 +
   40.32 +union rpm_entry {
   40.33 +	void *p;
   40.34 +	char *string;
   40.35 +	char **list;
   40.36 +	uint_32 *flags;
   40.37 +	uint_32 integer;
   40.38 +};
   40.39 +
   40.40 +static uint32_t
   40.41 +rpm_to_razor_flags(uint32_t flags)
   40.42 +{
   40.43 +	uint32_t razor_flags;
   40.44 +
   40.45 +	razor_flags = 0;
   40.46 +	if (flags & RPMSENSE_LESS)
   40.47 +		razor_flags |= RAZOR_PROPERTY_LESS;
   40.48 +	if (flags & RPMSENSE_EQUAL)
   40.49 +		razor_flags |= RAZOR_PROPERTY_EQUAL;
   40.50 +	if (flags & RPMSENSE_GREATER)
   40.51 +		razor_flags |= RAZOR_PROPERTY_GREATER;
   40.52 +
   40.53 +	if (flags & RPMSENSE_SCRIPT_PRE)
   40.54 +		razor_flags |= RAZOR_PROPERTY_PRE;
   40.55 +	if (flags & RPMSENSE_SCRIPT_POST)
   40.56 +		razor_flags |= RAZOR_PROPERTY_POST;
   40.57 +	if (flags & RPMSENSE_SCRIPT_PREUN)
   40.58 +		razor_flags |= RAZOR_PROPERTY_PREUN;
   40.59 +	if (flags & RPMSENSE_SCRIPT_POSTUN)
   40.60 +		razor_flags |= RAZOR_PROPERTY_POSTUN;
   40.61 +
   40.62 +	return razor_flags;
   40.63 +}
   40.64 +
   40.65 +static void
   40.66 +add_properties(struct razor_importer *importer,
   40.67 +	       uint32_t type_flags,
   40.68 +	       Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
   40.69 +{
   40.70 +	union rpm_entry names, versions, flags;
   40.71 +	int_32 i, type, count;
   40.72 +
   40.73 +	headerGetEntry(h, name_tag, &type, &names.p, &count);
   40.74 +	headerGetEntry(h, version_tag, &type, &versions.p, &count);
   40.75 +	headerGetEntry(h, flags_tag, &type, &flags.p, &count);
   40.76 +
   40.77 +	for (i = 0; i < count; i++)
   40.78 +		razor_importer_add_property(importer,
   40.79 +					    names.list[i],
   40.80 +					    rpm_to_razor_flags (flags.flags[i]) | type_flags,
   40.81 +					    versions.list[i]);
   40.82 +}
   40.83 +
   40.84 +struct razor_set *
   40.85 +razor_set_create_from_rpmdb(void)
   40.86 +{
   40.87 +	struct razor_importer *importer;
   40.88 +	rpmdbMatchIterator iter;
   40.89 +	Header h;
   40.90 +	int_32 type, count, i;
   40.91 +	union rpm_entry name, epoch, version, release, arch;
   40.92 +	union rpm_entry summary, description, url, license;
   40.93 +	union rpm_entry basenames, dirnames, dirindexes;
   40.94 +	char filename[PATH_MAX], evr[128], buf[16];
   40.95 +	rpmdb db;
   40.96 +
   40.97 +	rpmReadConfigFiles(NULL, NULL);
   40.98 +
   40.99 +	if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
  40.100 +		fprintf(stderr, "cannot open rpm database\n");
  40.101 +		exit(1);
  40.102 +	}
  40.103 +
  40.104 +	importer = razor_importer_new();
  40.105 +
  40.106 +	iter = rpmdbInitIterator(db, 0, NULL, 0);
  40.107 +	while (h = rpmdbNextIterator(iter), h != NULL) {
  40.108 +		headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
  40.109 +		headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
  40.110 +		headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
  40.111 +		headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
  40.112 +		headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
  40.113 +		headerGetEntry(h, RPMTAG_SUMMARY, &type, &summary.p, &count);
  40.114 +		headerGetEntry(h, RPMTAG_DESCRIPTION, &type, &description.p,
  40.115 +			       &count);
  40.116 +		headerGetEntry(h, RPMTAG_URL, &type, &url.p, &count);
  40.117 +		headerGetEntry(h, RPMTAG_LICENSE, &type, &license.p, &count);
  40.118 +
  40.119 +		if (epoch.flags != NULL) {
  40.120 +			snprintf(buf, sizeof buf, "%u", *epoch.flags);
  40.121 +			razor_build_evr(evr, sizeof evr,
  40.122 +					buf, version.string, release.string);
  40.123 +		} else {
  40.124 +			razor_build_evr(evr, sizeof evr,
  40.125 +					NULL, version.string, release.string);
  40.126 +		}
  40.127 +
  40.128 +		razor_importer_begin_package(importer,
  40.129 +					     name.string, evr, arch.string);
  40.130 +		razor_importer_add_details(importer, summary.string,
  40.131 +					   description.string, url.string,
  40.132 +					   license.string);
  40.133 +
  40.134 +		add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
  40.135 +			       RPMTAG_REQUIRENAME,
  40.136 +			       RPMTAG_REQUIREVERSION,
  40.137 +			       RPMTAG_REQUIREFLAGS);
  40.138 +
  40.139 +		add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
  40.140 +			       RPMTAG_PROVIDENAME,
  40.141 +			       RPMTAG_PROVIDEVERSION,
  40.142 +			       RPMTAG_PROVIDEFLAGS);
  40.143 +
  40.144 +		add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
  40.145 +			       RPMTAG_OBSOLETENAME,
  40.146 +			       RPMTAG_OBSOLETEVERSION,
  40.147 +			       RPMTAG_OBSOLETEFLAGS);
  40.148 +
  40.149 +		add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
  40.150 +			       RPMTAG_CONFLICTNAME,
  40.151 +			       RPMTAG_CONFLICTVERSION,
  40.152 +			       RPMTAG_CONFLICTFLAGS);
  40.153 +
  40.154 +		headerGetEntry(h, RPMTAG_BASENAMES, &type,
  40.155 +			       &basenames.p, &count);
  40.156 +		headerGetEntry(h, RPMTAG_DIRNAMES, &type,
  40.157 +			       &dirnames.p, &count);
  40.158 +		headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
  40.159 +			       &dirindexes.p, &count);
  40.160 +		for (i = 0; i < count; i++) {
  40.161 +			snprintf(filename, sizeof filename, "%s%s",
  40.162 +				 dirnames.list[dirindexes.flags[i]],
  40.163 +				 basenames.list[i]);
  40.164 +			razor_importer_add_file(importer, filename);
  40.165 +		}
  40.166 +
  40.167 +		razor_importer_finish_package(importer);
  40.168 +	}
  40.169 +
  40.170 +	rpmdbClose(db);
  40.171 +
  40.172 +	return razor_importer_finish(importer);
  40.173 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/src/import-yum.c	Fri Jun 20 19:04:47 2008 -0400
    41.3 @@ -0,0 +1,352 @@
    41.4 +/*
    41.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    41.6 + * Copyright (C) 2008  Red Hat, Inc
    41.7 + *
    41.8 + * This program is free software; you can redistribute it and/or modify
    41.9 + * it under the terms of the GNU General Public License as published by
   41.10 + * the Free Software Foundation; either version 2 of the License, or
   41.11 + * (at your option) any later version.
   41.12 + *
   41.13 + * This program is distributed in the hope that it will be useful,
   41.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.16 + * GNU General Public License for more details.
   41.17 + *
   41.18 + * You should have received a copy of the GNU General Public License along
   41.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   41.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   41.21 + */
   41.22 +
   41.23 +#define _GNU_SOURCE
   41.24 +
   41.25 +#include <string.h>
   41.26 +#include <stdio.h>
   41.27 +#include <stdint.h>
   41.28 +#include <sys/stat.h>
   41.29 +#include <sys/mman.h>
   41.30 +#include <unistd.h>
   41.31 +#include <fcntl.h>
   41.32 +#include <errno.h>
   41.33 +
   41.34 +#include <expat.h>
   41.35 +#include <zlib.h>
   41.36 +#include "razor.h"
   41.37 +
   41.38 +/* Import a yum filelist as a razor package set. */
   41.39 +
   41.40 +enum {
   41.41 +	YUM_STATE_BEGIN,
   41.42 +	YUM_STATE_PACKAGE_NAME,
   41.43 +	YUM_STATE_PACKAGE_ARCH,
   41.44 +	YUM_STATE_SUMMARY,
   41.45 +	YUM_STATE_DESCRIPTION,
   41.46 +	YUM_STATE_URL,
   41.47 +	YUM_STATE_LICENSE,
   41.48 +	YUM_STATE_CHECKSUM,
   41.49 +	YUM_STATE_REQUIRES,
   41.50 +	YUM_STATE_PROVIDES,
   41.51 +	YUM_STATE_OBSOLETES,
   41.52 +	YUM_STATE_CONFLICTS,
   41.53 +	YUM_STATE_FILE
   41.54 +};
   41.55 +
   41.56 +struct yum_context {
   41.57 +	XML_Parser primary_parser;
   41.58 +	XML_Parser filelists_parser;
   41.59 +	XML_Parser current_parser;
   41.60 +
   41.61 +	struct razor_importer *importer;
   41.62 +	struct import_property_context *current_property_context;
   41.63 +	char name[256], arch[64], summary[512], description[4096];
   41.64 +	char url[256], license[64], buffer[512], *p;
   41.65 +	char pkgid[128];
   41.66 +	uint32_t property_type;
   41.67 +	int state;
   41.68 +};
   41.69 +
   41.70 +static uint32_t
   41.71 +yum_to_razor_relation (const char *flags)
   41.72 +{
   41.73 +	if (flags[0] == 'L') {
   41.74 +		if (flags[1] == 'T')
   41.75 +			return RAZOR_PROPERTY_LESS;
   41.76 +		else
   41.77 +			return RAZOR_PROPERTY_LESS | RAZOR_PROPERTY_EQUAL;
   41.78 +	} else if (flags[0] == 'G') {
   41.79 +		if (flags[1] == 'T')
   41.80 +			return RAZOR_PROPERTY_GREATER;
   41.81 +		else
   41.82 +			return RAZOR_PROPERTY_GREATER | RAZOR_PROPERTY_EQUAL;
   41.83 +	} else
   41.84 +		return RAZOR_PROPERTY_EQUAL;
   41.85 +}
   41.86 +
   41.87 +static void
   41.88 +yum_primary_start_element(void *data, const char *name, const char **atts)
   41.89 +{
   41.90 +	struct yum_context *ctx = data;
   41.91 +	const char *n, *epoch, *version, *release;
   41.92 +	char buffer[128];
   41.93 +	uint32_t pre, relation, flags;
   41.94 +	int i;
   41.95 +
   41.96 +	if (strcmp(name, "name") == 0) {
   41.97 +		ctx->state = YUM_STATE_PACKAGE_NAME;
   41.98 +		ctx->p = ctx->name;
   41.99 +	} else if (strcmp(name, "arch") == 0) {
  41.100 +		ctx->state = YUM_STATE_PACKAGE_ARCH;
  41.101 +		ctx->p = ctx->arch;
  41.102 +	} else if (strcmp(name, "version") == 0) {
  41.103 +		epoch = NULL;
  41.104 +		version = NULL;
  41.105 +		release = NULL;
  41.106 +		for (i = 0; atts[i]; i += 2) {
  41.107 +			if (strcmp(atts[i], "epoch") == 0)
  41.108 +				epoch = atts[i + 1];
  41.109 +			else if (strcmp(atts[i], "ver") == 0)
  41.110 +				version = atts[i + 1];
  41.111 +			else if (strcmp(atts[i], "rel") == 0)
  41.112 +				release = atts[i + 1];
  41.113 +		}
  41.114 +		if (version == NULL || release == NULL) {
  41.115 +			fprintf(stderr, "invalid version tag, "
  41.116 +				"missing version or  release attribute\n");
  41.117 +			return;
  41.118 +		}
  41.119 +
  41.120 +		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  41.121 +		razor_importer_begin_package(ctx->importer,
  41.122 +					     ctx->name, buffer, ctx->arch);
  41.123 +	} else if (strcmp(name, "summary") == 0) {
  41.124 +		ctx->p = ctx->summary;
  41.125 +		ctx->state = YUM_STATE_SUMMARY;
  41.126 +	} else if (strcmp(name, "description") == 0) {
  41.127 +		ctx->p = ctx->description;
  41.128 +		ctx->state = YUM_STATE_DESCRIPTION;
  41.129 +	} else if (strcmp(name, "url") == 0) {
  41.130 +		ctx->p = ctx->url;
  41.131 +		ctx->state = YUM_STATE_URL;
  41.132 +	} else if (strcmp(name, "checksum") == 0) {
  41.133 +		ctx->p = ctx->pkgid;
  41.134 +		ctx->state = YUM_STATE_CHECKSUM;
  41.135 +	} else if (strcmp(name, "rpm:license") == 0) {
  41.136 +		ctx->p = ctx->license;
  41.137 +		ctx->state = YUM_STATE_LICENSE;
  41.138 +	} else if (strcmp(name, "rpm:requires") == 0) {
  41.139 +		ctx->state = YUM_STATE_REQUIRES;
  41.140 +		ctx->property_type = RAZOR_PROPERTY_REQUIRES;
  41.141 +	} else if (strcmp(name, "rpm:provides") == 0) {
  41.142 +		ctx->state = YUM_STATE_PROVIDES;
  41.143 +		ctx->property_type = RAZOR_PROPERTY_PROVIDES;
  41.144 +	} else if (strcmp(name, "rpm:obsoletes") == 0) {
  41.145 +		ctx->state = YUM_STATE_OBSOLETES;
  41.146 +		ctx->property_type = RAZOR_PROPERTY_OBSOLETES;
  41.147 +	} else if (strcmp(name, "rpm:conflicts") == 0) {
  41.148 +		ctx->state = YUM_STATE_CONFLICTS;
  41.149 +		ctx->property_type = RAZOR_PROPERTY_CONFLICTS;
  41.150 +	} else if (strcmp(name, "rpm:entry") == 0 &&
  41.151 +		   ctx->state != YUM_STATE_BEGIN) {
  41.152 +		n = NULL;
  41.153 +		epoch = NULL;
  41.154 +		version = NULL;
  41.155 +		release = NULL;
  41.156 +		relation = RAZOR_PROPERTY_EQUAL;
  41.157 +		pre = 0;
  41.158 +		for (i = 0; atts[i]; i += 2) {
  41.159 +			if (strcmp(atts[i], "name") == 0)
  41.160 +				n = atts[i + 1];
  41.161 +			else if (strcmp(atts[i], "epoch") == 0)
  41.162 +				epoch = atts[i + 1];
  41.163 +			else if (strcmp(atts[i], "ver") == 0)
  41.164 +				version = atts[i + 1];
  41.165 +			else if (strcmp(atts[i], "rel") == 0)
  41.166 +				release = atts[i + 1];
  41.167 +			else if (strcmp(atts[i], "flags") == 0)
  41.168 +				relation = yum_to_razor_relation(atts[i + 1]);
  41.169 +			else if (strcmp(atts[i], "pre") == 0)
  41.170 +				pre = 
  41.171 +					RAZOR_PROPERTY_PRE |
  41.172 +					RAZOR_PROPERTY_POST |
  41.173 +					RAZOR_PROPERTY_PREUN |
  41.174 +					RAZOR_PROPERTY_POSTUN;
  41.175 +		}
  41.176 +
  41.177 +		if (n == NULL) {
  41.178 +			fprintf(stderr, "invalid rpm:entry, "
  41.179 +				"missing name or version attributes\n");
  41.180 +			return;
  41.181 +		}
  41.182 +
  41.183 +		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  41.184 +		flags = ctx->property_type | relation | pre;
  41.185 +		razor_importer_add_property(ctx->importer, n, flags, buffer);
  41.186 +	}
  41.187 +}
  41.188 +
  41.189 +static void
  41.190 +yum_primary_end_element (void *data, const char *name)
  41.191 +{
  41.192 +	struct yum_context *ctx = data;
  41.193 +
  41.194 +	switch (ctx->state) {
  41.195 +	case YUM_STATE_PACKAGE_NAME:
  41.196 +	case YUM_STATE_PACKAGE_ARCH:
  41.197 +	case YUM_STATE_SUMMARY:
  41.198 +	case YUM_STATE_DESCRIPTION:
  41.199 +	case YUM_STATE_URL:
  41.200 +	case YUM_STATE_LICENSE:
  41.201 +	case YUM_STATE_CHECKSUM:
  41.202 +	case YUM_STATE_FILE:
  41.203 +		ctx->state = YUM_STATE_BEGIN;
  41.204 +		break;
  41.205 +	}
  41.206 +
  41.207 +	if (strcmp(name, "package") == 0) {
  41.208 +		razor_importer_add_details(ctx->importer, ctx->summary,
  41.209 +					   ctx->description, ctx->url,
  41.210 +					   ctx->license);
  41.211 +
  41.212 +		XML_StopParser(ctx->current_parser, XML_TRUE);
  41.213 +		ctx->current_parser = ctx->filelists_parser;
  41.214 +	}
  41.215 +}
  41.216 +
  41.217 +static void
  41.218 +yum_character_data (void *data, const XML_Char *s, int len)
  41.219 +{
  41.220 +	struct yum_context *ctx = data;
  41.221 +
  41.222 +	switch (ctx->state) {
  41.223 +	case YUM_STATE_PACKAGE_NAME:
  41.224 +	case YUM_STATE_PACKAGE_ARCH:
  41.225 +	case YUM_STATE_SUMMARY:
  41.226 +	case YUM_STATE_DESCRIPTION:
  41.227 +	case YUM_STATE_URL:
  41.228 +	case YUM_STATE_LICENSE:
  41.229 +	case YUM_STATE_CHECKSUM:
  41.230 +	case YUM_STATE_FILE:
  41.231 +		memcpy(ctx->p, s, len);
  41.232 +		ctx->p += len;
  41.233 +		*ctx->p = '\0';
  41.234 +		break;
  41.235 +	}
  41.236 +}
  41.237 +
  41.238 +static void
  41.239 +yum_filelists_start_element(void *data, const char *name, const char **atts)
  41.240 +{
  41.241 +	struct yum_context *ctx = data;
  41.242 +	const char *pkg, *pkgid;
  41.243 +	int i;
  41.244 +
  41.245 +	if (strcmp(name, "package") == 0) {
  41.246 +		pkg = NULL;
  41.247 +		pkgid = NULL;
  41.248 +		for (i = 0; atts[i]; i += 2) {
  41.249 +			if (strcmp(atts[i], "name") == 0)
  41.250 +				pkg = atts[i + 1];
  41.251 +			else if (strcmp(atts[i], "pkgid") == 0)
  41.252 +				pkgid = atts[i + 1];
  41.253 +		}
  41.254 +		if (strcmp(pkgid, ctx->pkgid) != 0)
  41.255 +			fprintf(stderr, "primary.xml and filelists.xml "
  41.256 +				"mismatch for %s: %s vs %s",
  41.257 +				pkg, pkgid, ctx->pkgid);
  41.258 +	} else if (strcmp(name, "file") == 0) {
  41.259 +		ctx->state = YUM_STATE_FILE;
  41.260 +		ctx->p = ctx->buffer;
  41.261 +	}
  41.262 +}
  41.263 +
  41.264 +
  41.265 +static void
  41.266 +yum_filelists_end_element (void *data, const char *name)
  41.267 +{
  41.268 +	struct yum_context *ctx = data;
  41.269 +
  41.270 +	ctx->state = YUM_STATE_BEGIN;
  41.271 +	if (strcmp(name, "package") == 0) {
  41.272 +		XML_StopParser(ctx->current_parser, XML_TRUE);
  41.273 +		ctx->current_parser = ctx->primary_parser;
  41.274 +		razor_importer_finish_package(ctx->importer);
  41.275 +	} else if (strcmp(name, "file") == 0)
  41.276 +		razor_importer_add_file(ctx->importer, ctx->buffer);
  41.277 +
  41.278 +}
  41.279 +
  41.280 +#define XML_BUFFER_SIZE 4096
  41.281 +
  41.282 +struct razor_set *
  41.283 +razor_set_create_from_yum(void)
  41.284 +{
  41.285 +	struct yum_context ctx;
  41.286 +	void *buf;
  41.287 +	int len, ret;
  41.288 +	gzFile primary, filelists;
  41.289 +	XML_ParsingStatus status;
  41.290 +
  41.291 +	ctx.importer = razor_importer_new();
  41.292 +	ctx.state = YUM_STATE_BEGIN;
  41.293 +
  41.294 +	ctx.primary_parser = XML_ParserCreate(NULL);
  41.295 +	XML_SetUserData(ctx.primary_parser, &ctx);
  41.296 +	XML_SetElementHandler(ctx.primary_parser,
  41.297 +			      yum_primary_start_element,
  41.298 +			      yum_primary_end_element);
  41.299 +	XML_SetCharacterDataHandler(ctx.primary_parser,
  41.300 +				    yum_character_data);
  41.301 +
  41.302 +	ctx.filelists_parser = XML_ParserCreate(NULL);
  41.303 +	XML_SetUserData(ctx.filelists_parser, &ctx);
  41.304 +	XML_SetElementHandler(ctx.filelists_parser,
  41.305 +			      yum_filelists_start_element,
  41.306 +			      yum_filelists_end_element);
  41.307 +	XML_SetCharacterDataHandler(ctx.filelists_parser,
  41.308 +				    yum_character_data);
  41.309 +
  41.310 +	primary = gzopen("primary.xml.gz", "rb");
  41.311 +	if (primary == NULL)
  41.312 +		return NULL;
  41.313 +	filelists = gzopen("filelists.xml.gz", "rb");
  41.314 +	if (filelists == NULL)
  41.315 +		return NULL;
  41.316 +
  41.317 +	ctx.current_parser = ctx.primary_parser;
  41.318 +
  41.319 +	do {
  41.320 +		XML_GetParsingStatus(ctx.current_parser, &status);
  41.321 +		switch (status.parsing) {
  41.322 +		case XML_SUSPENDED:
  41.323 +			ret = XML_ResumeParser(ctx.current_parser);
  41.324 +			break;
  41.325 +		case XML_PARSING:
  41.326 +		case XML_INITIALIZED:
  41.327 +			buf = XML_GetBuffer(ctx.current_parser,
  41.328 +					    XML_BUFFER_SIZE);
  41.329 +			if (ctx.current_parser == ctx.primary_parser)
  41.330 +				len = gzread(primary, buf, XML_BUFFER_SIZE);
  41.331 +			else
  41.332 +				len = gzread(filelists, buf, XML_BUFFER_SIZE);
  41.333 +			if (len < 0) {
  41.334 +				fprintf(stderr,
  41.335 +					"couldn't read input: %s\n",
  41.336 +					strerror(errno));
  41.337 +				return NULL;
  41.338 +			}
  41.339 +
  41.340 +			XML_ParseBuffer(ctx.current_parser, len, len == 0);
  41.341 +			break;
  41.342 +		case XML_FINISHED:
  41.343 +			break;
  41.344 +		}
  41.345 +	} while (status.parsing != XML_FINISHED);
  41.346 +
  41.347 +
  41.348 +	XML_ParserFree(ctx.primary_parser);
  41.349 +	XML_ParserFree(ctx.filelists_parser);
  41.350 +
  41.351 +	gzclose(primary);
  41.352 +	gzclose(filelists);
  41.353 +
  41.354 +	return razor_importer_finish(ctx.importer);
  41.355 +}
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/src/main.c	Fri Jun 20 19:04:47 2008 -0400
    42.3 @@ -0,0 +1,858 @@
    42.4 +/*
    42.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    42.6 + * Copyright (C) 2008  Red Hat, Inc
    42.7 + *
    42.8 + * This program is free software; you can redistribute it and/or modify
    42.9 + * it under the terms of the GNU General Public License as published by
   42.10 + * the Free Software Foundation; either version 2 of the License, or
   42.11 + * (at your option) any later version.
   42.12 + *
   42.13 + * This program is distributed in the hope that it will be useful,
   42.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.16 + * GNU General Public License for more details.
   42.17 + *
   42.18 + * You should have received a copy of the GNU General Public License along
   42.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   42.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   42.21 + */
   42.22 +
   42.23 +#include <stdlib.h>
   42.24 +#include <stddef.h>
   42.25 +#include <stdio.h>
   42.26 +#include <stdint.h>
   42.27 +#include <string.h>
   42.28 +#include <sys/stat.h>
   42.29 +#include <unistd.h>
   42.30 +#include <fcntl.h>
   42.31 +#include <dirent.h>
   42.32 +#include <curl/curl.h>
   42.33 +#include <fnmatch.h>
   42.34 +#include <errno.h>
   42.35 +#include "razor.h"
   42.36 +
   42.37 +static const char system_repo_filename[] = "system.repo";
   42.38 +static const char next_repo_filename[] = "system-next.repo";
   42.39 +static const char rawhide_repo_filename[] = "rawhide.repo";
   42.40 +static const char updated_repo_filename[] = "system-updated.repo";
   42.41 +static const char install_root[] = "install";
   42.42 +static const char *repo_filename = system_repo_filename;
   42.43 +static const char *yum_url;
   42.44 +
   42.45 +static int
   42.46 +command_list(int argc, const char *argv[])
   42.47 +{
   42.48 +	struct razor_set *set;
   42.49 +	struct razor_package_iterator *pi;
   42.50 +	struct razor_package *package;
   42.51 +	const char *pattern, *name, *version, *arch;
   42.52 +	int only_names = 0, i = 0;
   42.53 +
   42.54 +	if (i < argc && strcmp(argv[i], "--only-names") == 0) {
   42.55 +		only_names = 1;
   42.56 +		i++;
   42.57 +	}
   42.58 +
   42.59 +	pattern = argv[i];
   42.60 +	set = razor_set_open(repo_filename);
   42.61 +	pi = razor_package_iterator_create(set);
   42.62 +	while (razor_package_iterator_next(pi, &package,
   42.63 +					   &name, &version, &arch)) {
   42.64 +		if (pattern && fnmatch(pattern, name, 0) != 0)
   42.65 +			continue;
   42.66 +
   42.67 +		if (only_names)
   42.68 +			printf("%s\n", name);
   42.69 +		else
   42.70 +			printf("%s-%s.%s\n", name, version, arch);
   42.71 +	}
   42.72 +	razor_package_iterator_destroy(pi);
   42.73 +	razor_set_destroy(set);
   42.74 +
   42.75 +	return 0;
   42.76 +}
   42.77 +
   42.78 +static int
   42.79 +list_properties(const char *package_name, uint32_t type)
   42.80 +{
   42.81 +	struct razor_set *set;
   42.82 +	struct razor_property *property;
   42.83 +	struct razor_package *package;
   42.84 +	struct razor_property_iterator *pi;
   42.85 +	const char *name, *version;
   42.86 +	uint32_t flags;
   42.87 +
   42.88 +	set = razor_set_open(repo_filename);
   42.89 +	if (package_name)
   42.90 +		package = razor_set_get_package(set, package_name);
   42.91 +	else
   42.92 +		package = NULL;
   42.93 +
   42.94 +	pi = razor_property_iterator_create(set, package);
   42.95 +	while (razor_property_iterator_next(pi, &property,
   42.96 +					    &name, &flags, &version)) {
   42.97 +		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
   42.98 +			continue;
   42.99 +		printf("%s", name);
  42.100 +		if (version[0] != '\0')
  42.101 +			printf(" %s %s",
  42.102 +			       razor_property_relation_to_string(property),
  42.103 +			       version);
  42.104 +
  42.105 +		if (flags & ~(RAZOR_PROPERTY_RELATION_MASK | RAZOR_PROPERTY_TYPE_MASK)) {
  42.106 +			printf(" [");
  42.107 +			if (flags & RAZOR_PROPERTY_PRE)
  42.108 +				printf(" pre");
  42.109 +			if (flags & RAZOR_PROPERTY_POST)
  42.110 +				printf(" post");
  42.111 +			if (flags & RAZOR_PROPERTY_PREUN)
  42.112 +				printf(" preun");
  42.113 +			if (flags & RAZOR_PROPERTY_POSTUN)
  42.114 +				printf(" postun");
  42.115 +			printf(" ]");
  42.116 +		}
  42.117 +		printf("\n");
  42.118 +	}
  42.119 +	razor_property_iterator_destroy(pi);
  42.120 +
  42.121 +	razor_set_destroy(set);
  42.122 +
  42.123 +	return 0;
  42.124 +}
  42.125 +
  42.126 +static int
  42.127 +command_list_requires(int argc, const char *argv[])
  42.128 +{
  42.129 +	return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
  42.130 +}
  42.131 +
  42.132 +static int
  42.133 +command_list_provides(int argc, const char *argv[])
  42.134 +{
  42.135 +	return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
  42.136 +}
  42.137 +
  42.138 +static int
  42.139 +command_list_obsoletes(int argc, const char *argv[])
  42.140 +{
  42.141 +	return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
  42.142 +}
  42.143 +
  42.144 +static int
  42.145 +command_list_conflicts(int argc, const char *argv[])
  42.146 +{
  42.147 +	return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
  42.148 +}
  42.149 +
  42.150 +static int
  42.151 +command_list_files(int argc, const char *argv[])
  42.152 +{
  42.153 +	struct razor_set *set;
  42.154 +
  42.155 +	set = razor_set_open(repo_filename);
  42.156 +	razor_set_open_files(set, "system-files.repo");
  42.157 +	if (set == NULL)
  42.158 +		return 1;
  42.159 +	razor_set_list_files(set, argv[0]);
  42.160 +	razor_set_destroy(set);
  42.161 +
  42.162 +	return 0;
  42.163 +}
  42.164 +
  42.165 +static int
  42.166 +command_list_file_packages(int argc, const char *argv[])
  42.167 +{
  42.168 +	struct razor_set *set;
  42.169 +	struct razor_package_iterator *pi;
  42.170 +	struct razor_package *package;
  42.171 +	const char *name, *version, *arch;
  42.172 +
  42.173 +	set = razor_set_open(repo_filename);
  42.174 +	razor_set_open_files(set, "system-files.repo");
  42.175 +	if (set == NULL)
  42.176 +		return 1;
  42.177 +
  42.178 +	pi = razor_package_iterator_create_for_file(set, argv[0]);
  42.179 +	while (razor_package_iterator_next(pi, &package,
  42.180 +					   &name, &version, &arch))
  42.181 +		printf("%s-%s\n", name, version);
  42.182 +	razor_package_iterator_destroy(pi);
  42.183 +
  42.184 +	razor_set_destroy(set);
  42.185 +
  42.186 +	return 0;
  42.187 +}
  42.188 +
  42.189 +static int
  42.190 +command_list_package_files(int argc, const char *argv[])
  42.191 +{
  42.192 +	struct razor_set *set;
  42.193 +
  42.194 +	set = razor_set_open(repo_filename);
  42.195 +	razor_set_open_files(set, "system-files.repo");
  42.196 +	if (set == NULL)
  42.197 +		return 1;
  42.198 +	razor_set_list_package_files(set, argv[0]);
  42.199 +	razor_set_destroy(set);
  42.200 +
  42.201 +	return 0;
  42.202 +}
  42.203 +
  42.204 +static void
  42.205 +list_packages_for_property(struct razor_set *set,
  42.206 +			   struct razor_property *property)
  42.207 +{
  42.208 +	struct razor_package_iterator *pi;
  42.209 +	struct razor_package *package;
  42.210 +	const char *name, *version, *arch;
  42.211 +
  42.212 +	pi = razor_package_iterator_create_for_property(set, property);
  42.213 +	while (razor_package_iterator_next(pi, &package,
  42.214 +					   &name, &version, &arch))
  42.215 +		printf("%s-%s.%s\n", name, version, arch);
  42.216 +	razor_package_iterator_destroy(pi);
  42.217 +}
  42.218 +
  42.219 +static int
  42.220 +list_property_packages(const char *ref_name,
  42.221 +		       const char *ref_version,
  42.222 +		       uint32_t type)
  42.223 +{
  42.224 +	struct razor_set *set;
  42.225 +	struct razor_property *property;
  42.226 +	struct razor_property_iterator *pi;
  42.227 +	const char *name, *version;
  42.228 +	uint32_t flags;
  42.229 +
  42.230 +	if (ref_name == NULL)
  42.231 +		return 0;
  42.232 +
  42.233 +	set = razor_set_open(repo_filename);
  42.234 +	if (set == NULL)
  42.235 +		return 1;
  42.236 +
  42.237 +	pi = razor_property_iterator_create(set, NULL);
  42.238 +	while (razor_property_iterator_next(pi, &property,
  42.239 +					    &name, &flags, &version)) {
  42.240 +		if (strcmp(ref_name, name) != 0)
  42.241 +			continue;
  42.242 +		if (ref_version &&
  42.243 +		    (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
  42.244 +		    strcmp(ref_version, version) != 0)
  42.245 +			continue;
  42.246 +		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != type)
  42.247 +			continue;
  42.248 +
  42.249 +		list_packages_for_property(set, property);
  42.250 +	}
  42.251 +	razor_property_iterator_destroy(pi);
  42.252 +
  42.253 +	return 0;
  42.254 +}
  42.255 +
  42.256 +static int
  42.257 +command_what_requires(int argc, const char *argv[])
  42.258 +{
  42.259 +	return list_property_packages(argv[0], argv[1],
  42.260 +				      RAZOR_PROPERTY_REQUIRES);
  42.261 +}
  42.262 +
  42.263 +static int
  42.264 +command_what_provides(int argc, const char *argv[])
  42.265 +{
  42.266 +	return list_property_packages(argv[0], argv[1],
  42.267 +				      RAZOR_PROPERTY_PROVIDES);
  42.268 +}
  42.269 +
  42.270 +static int
  42.271 +show_progress(void *clientp,
  42.272 +	      double dltotal, double dlnow, double ultotal, double ulnow)
  42.273 +{
  42.274 +	const char *file = clientp;
  42.275 +
  42.276 +	if (!dlnow < dltotal)
  42.277 +		fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
  42.278 +			file, (int) dlnow / 1024, (int) dltotal / 1024);
  42.279 +
  42.280 +	return 0;
  42.281 +}
  42.282 +
  42.283 +static int
  42.284 +download_if_missing(const char *url, const char *file)
  42.285 +{
  42.286 +	CURL *curl;
  42.287 +	struct stat buf;
  42.288 +	char error[256];
  42.289 +	FILE *fp;
  42.290 +	CURLcode res;
  42.291 +	long response;
  42.292 +
  42.293 +	curl = curl_easy_init();
  42.294 +	if (curl == NULL)
  42.295 +		return 1;
  42.296 +
  42.297 +	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
  42.298 +	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  42.299 +	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
  42.300 +	curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
  42.301 +
  42.302 +	if (stat(file, &buf) < 0) {
  42.303 +		fp = fopen(file, "w");
  42.304 +		if (fp == NULL) {
  42.305 +			fprintf(stderr,
  42.306 +				"failed to open %s for writing\n", file);
  42.307 +			return -1;
  42.308 +		}
  42.309 +		curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  42.310 +		curl_easy_setopt(curl, CURLOPT_URL, url);
  42.311 +		res = curl_easy_perform(curl);
  42.312 +		fclose(fp);
  42.313 +		if (res != CURLE_OK) {
  42.314 +			fprintf(stderr, "curl error: %s\n", error);
  42.315 +			unlink(file);
  42.316 +			return -1;
  42.317 +		}
  42.318 +		res = curl_easy_getinfo(curl,
  42.319 +					CURLINFO_RESPONSE_CODE, &response);
  42.320 +		if (res != CURLE_OK) {
  42.321 +			fprintf(stderr, "curl error: %s\n", error);
  42.322 +                        unlink(file);
  42.323 +                        return -1;
  42.324 +		}
  42.325 +		if (response != 200) {
  42.326 +			fprintf(stderr, " - failed %ld\n", response);
  42.327 +                        unlink(file);
  42.328 +                        return -1;
  42.329 +		}
  42.330 +		fprintf(stderr, "\n");
  42.331 +	}
  42.332 +
  42.333 +	curl_easy_cleanup(curl);
  42.334 +
  42.335 +	return 0;
  42.336 +}
  42.337 +
  42.338 +#define YUM_URL "http://download.fedora.redhat.com" \
  42.339 +	"/pub/fedora/linux/development/i386/os"
  42.340 +
  42.341 +static int
  42.342 +command_import_yum(int argc, const char *argv[])
  42.343 +{
  42.344 +	struct razor_set *set;
  42.345 +	char buffer[512];
  42.346 +
  42.347 +	printf("downloading from %s.\n", yum_url);
  42.348 +	snprintf(buffer, sizeof buffer,
  42.349 +		 "%s/repodata/primary.xml.gz", yum_url);
  42.350 +	if (download_if_missing(buffer, "primary.xml.gz") < 0)
  42.351 +		return -1;
  42.352 +	snprintf(buffer, sizeof buffer,
  42.353 +		 "%s/repodata/filelists.xml.gz", yum_url);
  42.354 +	if (download_if_missing(buffer, "filelists.xml.gz") < 0)
  42.355 +		return -1;
  42.356 +
  42.357 +	set = razor_set_create_from_yum();
  42.358 +	if (set == NULL)
  42.359 +		return 1;
  42.360 +	razor_set_write(set, rawhide_repo_filename, RAZOR_REPO_FILE_MAIN);
  42.361 +	razor_set_write(set, "rawhide-details.repo", RAZOR_REPO_FILE_DETAILS);
  42.362 +	razor_set_write(set, "rawhide-files.repo", RAZOR_REPO_FILE_FILES);
  42.363 +	razor_set_destroy(set);
  42.364 +	printf("wrote %s\n", rawhide_repo_filename);
  42.365 +
  42.366 +	return 0;
  42.367 +}
  42.368 +
  42.369 +static int
  42.370 +command_import_rpmdb(int argc, const char *argv[])
  42.371 +{
  42.372 +	struct razor_set *set;
  42.373 +
  42.374 +	set = razor_set_create_from_rpmdb();
  42.375 +	if (set == NULL)
  42.376 +		return 1;
  42.377 +	razor_set_write(set, repo_filename, RAZOR_REPO_FILE_MAIN);
  42.378 +	razor_set_write(set, "system-details.repo", RAZOR_REPO_FILE_DETAILS);
  42.379 +	razor_set_write(set, "system-files.repo", RAZOR_REPO_FILE_FILES);
  42.380 +	razor_set_destroy(set);
  42.381 +	printf("wrote %s\n", repo_filename);
  42.382 +
  42.383 +	return 0;
  42.384 +}
  42.385 +
  42.386 +static int
  42.387 +mark_packages_for_update(struct razor_transaction *trans,
  42.388 +			 struct razor_set *set, const char *pattern)
  42.389 +{
  42.390 +	struct razor_package_iterator *pi;
  42.391 +	struct razor_package *package;
  42.392 +	const char *name, *version, *arch;
  42.393 +	int matches = 0;
  42.394 +
  42.395 +	pi = razor_package_iterator_create(set);
  42.396 +	while (razor_package_iterator_next(pi, &package,
  42.397 +					   &name, &version, &arch)) {
  42.398 +		if (pattern && fnmatch(pattern, name, 0) == 0) {
  42.399 +			razor_transaction_update_package(trans, package);
  42.400 +			matches++;
  42.401 +		}
  42.402 +	}
  42.403 +	razor_package_iterator_destroy(pi);
  42.404 +
  42.405 +	return matches;
  42.406 +}
  42.407 +
  42.408 +static int
  42.409 +mark_packages_for_removal(struct razor_transaction *trans,
  42.410 +			  struct razor_set *set, const char *pattern)
  42.411 +{
  42.412 +	struct razor_package_iterator *pi;
  42.413 +	struct razor_package *package;
  42.414 +	const char *name, *version, *arch;
  42.415 +	int matches = 0;
  42.416 +
  42.417 +	pi = razor_package_iterator_create(set);
  42.418 +	while (razor_package_iterator_next(pi, &package,
  42.419 +					   &name, &version, &arch)) {
  42.420 +		if (pattern && fnmatch(pattern, name, 0) == 0) {
  42.421 +			razor_transaction_remove_package(trans, package);
  42.422 +			matches++;
  42.423 +		}
  42.424 +	}
  42.425 +	razor_package_iterator_destroy(pi);
  42.426 +
  42.427 +	return matches;
  42.428 +}
  42.429 +
  42.430 +static int
  42.431 +command_update(int argc, const char *argv[])
  42.432 +{
  42.433 +	struct razor_set *set, *upstream;
  42.434 +	struct razor_transaction *trans;
  42.435 +	int i, errors;
  42.436 +
  42.437 +	set = razor_set_open(repo_filename);
  42.438 +	upstream = razor_set_open(rawhide_repo_filename);
  42.439 +	if (set == NULL || upstream == NULL)
  42.440 +		return 1;
  42.441 +
  42.442 +	trans = razor_transaction_create(set, upstream);
  42.443 +	if (argc == 0)
  42.444 +		razor_transaction_update_all(trans);
  42.445 +	for (i = 0; i < argc; i++) {
  42.446 +		if (mark_packages_for_update(trans, set, argv[i]) == 0) {
  42.447 +			fprintf(stderr, "no match for %s\n", argv[i]);
  42.448 +			return 1;
  42.449 +		}
  42.450 +	}
  42.451 +
  42.452 +	errors = razor_transaction_resolve(trans);
  42.453 +	if (errors)
  42.454 +		return 1;
  42.455 +
  42.456 +	set = razor_transaction_finish(trans);
  42.457 +	razor_set_write(set, updated_repo_filename, RAZOR_REPO_FILE_MAIN);
  42.458 +	razor_set_destroy(set);
  42.459 +	razor_set_destroy(upstream);
  42.460 +	printf("wrote system-updated.repo\n");
  42.461 +
  42.462 +	return 0;
  42.463 +}
  42.464 +
  42.465 +static int
  42.466 +command_remove(int argc, const char *argv[])
  42.467 +{
  42.468 +	struct razor_set *set, *upstream;
  42.469 +	struct razor_transaction *trans;
  42.470 +	int i, errors;
  42.471 +
  42.472 +	set = razor_set_open(repo_filename);
  42.473 +	if (set == NULL)
  42.474 +		return 1;
  42.475 +
  42.476 +	upstream = razor_set_create();
  42.477 +	trans = razor_transaction_create(set, upstream);
  42.478 +	for (i = 0; i < argc; i++) {
  42.479 +		if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
  42.480 +			fprintf(stderr, "no match for %s\n", argv[i]);
  42.481 +			return 1;
  42.482 +		}
  42.483 +	}
  42.484 +
  42.485 +	errors = razor_transaction_resolve(trans);
  42.486 +	if (errors)
  42.487 +		return 1;
  42.488 +
  42.489 +	set = razor_transaction_finish(trans);
  42.490 +	razor_set_write(set, updated_repo_filename, RAZOR_REPO_FILE_MAIN);
  42.491 +	razor_set_destroy(set);
  42.492 +	razor_set_destroy(upstream);
  42.493 +	printf("wrote system-updated.repo\n");
  42.494 +
  42.495 +	return 0;
  42.496 +}
  42.497 +
  42.498 +static void
  42.499 +print_diff(const char *name,
  42.500 +	   const char *old_version, const char *new_version, const char *arch,
  42.501 +	   void *data)
  42.502 +{
  42.503 +	if (old_version)
  42.504 +		printf("removing %s %s\n", name, old_version);
  42.505 +	else
  42.506 +		printf("install %s %s\n", name, new_version);
  42.507 +}
  42.508 +
  42.509 +static int
  42.510 +command_diff(int argc, const char *argv[])
  42.511 +{
  42.512 +	struct razor_set *set, *updated;
  42.513 +
  42.514 +	set = razor_set_open(repo_filename);
  42.515 +	updated = razor_set_open(updated_repo_filename);
  42.516 +	if (set == NULL || updated == NULL)
  42.517 +		return 1;
  42.518 +
  42.519 +	razor_set_diff(set, updated, print_diff, NULL);
  42.520 +
  42.521 +	razor_set_destroy(set);
  42.522 +	razor_set_destroy(updated);
  42.523 +
  42.524 +	return 0;
  42.525 +}
  42.526 +
  42.527 +static int
  42.528 +command_import_rpms(int argc, const char *argv[])
  42.529 +{
  42.530 +	DIR *dir;
  42.531 +	struct dirent *de;
  42.532 +	struct razor_importer *importer;
  42.533 +	struct razor_set *set;
  42.534 +	struct razor_rpm *rpm;
  42.535 +	int len;
  42.536 +	char filename[256];
  42.537 +	const char *dirname = argv[0];
  42.538 +
  42.539 +	if (dirname == NULL) {
  42.540 +		fprintf(stderr, "usage: razor import-rpms DIR\n");
  42.541 +		return -1;
  42.542 +	}
  42.543 +
  42.544 +	dir = opendir(dirname);
  42.545 +	if (dir == NULL) {
  42.546 +		fprintf(stderr, "couldn't read dir %s\n", dirname);
  42.547 +		return -1;
  42.548 +	}
  42.549 +
  42.550 +	importer = razor_importer_new();
  42.551 +
  42.552 +	while (de = readdir(dir), de != NULL) {
  42.553 +		len = strlen(de->d_name);
  42.554 +		if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
  42.555 +		    continue;
  42.556 +		snprintf(filename, sizeof filename,
  42.557 +			 "%s/%s", dirname, de->d_name);
  42.558 +		rpm = razor_rpm_open(filename);
  42.559 +		if (rpm == NULL) {
  42.560 +			fprintf(stderr,
  42.561 +				"failed to open rpm \"%s\"\n", filename);
  42.562 +			continue;
  42.563 +		}
  42.564 +		if (razor_importer_add_rpm(importer, rpm)) {
  42.565 +			fprintf(stderr, "couldn't import %s\n", filename);
  42.566 +			break;
  42.567 +		}
  42.568 +		razor_rpm_close(rpm);
  42.569 +	}
  42.570 +
  42.571 +	if (de != NULL) {
  42.572 +		razor_importer_destroy(importer);
  42.573 +		return -1;
  42.574 +	}
  42.575 +
  42.576 +	set = razor_importer_finish(importer);
  42.577 +
  42.578 +	razor_set_write(set, repo_filename, RAZOR_REPO_FILE_MAIN);
  42.579 +	razor_set_destroy(set);
  42.580 +	printf("wrote %s\n", repo_filename);
  42.581 +
  42.582 +	return 0;
  42.583 +}
  42.584 +
  42.585 +static void
  42.586 +download_package(const char *name,
  42.587 +		 const char *old_version,
  42.588 +		 const char *new_version,
  42.589 +		 const char *arch,
  42.590 +		 void *data)
  42.591 +{
  42.592 +	char file[PATH_MAX], url[256];
  42.593 +	const char *v;
  42.594 +	int *errors = data;
  42.595 +
  42.596 +	if (old_version)
  42.597 +		return;
  42.598 +
  42.599 +	/* Skip epoch */
  42.600 +	v = strchr(new_version, ':');
  42.601 +	if (v != NULL)
  42.602 +		v = v + 1;
  42.603 +	else
  42.604 +		v = new_version;
  42.605 +
  42.606 +	snprintf(url, sizeof url,
  42.607 +		 "%s/Packages/%s-%s.%s.rpm", yum_url, name, v, arch);
  42.608 +	snprintf(file, sizeof file,
  42.609 +		 "rpms/%s-%s.%s.rpm", name, v, arch);
  42.610 +	if (download_if_missing(url, file) < 0)
  42.611 +		(*errors)++;
  42.612 +}
  42.613 +
  42.614 +static void
  42.615 +install_package(const char *name,
  42.616 +		const char *old_version,
  42.617 +		const char *new_version,
  42.618 +		const char *arch,
  42.619 +		void *data)
  42.620 +{
  42.621 +	const char *v, *root = data;
  42.622 +	char file[PATH_MAX];
  42.623 +	struct razor_rpm *rpm;
  42.624 +
  42.625 +	if (old_version) {
  42.626 +		printf("removing %s %s not handled\n", name, old_version);
  42.627 +		return;
  42.628 +	}
  42.629 +
  42.630 +	/* Skip epoch */
  42.631 +	v = strchr(new_version, ':');
  42.632 +	if (v != NULL)
  42.633 +		v = v + 1;
  42.634 +	else
  42.635 +		v = new_version;
  42.636 +
  42.637 +	printf("install %s %s\n", name, v);
  42.638 +	snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
  42.639 +
  42.640 + 	rpm = razor_rpm_open(file);
  42.641 +	if (rpm == NULL) {
  42.642 +		fprintf(stderr, "failed to open rpm %s\n", file);
  42.643 +		return;
  42.644 +	}
  42.645 +	if (razor_rpm_install(rpm, root) < 0) {
  42.646 +		fprintf(stderr,
  42.647 +			"failed to install rpm %s\n", file);
  42.648 +		return;
  42.649 +	}
  42.650 +	razor_rpm_close(rpm);
  42.651 +}
  42.652 +
  42.653 +static int
  42.654 +command_install(int argc, const char *argv[])
  42.655 +{
  42.656 +	struct razor_root *root;
  42.657 +	struct razor_set *upstream, *next;
  42.658 +	struct razor_transaction *trans;
  42.659 +	int i = 0, errors, dependencies = 1;
  42.660 +
  42.661 +	if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
  42.662 +		dependencies = 0;
  42.663 +		i++;
  42.664 +	}
  42.665 +
  42.666 +	root = razor_root_open(install_root, RAZOR_ROOT_OPEN_WRITE);
  42.667 +	upstream = razor_set_open(rawhide_repo_filename);
  42.668 +	trans = razor_root_create_transaction(root, upstream);
  42.669 +
  42.670 +	for (; i < argc; i++) {
  42.671 +		if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
  42.672 +			fprintf(stderr, "no package matched %s\n", argv[i]);
  42.673 +			razor_root_close(root);
  42.674 +			return 1;
  42.675 +		}
  42.676 +	}
  42.677 +
  42.678 +	if (dependencies) {
  42.679 +		razor_transaction_resolve(trans);
  42.680 +		if (razor_transaction_describe(trans) > 0) {
  42.681 +			razor_root_close(root);
  42.682 +			return 1;
  42.683 +		}
  42.684 +	}
  42.685 +
  42.686 +	next = razor_transaction_finish(trans);
  42.687 +
  42.688 +	razor_root_update(root, next);
  42.689 +
  42.690 +	if (mkdir("rpms", 0777) && errno != EEXIST) {
  42.691 +		fprintf(stderr, "failed to create rpms directory.\n");
  42.692 +		razor_root_close(root);
  42.693 +		return 1;
  42.694 +	}
  42.695 +
  42.696 +	errors = 0;
  42.697 +	razor_root_diff(root, download_package, &errors);
  42.698 +	if (errors > 0) {
  42.699 +		fprintf(stderr, "failed to download %d packages\n", errors);
  42.700 +		razor_root_close(root);
  42.701 +                return 1;
  42.702 +        }
  42.703 +
  42.704 +	/* FIXME: We need to figure out the right install order here,
  42.705 +	 * so the post and pre scripts can run. */
  42.706 +	razor_root_diff(root, install_package, (void *) install_root);
  42.707 +
  42.708 +	razor_set_destroy(next);
  42.709 +	razor_set_destroy(upstream);
  42.710 +
  42.711 +	return razor_root_commit(root);
  42.712 +}
  42.713 +
  42.714 +static int
  42.715 +command_init(int argc, const char *argv[])
  42.716 +{
  42.717 +	return razor_root_create(install_root);
  42.718 +}
  42.719 +
  42.720 +static int
  42.721 +command_download(int argc, const char *argv[])
  42.722 +{
  42.723 +	struct razor_set *set;
  42.724 +	struct razor_package_iterator *pi;
  42.725 +	struct razor_package *package;
  42.726 +	const char *pattern = argv[0], *name, *version, *arch;
  42.727 +	char url[256], file[256];
  42.728 +	int matches = 0;
  42.729 +
  42.730 +	if (mkdir("rpms", 0777) && errno != EEXIST) {
  42.731 +		fprintf(stderr, "failed to create rpms directory.\n");
  42.732 +		return 1;
  42.733 +	}
  42.734 +
  42.735 +	set = razor_set_open(rawhide_repo_filename);
  42.736 +	pi = razor_package_iterator_create(set);
  42.737 +	while (razor_package_iterator_next(pi, &package,
  42.738 +					   &name, &version, &arch)) {
  42.739 +		if (pattern && fnmatch(pattern, name, 0) != 0)
  42.740 +			continue;
  42.741 +
  42.742 +		matches++;
  42.743 +		snprintf(url, sizeof url,
  42.744 +			 "%s/Packages/%s-%s.%s.rpm",
  42.745 +			 yum_url, name, version, arch);
  42.746 +		snprintf(file, sizeof file,
  42.747 +			 "rpms/%s-%s.%s.rpm", name, version, arch);
  42.748 +		download_if_missing(url, file);
  42.749 +	}
  42.750 +	razor_package_iterator_destroy(pi);
  42.751 +	razor_set_destroy(set);
  42.752 +
  42.753 +	if (matches == 0)
  42.754 +		fprintf(stderr, "no packages matched \"%s\"\n", pattern);
  42.755 +	else if (matches == 1)
  42.756 +		fprintf(stderr, "downloaded 1 package\n");
  42.757 +	else
  42.758 +		fprintf(stderr, "downloaded %d packages\n", matches);
  42.759 +
  42.760 +	return 0;
  42.761 +}
  42.762 +
  42.763 +static int
  42.764 +command_info(int argc, const char *argv[])
  42.765 +{
  42.766 +	struct razor_set *set;
  42.767 +	struct razor_package_iterator *pi;
  42.768 +	struct razor_package *package;
  42.769 +	const char *pattern = argv[0], *name, *version, *arch;
  42.770 +	const char *summary, *description, *url, *license;
  42.771 +
  42.772 +	set = razor_set_open(repo_filename);
  42.773 +	razor_set_open_details(set, "system-details.repo");
  42.774 +	pi = razor_package_iterator_create(set);
  42.775 +	while (razor_package_iterator_next(pi, &package,
  42.776 +					   &name, &version, &arch)) {
  42.777 +		if (pattern && fnmatch(pattern, name, 0) != 0)
  42.778 +			continue;
  42.779 +
  42.780 +		razor_package_get_details (set, package, &summary, &description,
  42.781 +					   &url, &license);
  42.782 +
  42.783 +		printf ("Name:        %s\n", name);
  42.784 +		printf ("Arch:        %s\n", arch);
  42.785 +		printf ("Version:     %s\n", version);
  42.786 +		printf ("URL:         %s\n", url);
  42.787 +		printf ("License:     %s\n", license);
  42.788 +		printf ("Summary:     %s\n", summary);
  42.789 +		printf ("Description:\n");
  42.790 +		printf ("%s\n", description);
  42.791 +		printf ("\n");
  42.792 +	}
  42.793 +	razor_package_iterator_destroy(pi);
  42.794 +	razor_set_destroy(set);
  42.795 +
  42.796 +	return 0;
  42.797 +}
  42.798 +
  42.799 +static struct {
  42.800 +	const char *name;
  42.801 +	const char *description;
  42.802 +	int (*func)(int argc, const char *argv[]);
  42.803 +} razor_commands[] = {
  42.804 +	{ "list", "list all packages", command_list },
  42.805 +	{ "list-requires", "list all requires for the given package", command_list_requires },
  42.806 +	{ "list-provides", "list all provides for the given package", command_list_provides },
  42.807 +	{ "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
  42.808 +	{ "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
  42.809 +	{ "list-files", "list files for package set", command_list_files },
  42.810 +	{ "list-file-packages", "list packages owning file", command_list_file_packages },
  42.811 +	{ "list-package-files", "list files in package", command_list_package_files },
  42.812 +	{ "what-requires", "list the packages that have the given requires", command_what_requires },
  42.813 +	{ "what-provides", "list the packages that have the given provides", command_what_provides },
  42.814 +	{ "import-yum", "import yum metadata files", command_import_yum },
  42.815 +	{ "import-rpmdb", "import the system rpm database", command_import_rpmdb },
  42.816 +	{ "import-rpms", "import rpms from the given directory", command_import_rpms },
  42.817 +	{ "update", "update all or specified packages", command_update },
  42.818 +	{ "remove", "remove specified packages", command_remove },
  42.819 +	{ "diff", "show diff between two package sets", command_diff },
  42.820 +	{ "install", "install rpm", command_install },
  42.821 +	{ "init", "init razor root", command_init },
  42.822 +	{ "download", "download packages", command_download },
  42.823 +	{ "info", "display package details", command_info }
  42.824 +};
  42.825 +
  42.826 +static int
  42.827 +usage(void)
  42.828 +{
  42.829 +	int i;
  42.830 +
  42.831 +	printf("usage:\n");
  42.832 +	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  42.833 +		printf("  %-20s%s\n",
  42.834 +		       razor_commands[i].name, razor_commands[i].description);
  42.835 +
  42.836 +	return 1;
  42.837 +}
  42.838 +
  42.839 +int
  42.840 +main(int argc, const char *argv[])
  42.841 +{
  42.842 +	char *repo;
  42.843 +	int i;
  42.844 +
  42.845 +	repo = getenv("RAZOR_REPO");
  42.846 +	if (repo != NULL)
  42.847 +		repo_filename = repo;
  42.848 +
  42.849 +	yum_url = getenv("YUM_URL");
  42.850 +	if (yum_url == NULL)
  42.851 +		yum_url = YUM_URL;
  42.852 +
  42.853 +	if (argc < 2)
  42.854 +		return usage();
  42.855 +
  42.856 +	for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
  42.857 +		if (strcmp(razor_commands[i].name, argv[1]) == 0)
  42.858 +			return razor_commands[i].func(argc - 2, argv + 2);
  42.859 +
  42.860 +	return usage();
  42.861 +}
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/src/rpm.c	Fri Jun 20 19:04:47 2008 -0400
    43.3 @@ -0,0 +1,895 @@
    43.4 +/*
    43.5 + * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    43.6 + * Copyright (C) 2008  Red Hat, Inc
    43.7 + *
    43.8 + * This program is free software; you can redistribute it and/or modify
    43.9 + * it under the terms of the GNU General Public License as published by
   43.10 + * the Free Software Foundation; either version 2 of the License, or
   43.11 + * (at your option) any later version.
   43.12 + *
   43.13 + * This program is distributed in the hope that it will be useful,
   43.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   43.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   43.16 + * GNU General Public License for more details.
   43.17 + *
   43.18 + * You should have received a copy of the GNU General Public License along
   43.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
   43.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   43.21 + */
   43.22 +
   43.23 +#include <stdlib.h>
   43.24 +#include <string.h>
   43.25 +#include <stdio.h>
   43.26 +#include <stdint.h>
   43.27 +#include <dirent.h>
   43.28 +#include "razor.h"
   43.29 +
   43.30 +enum option_type {
   43.31 +	OPTION_LAST,
   43.32 +	OPTION_GROUP,
   43.33 +	OPTION_BOOL,
   43.34 +	OPTION_STRING
   43.35 +};
   43.36 +
   43.37 +struct option {
   43.38 +	enum option_type type;
   43.39 +	const char *name;
   43.40 +	char short_name;
   43.41 +	const char *arg_name;
   43.42 +	const char *description;
   43.43 +	void *data;
   43.44 +};
   43.45 +
   43.46 +/* A note about all these options: rpm allows options to mean
   43.47 + * different things depending on what other options are present on the
   43.48 + * command line.  For example, if -q or --query is present, -i no
   43.49 + * longer means install, but info.  The way we handle this is by
   43.50 + * setting all the options that may match (ie if -i is given we set
   43.51 + * install and info), and then look at the relevent one depending on
   43.52 + * what else in on the command line. */
   43.53 +
   43.54 +static int option_all, option_whatrequires, option_whatprovides;
   43.55 +static int option_package;
   43.56 +
   43.57 +static const struct option query_options[] = {
   43.58 +	{ OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
   43.59 +	{ OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
   43.60 +	{ OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
   43.61 +	{ OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
   43.62 +	{ OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
   43.63 +	{ OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
   43.64 +	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   43.65 +	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   43.66 +	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   43.67 +	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   43.68 +	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   43.69 +	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   43.70 +	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   43.71 +	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   43.72 +	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
   43.73 +	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   43.74 +	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   43.75 +	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   43.76 +	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
   43.77 +	{ }
   43.78 +};
   43.79 +
   43.80 +static int option_nodeps;
   43.81 +
   43.82 +static const struct option verify_options[] = {
   43.83 +	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
   43.84 +	{ OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
   43.85 +	{ OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", &option_nodeps },
   43.86 +	{ OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
   43.87 +	{ OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
   43.88 +	{ OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
   43.89 +	{ OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
   43.90 +	{ OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
   43.91 +	{ OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
   43.92 +	{ OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
   43.93 +	{ OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
   43.94 +	{ OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
   43.95 +	{ OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
   43.96 +	{ OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
   43.97 +	{ OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
   43.98 +	{ OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
   43.99 +	{ OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
  43.100 +	{ }
  43.101 +};
  43.102 +
  43.103 +static const struct option ftw_options[] = {
  43.104 +	{ OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
  43.105 +	{ OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
  43.106 +	{ OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
  43.107 +	{ OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
  43.108 +	{ OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
  43.109 +	{ OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
  43.110 +	{ OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
  43.111 +	{ OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
  43.112 +	{ }
  43.113 +};
  43.114 +
  43.115 +static const struct option signature_options[] = {
  43.116 +	{ OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
  43.117 +	{ OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
  43.118 +	{ OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
  43.119 +	{ OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
  43.120 +	{ OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
  43.121 +	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  43.122 +	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
  43.123 +	{ }
  43.124 +};
  43.125 +
  43.126 +static int option_initdb;
  43.127 +
  43.128 +static const struct option database_options[] = {
  43.129 +	{ OPTION_BOOL, "initdb", 0, NULL, "initialize database", &option_initdb },
  43.130 +	{ OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
  43.131 +	{ }
  43.132 +};
  43.133 +
  43.134 +static int option_erase, option_install, option_upgrade, option_justdb;
  43.135 +static int option_test;
  43.136 +
  43.137 +static const struct option install_options[] = {
  43.138 +	{ OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
  43.139 +	{ OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
  43.140 +	{ OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
  43.141 +	{ OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
  43.142 +	{ OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
  43.143 +	{ OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
  43.144 +	{ OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
  43.145 +	{ OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
  43.146 +	{ OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
  43.147 +	{ OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
  43.148 +	{ OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
  43.149 +	{ OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
  43.150 +	{ OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
  43.151 +	{ OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
  43.152 +	{ OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
  43.153 +	{ OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", &option_justdb, },
  43.154 +	{ OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", &option_nodeps, },
  43.155 +	{ OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
  43.156 +	{ OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
  43.157 +	{ OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
  43.158 +	{ OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
  43.159 +	{ OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
  43.160 +	{ OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
  43.161 +	{ OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
  43.162 +	{ OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
  43.163 +	{ OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
  43.164 +	{ OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
  43.165 +	{ OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
  43.166 +	{ OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
  43.167 +	{ OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
  43.168 +	{ OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", &option_test },
  43.169 +	{ OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
  43.170 +	{ }
  43.171 +};
  43.172 +
  43.173 +static int option_version;
  43.174 +static const char *option_root = "install";
  43.175 +
  43.176 +static const struct option common_options[] = {
  43.177 +	{ OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
  43.178 +	{ OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
  43.179 +	{ OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  43.180 +	{ OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
  43.181 +	{ OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
  43.182 +	{ OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
  43.183 +	{ OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", &option_root },
  43.184 +	{ OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
  43.185 +	{ OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
  43.186 +	{ OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
  43.187 +	{ OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
  43.188 +	{ OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
  43.189 +	{ }
  43.190 +};
  43.191 +
  43.192 +static int option_conflicts, option_obsoletes, option_requires;
  43.193 +static int option_provides, option_info, option_changelog;
  43.194 +
  43.195 +static const struct option alias_options[] = {
  43.196 +	{ OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
  43.197 +	{ OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
  43.198 +	{ OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
  43.199 +	{ OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
  43.200 +	{ OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
  43.201 +	{ OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
  43.202 +	{ OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
  43.203 +	{ OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
  43.204 +	{ OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
  43.205 +	{ OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
  43.206 +	{ OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
  43.207 +	{ OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
  43.208 +	{ OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
  43.209 +	{ OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
  43.210 +	{ OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
  43.211 +	{ OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
  43.212 +	{ OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
  43.213 +	{ OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
  43.214 +	{ OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
  43.215 +	{ OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
  43.216 +	{ OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
  43.217 +	{ OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
  43.218 +	{ OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
  43.219 +	{ OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
  43.220 +	{ OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
  43.221 +	{ OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
  43.222 +	{ }
  43.223 +};
  43.224 +
  43.225 +static int option_help, option_usage;
  43.226 +
  43.227 +static const struct option help_options[] = {
  43.228 +	{ OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
  43.229 +	{ OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
  43.230 +	{ }
  43.231 +};
  43.232 +
  43.233 +static int option_query, option_verify;
  43.234 +
  43.235 +static const struct option rpm_options[] = {
  43.236 +	{ OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
  43.237 +	{ OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
  43.238 +	{ OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
  43.239 +	{ OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
  43.240 +	{ OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
  43.241 +	{ OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
  43.242 +	{ OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
  43.243 +	{ OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
  43.244 +	{ OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
  43.245 +	{ OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
  43.246 +	{ OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
  43.247 +	{ }
  43.248 +};
  43.249 +
  43.250 +static const char system_repo_filename[] = "system.repo";
  43.251 +static const char *repo_filename = system_repo_filename;
  43.252 +
  43.253 +static void
  43.254 +command_initdb(int argc, const char *argv[])
  43.255 +{
  43.256 +	razor_root_create(option_root);
  43.257 +}
  43.258 +
  43.259 +static struct razor_property *
  43.260 +add_property_packages(struct razor_set *set,
  43.261 +		      struct razor_package_query *query,
  43.262 +		      const char *ref_name,
  43.263 +		      const char *ref_version,
  43.264 +		      uint32_t ref_type)
  43.265 +{
  43.266 +	struct razor_property *property;
  43.267 +	struct razor_property_iterator *pi;
  43.268 +	struct razor_package_iterator *pkgi;
  43.269 +	const char *name, *version;
  43.270 +	uint32_t flags;
  43.271 +
  43.272 +	pi = razor_property_iterator_create(set, NULL);
  43.273 +	while (razor_property_iterator_next(pi, &property, &name,
  43.274 +					    &flags, &version)) {
  43.275 +		if (strcmp(ref_name, name) != 0)
  43.276 +			continue;
  43.277 +		if (ref_version &&
  43.278 +		    (flags & RAZOR_PROPERTY_RELATION_MASK) == RAZOR_PROPERTY_EQUAL &&
  43.279 +		    strcmp(ref_version, version) != 0)
  43.280 +			continue;
  43.281 +		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != ref_type)
  43.282 +			continue;
  43.283 +
  43.284 +		pkgi = razor_package_iterator_create_for_property(set,
  43.285 +								  property);
  43.286 +		razor_package_query_add_iterator(query, pkgi);
  43.287 +		razor_package_iterator_destroy(pkgi);
  43.288 +	}
  43.289 +	razor_property_iterator_destroy(pi);
  43.290 +
  43.291 +	return property;
  43.292 +}
  43.293 +
  43.294 +static int
  43.295 +strcmpp(const void *p1, const void *p2)
  43.296 +{
  43.297 +	return strcmp(*(char * const *) p1, *(char * const *) p2);
  43.298 +}
  43.299 +
  43.300 +static void
  43.301 +add_command_line_packages(struct razor_set *set,
  43.302 +			  struct razor_package_query *query,
  43.303 +			  int argc, const char **argv)
  43.304 +{
  43.305 +	struct razor_package *package;
  43.306 +	struct razor_package_iterator *pi;
  43.307 +	const char *name, *version, *arch;
  43.308 +	int i, cmp, errors;
  43.309 +
  43.310 +	qsort(argv, argc, sizeof(*argv), strcmpp);
  43.311 +	i = 0;
  43.312 +	errors = 0;
  43.313 +
  43.314 +	pi = razor_package_iterator_create(set);
  43.315 +
  43.316 +	while (razor_package_iterator_next(pi, &package,
  43.317 +					   &name, &version, &arch)) {
  43.318 +		while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
  43.319 +			fprintf(stderr, "error: package %s is not installed\n",
  43.320 +				argv[i]);
  43.321 +			errors++;
  43.322 +			i++;
  43.323 +		}
  43.324 +
  43.325 +		if (cmp == 0) {
  43.326 +			razor_package_query_add_package(query, package);
  43.327 +			i++;
  43.328 +		}
  43.329 +	}
  43.330 +
  43.331 +	razor_package_iterator_destroy(pi);
  43.332 +
  43.333 +	if (errors)
  43.334 +		exit(1);
  43.335 +}
  43.336 +
  43.337 +static struct razor_package_iterator *
  43.338 +get_query_packages(struct razor_set *set, int argc, const char *argv[])
  43.339 +{
  43.340 +	struct razor_package_query *query;
  43.341 +	struct razor_package_iterator *pi;
  43.342 +	int i;
  43.343 +
  43.344 +	if (option_all + option_whatprovides + option_whatrequires > 1) {
  43.345 +		printf("only one type of query/verify "
  43.346 +		       "may be performed at a time\n");
  43.347 +		exit(1);
  43.348 +	}
  43.349 +
  43.350 +	query = razor_package_query_create(set);
  43.351 +
  43.352 +	if (option_all) {
  43.353 +		pi = razor_package_iterator_create(set);
  43.354 +		razor_package_query_add_iterator(query, pi);
  43.355 +		razor_package_iterator_destroy(pi);
  43.356 +	} else if (option_whatrequires) {
  43.357 +		for (i = 0; i < argc; i++)
  43.358 +			add_property_packages(set, query,
  43.359 +					      argv[i], NULL,
  43.360 +					      RAZOR_PROPERTY_REQUIRES);
  43.361 +	} else if (option_whatprovides) {
  43.362 +		for (i = 0; i < argc; i++)
  43.363 +			add_property_packages(set, query,
  43.364 +					      argv[i], NULL,
  43.365 +					      RAZOR_PROPERTY_PROVIDES);
  43.366 +	} else if (argc > 0) {
  43.367 +		add_command_line_packages(set, query, argc, argv);
  43.368 +	} else {
  43.369 +		printf("no arguments given for query/verify\n");
  43.370 +		exit(1);
  43.371 +	}
  43.372 +
  43.373 +	return razor_package_query_finish(query);
  43.374 +}
  43.375 +
  43.376 +static void
  43.377 +print_package_properties(struct razor_set *set,
  43.378 +			 struct razor_package *package,
  43.379 +			 uint32_t ref_type)
  43.380 +{
  43.381 +	struct razor_property *property;
  43.382 +	struct razor_property_iterator *pi;
  43.383 +	const char *name, *version;
  43.384 +	uint32_t flags;
  43.385 +
  43.386 +	pi = razor_property_iterator_create(set, package);
  43.387 +	while (razor_property_iterator_next(pi, &property,
  43.388 +					    &name, &flags, &version)) {
  43.389 +		if ((flags & RAZOR_PROPERTY_TYPE_MASK) != ref_type)
  43.390 +			continue;
  43.391 +		if (version[0] == '\0')
  43.392 +			printf("%s\n", name);
  43.393 +		else
  43.394 +			printf("%s %s %s\n", name,
  43.395 +			       razor_property_relation_to_string(property),
  43.396 +			       version);
  43.397 +	}
  43.398 +	razor_property_iterator_destroy(pi);
  43.399 +}
  43.400 +
  43.401 +static void
  43.402 +print_package_info(struct razor_set *set, struct razor_package *package)
  43.403 +{
  43.404 +	printf("FIXME: Package info not tracked.\n");
  43.405 +}
  43.406 +
  43.407 +static void
  43.408 +print_package_changelog(struct razor_set *set, struct razor_package *package)
  43.409 +{
  43.410 +	printf("FIXME: Package changelog not tracked.\n");
  43.411 +}
  43.412 +
  43.413 +static struct razor_set *
  43.414 +create_set_from_command_line(int argc, const char *argv[])
  43.415 +{
  43.416 +	struct razor_importer *importer;
  43.417 +	struct razor_rpm *rpm;
  43.418 +	int i;
  43.419 +
  43.420 +	importer = razor_importer_new();
  43.421 +
  43.422 +	for (i = 0; i < argc; i++) {
  43.423 +		rpm = razor_rpm_open(argv[i]);
  43.424 +		if (rpm == NULL)
  43.425 +			continue;
  43.426 +		if (razor_importer_add_rpm(importer, rpm))
  43.427 +			printf("couldn't import %s\n", argv[i]);
  43.428 +
  43.429 +		razor_rpm_close(rpm);
  43.430 +	}
  43.431 +
  43.432 +	return razor_importer_finish(importer);
  43.433 +}
  43.434 +
  43.435 +static void
  43.436 +command_query(int argc, const char *argv[])
  43.437 +{
  43.438 +	struct razor_set *set;
  43.439 +	struct razor_package_iterator *pi;
  43.440 +	struct razor_package *package;
  43.441 +	const char *name, *version, *arch;
  43.442 +
  43.443 +	if (option_package) {
  43.444 +		set = create_set_from_command_line(argc, argv);
  43.445 +		argc = 0;
  43.446 +		option_all = 1;
  43.447 +	} else {
  43.448 +		set = razor_root_open_read_only(option_root);
  43.449 +	}
  43.450 +
  43.451 +	pi = get_query_packages(set, argc, argv);
  43.452 +
  43.453 +	while (razor_package_iterator_next(pi, &package,
  43.454 +					   &name, &version, &arch)) {
  43.455 +		if (option_conflicts)
  43.456 +			print_package_properties(set, package,
  43.457 +						 RAZOR_PROPERTY_CONFLICTS);
  43.458 +		if (option_obsoletes)
  43.459 +			print_package_properties(set, package,
  43.460 +						 RAZOR_PROPERTY_OBSOLETES);
  43.461 +		if (option_requires)
  43.462 +			print_package_properties(set, package,
  43.463 +						 RAZOR_PROPERTY_REQUIRES);
  43.464 +		if (option_provides)
  43.465 +			print_package_properties(set, package,
  43.466 +						 RAZOR_PROPERTY_PROVIDES);
  43.467 +		if (option_info)
  43.468 +			print_package_info(set, package);
  43.469 +		if (option_changelog)
  43.470 +			print_package_changelog(set, package);
  43.471 +
  43.472 +		if (option_conflicts + option_obsoletes +
  43.473 +		    option_requires + option_provides +
  43.474 +		    option_info + option_changelog == 0)
  43.475 +			printf("%s-%s.%s\n", name, version, arch);
  43.476 +	}
  43.477 +
  43.478 +	razor_package_iterator_destroy(pi);
  43.479 +
  43.480 +	razor_set_destroy(set);
  43.481 +
  43.482 +	return;
  43.483 +}
  43.484 +
  43.485 +static void
  43.486 +command_verify(int argc, const char *argv[])
  43.487 +{
  43.488 +	struct razor_set *set;
  43.489 +	struct razor_package_iterator *pi;
  43.490 +	struct razor_package *package;
  43.491 +	const char *name, *version, *arch;
  43.492 +
  43.493 +	if (option_package) {
  43.494 +		set = create_set_from_command_line(argc, argv);
  43.495 +		argc = 0;
  43.496 +		option_all = 1;
  43.497 +	} else {
  43.498 +		set = razor_root_open_read_only(option_root);
  43.499 +	}
  43.500 +
  43.501 +	pi = get_query_packages(set, argc, argv);
  43.502 +
  43.503 +	while (razor_package_iterator_next(pi, &package,
  43.504 +					   &name, &version, &arch)) {
  43.505 +		printf("verify %s-%s.%s - not implemented\n",
  43.506 +		       name, version, arch);
  43.507 +	}
  43.508 +
  43.509 +	razor_package_iterator_destroy(pi);
  43.510 +}
  43.511 +
  43.512 +static void
  43.513 +remove_package(const char *name,
  43.514 +	       const char *old_version, const char *new_version,
  43.515 +	       const char *arch, void *data)
  43.516 +{
  43.517 +	if (old_version)
  43.518 +		printf("remove %s-%s.%s\n", name, old_version, arch);
  43.519 +}
  43.520 +
  43.521 +static void
  43.522 +command_erase(int argc, const char *argv[])
  43.523 +{
  43.524 +	struct razor_set *set, *upstream, *next;
  43.525 +	struct razor_transaction *trans;
  43.526 +	struct razor_package_query *query;
  43.527 +	struct razor_package_iterator *pi;
  43.528 +	struct razor_package *package;
  43.529 +	const char *name, *version, *arch;
  43.530 +
  43.531 +	if (argc == 0) {
  43.532 +		printf("no packages given for erase\n");
  43.533 +		exit(1);
  43.534 +	}
  43.535 +
  43.536 +	set = razor_set_open(repo_filename);
  43.537 +	upstream = razor_set_create();
  43.538 +
  43.539 +	trans = razor_transaction_create(set, upstream);
  43.540 +
  43.541 +	query = razor_package_query_create(set);
  43.542 +	add_command_line_packages(set, query, argc, argv);
  43.543 +
  43.544 +	pi = razor_package_query_finish(query);
  43.545 +	while (razor_package_iterator_next(pi, &package,
  43.546 +					   &name, &version, &arch))
  43.547 +		razor_transaction_remove_package(trans, package);
  43.548 +	razor_package_iterator_destroy(pi);
  43.549 +
  43.550 +	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  43.551 +		printf("unsatisfied dependencies.\n");
  43.552 +		exit(1);
  43.553 +	}
  43.554 +
  43.555 +	if (option_test)
  43.556 +		exit(0);
  43.557 +
  43.558 +	next = razor_transaction_finish(trans);
  43.559 +
  43.560 +	if (!option_justdb)
  43.561 +		razor_set_diff(set, next, remove_package, NULL);
  43.562 +
  43.563 +	razor_set_destroy(set);
  43.564 +	razor_set_destroy(upstream);
  43.565 +
  43.566 +	razor_set_destroy(next);
  43.567 +}
  43.568 +
  43.569 +static void
  43.570 +install_package(const char *name,
  43.571 +		const char *old_version, const char *new_version,
  43.572 +		const char *arch, void *data)
  43.573 +{
  43.574 +	if (new_version)
  43.575 +		printf("install %s-%s.%s\n", name, new_version, arch);
  43.576 +}
  43.577 +
  43.578 +static void
  43.579 +command_install(int argc, const char *argv[])
  43.580 +{
  43.581 +	struct razor_set *set, *upstream, *next;
  43.582 +	struct razor_transaction *trans;
  43.583 +	struct razor_package_iterator *pi;
  43.584 +	struct razor_package *package;
  43.585 +	const char *name, *version, *arch;
  43.586 +
  43.587 +	if (argc == 0) {
  43.588 +		printf("no packages given for install\n");
  43.589 +		exit(1);
  43.590 +	}
  43.591 +
  43.592 +	set = razor_set_open(repo_filename);
  43.593 +	upstream = create_set_from_command_line(argc, argv);
  43.594 +
  43.595 +	trans = razor_transaction_create(set, upstream);
  43.596 +
  43.597 +	pi = razor_package_iterator_create(upstream);
  43.598 +	while (razor_package_iterator_next(pi, &package,
  43.599 +					   &name, &version, &arch))
  43.600 +		razor_transaction_install_package(trans, package);
  43.601 +	razor_package_iterator_destroy(pi);
  43.602 +
  43.603 +	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  43.604 +		printf("unsatisfied dependencies.\n");
  43.605 +		exit(1);
  43.606 +	}
  43.607 +
  43.608 +	if (option_test)
  43.609 +		exit(0);
  43.610 +
  43.611 +	next = razor_transaction_finish(trans);
  43.612 +
  43.613 +	if (!option_justdb)
  43.614 +		razor_set_diff(set, next, install_package, NULL);
  43.615 +
  43.616 +	razor_set_destroy(set);
  43.617 +	razor_set_destroy(upstream);
  43.618 +
  43.619 +	razor_set_destroy(next);
  43.620 +}
  43.621 +
  43.622 +static void
  43.623 +update_package(const char *name,
  43.624 +	       const char *old_version, const char *new_version,
  43.625 +	       const char *arch, void *data)
  43.626 +{
  43.627 +	if (old_version)
  43.628 +		printf("remove %s-%s.%s\n", name, old_version, arch);
  43.629 +	if (new_version)
  43.630 +		printf("install %s-%s.%s\n", name, new_version, arch);
  43.631 +}
  43.632 +
  43.633 +static void
  43.634 +command_update(int argc, const char *argv[])
  43.635 +{
  43.636 +	struct razor_set *set, *upstream, *next;
  43.637 +	struct razor_transaction *trans;
  43.638 +	struct razor_package_iterator *pi;
  43.639 +	struct razor_package *package;
  43.640 +	const char *name, *version, *arch;
  43.641 +
  43.642 +	if (argc == 0) {
  43.643 +		printf("no packages given for update\n");
  43.644 +		exit(1);
  43.645 +	}
  43.646 +
  43.647 +	set = razor_set_open(repo_filename);
  43.648 +	upstream = create_set_from_command_line(argc, argv);
  43.649 +
  43.650 +	trans = razor_transaction_create(set, upstream);
  43.651 +
  43.652 +	pi = razor_package_iterator_create(upstream);
  43.653 +	while (razor_package_iterator_next(pi, &package,
  43.654 +					   &name, &version, &arch))
  43.655 +		razor_transaction_update_package(trans, package);
  43.656 +	razor_package_iterator_destroy(pi);
  43.657 +
  43.658 +	if (!option_nodeps && razor_transaction_describe(trans) > 0) {
  43.659 +		printf("unsatisfied dependencies.\n");
  43.660 +		exit(1);
  43.661 +	}
  43.662 +
  43.663 +	if (option_test)
  43.664 +		exit(0);
  43.665 +
  43.666 +	next = razor_transaction_finish(trans);
  43.667 +
  43.668 +	if (!option_justdb)
  43.669 +		razor_set_diff(set, next, update_package, NULL);
  43.670 +
  43.671 +	razor_set_destroy(set);
  43.672 +	razor_set_destroy(upstream);
  43.673 +
  43.674 +	razor_set_destroy(next);
  43.675 +}
  43.676 +
  43.677 +static int
  43.678 +for_each_option(const struct option *options,
  43.679 +		const char *name, char short_name,
  43.680 +		void (*fn)(const struct option *o,
  43.681 +			   const char *name, char short_name,
  43.682 +			   void *data), void *data)
  43.683 +{
  43.684 +	int i, count = 0;
  43.685 +
  43.686 +	for (i = 0; options[i].type != OPTION_LAST; i++) {
  43.687 +		switch (options[i].type) {
  43.688 +		case OPTION_GROUP:
  43.689 +			count += for_each_option(options[i].data,
  43.690 +						 name, short_name, fn, data);
  43.691 +			break;
  43.692 +
  43.693 +		case OPTION_BOOL:
  43.694 +		case OPTION_STRING:
  43.695 +			if (name && strcmp(options[i].name, name) == 0) {
  43.696 +				fn(&options[i], name, 0, data);
  43.697 +				count++;
  43.698 +				break;
  43.699 +			}
  43.700 +
  43.701 +			if (short_name &&
  43.702 +			    short_name == options[i].short_name) {
  43.703 +				fn(&options[i], NULL, short_name, data);
  43.704 +				count++;
  43.705 +				break;
  43.706 +			}
  43.707 +			break;
  43.708 +
  43.709 +		case OPTION_LAST:
  43.710 +			break;
  43.711 +		}
  43.712 +	}
  43.713 +
  43.714 +	return count;
  43.715 +}
  43.716 +
  43.717 +static void
  43.718 +handle_option(const struct option *o,
  43.719 +	      const char *name, char short_name, void *data)
  43.720 +{
  43.721 +	if (o->data == NULL) {
  43.722 +		if (name)
  43.723 +			printf("option --%s not supported\n", name);
  43.724 +		else
  43.725 +			printf("option -%c not supported\n", short_name);
  43.726 +		return;
  43.727 +	}
  43.728 +
  43.729 +	switch (o->type) {
  43.730 +	case OPTION_BOOL:
  43.731 +		*(int *) o->data = 1;
  43.732 +		break;
  43.733 +
  43.734 +	case OPTION_STRING:
  43.735 +		*(const char **) o->data = name + strlen(o->name) + 1;
  43.736 +		break;
  43.737 +
  43.738 +	case OPTION_LAST:
  43.739 +	case OPTION_GROUP:
  43.740 +		/* Shouldn't happen. */
  43.741 +		break;
  43.742 +	}
  43.743 +}
  43.744 +
  43.745 +static int
  43.746 +parse_options(const struct option *options, int argc, const char **argv)
  43.747 +{
  43.748 +	int i, j, k;
  43.749 +
  43.750 +	for (i = 1, j = 0; i < argc; i++) {
  43.751 +		if (argv[i][0] != '-') {
  43.752 +			argv[j++] = argv[i];
  43.753 +			continue;
  43.754 +		}
  43.755 +
  43.756 +		if (argv[i][1] == '-') {
  43.757 +			if (for_each_option(options, &argv[i][2], 0,
  43.758 +					    handle_option, NULL) == 0) {
  43.759 +				printf("unknown option: %s\n", argv[i]);
  43.760 +				exit(1);
  43.761 +			}
  43.762 +			continue;
  43.763 +		}
  43.764 +
  43.765 +		for (k = 1; argv[i][k]; k++) {
  43.766 +			if (for_each_option(options, NULL, argv[i][k],
  43.767 +					    handle_option, NULL) == 0) {
  43.768 +				printf("unknown option: -%c\n", argv[i][k]);
  43.769 +				exit(1);
  43.770 +			}
  43.771 +		}
  43.772 +	}
  43.773 +
  43.774 +	return j;
  43.775 +}
  43.776 +
  43.777 +static void
  43.778 +print_options_help(const struct option *options)
  43.779 +{
  43.780 +	int i;
  43.781 +
  43.782 +	for (i = 0; options[i].type != OPTION_LAST; i++) {
  43.783 +		switch (options[i].type) {
  43.784 +		case OPTION_GROUP:
  43.785 +			printf("%s\n", options[i].description);
  43.786 +			print_options_help(options[i].data);
  43.787 +			printf("\n");
  43.788 +			break;
  43.789 +
  43.790 +		case OPTION_BOOL:
  43.791 +		case OPTION_STRING:
  43.792 +			printf("  ");
  43.793 +			if (options[i].short_name)
  43.794 +				printf("-%c", options[i].short_name);
  43.795 +			if (options[i].short_name && options[i].name)
  43.796 +				printf(", ");
  43.797 +			if (options[i].name)
  43.798 +				printf("--%s", options[i].name);
  43.799 +			if (options[i].arg_name)
  43.800 +				printf("=%s", options[i].arg_name);
  43.801 +			if (options[i].description)
  43.802 +				printf("\t\t%s", options[i].description);
  43.803 +			printf("\n");
  43.804 +			break;
  43.805 +
  43.806 +		case OPTION_LAST:
  43.807 +			break;
  43.808 +		}
  43.809 +	}
  43.810 +}
  43.811 +
  43.812 +static void
  43.813 +print_options_usage(const struct option *options)
  43.814 +{
  43.815 +	int i;
  43.816 +
  43.817 +	for (i = 0; options[i].type != OPTION_LAST; i++) {
  43.818 +		switch (options[i].type) {
  43.819 +		case OPTION_GROUP:
  43.820 +			print_options_usage(options[i].data);
  43.821 +			break;
  43.822 +
  43.823 +		case OPTION_BOOL:
  43.824 +			printf("[");
  43.825 +			if (options[i].short_name)
  43.826 +				printf("-%c", options[i].short_name);
  43.827 +			if (options[i].short_name && options[i].name)
  43.828 +				printf("|");
  43.829 +			if (options[i].name)
  43.830 +				printf("--%s", options[i].name);
  43.831 +			printf("] ");
  43.832 +			break;
  43.833 +
  43.834 +		case OPTION_STRING:
  43.835 +			printf("[");
  43.836 +			if (options[i].short_name)
  43.837 +				printf("-%c", options[i].short_name);
  43.838 +			if (options[i].short_name && options[i].name)
  43.839 +				printf("|");
  43.840 +			if (options[i].name)
  43.841 +				printf("--%s", options[i].name);
  43.842 +			if (options[i].arg_name)
  43.843 +				printf("=%s", options[i].arg_name);
  43.844 +			printf("] ");
  43.845 +			break;
  43.846 +
  43.847 +
  43.848 +			break;
  43.849 +
  43.850 +		case OPTION_LAST:
  43.851 +			break;
  43.852 +		}
  43.853 +	}
  43.854 +}
  43.855 +
  43.856 +int
  43.857 +main(int argc, const char *argv[])
  43.858 +{
  43.859 +	argc = parse_options(rpm_options, argc, argv);
  43.860 +
  43.861 +	if (option_version) {
  43.862 +		printf("razor rpm version hoopla.\n");
  43.863 +		exit(0);
  43.864 +	}
  43.865 +
  43.866 +	if (option_help) {
  43.867 +		printf("Usage: rpm [OPTION...]\n");
  43.868 +		print_options_help(rpm_options);
  43.869 +		exit(0);
  43.870 +	}
  43.871 +
  43.872 +	if (option_usage) {
  43.873 +		printf("Usage: rpm [OPTION...]\n");
  43.874 +		print_options_usage(rpm_options);
  43.875 +		printf("\n");
  43.876 +		exit(0);
  43.877 +	}
  43.878 +
  43.879 +	if (option_initdb) {
  43.880 +		command_initdb(argc, argv);
  43.881 +	} else if (option_verify) {
  43.882 +		command_verify(argc, argv);
  43.883 +	} else if (option_query) {
  43.884 +		command_query(argc, argv);
  43.885 +	} else if (option_install) {
  43.886 +		command_install(argc, argv);
  43.887 +	} else if (option_upgrade) {
  43.888 +		command_update(argc, argv);
  43.889 +	} else if (option_erase) {
  43.890 +		command_erase(argc, argv);
  43.891 +	} else {
  43.892 +		print_options_usage(rpm_options);
  43.893 +		printf("\n");
  43.894 +		exit(0);
  43.895 +	}
  43.896 +
  43.897 +	return 0;
  43.898 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/src/test-driver.c	Fri Jun 20 19:04:47 2008 -0400
    44.3 @@ -0,0 +1,463 @@
    44.4 +#include <stdio.h>
    44.5 +#include <string.h>
    44.6 +#include <stdarg.h>
    44.7 +#include <unistd.h>
    44.8 +#include <fcntl.h>
    44.9 +#include <errno.h>
   44.10 +#include <expat.h>
   44.11 +
   44.12 +#include "razor.h"
   44.13 +
   44.14 +#define XML_BUFFER_SIZE 4096
   44.15 +
   44.16 +static void
   44.17 +parse_xml_file(const char *filename,
   44.18 +	       XML_StartElementHandler start,
   44.19 +	       XML_EndElementHandler end,
   44.20 +	       void *data)
   44.21 +{
   44.22 +	XML_Parser parser;
   44.23 +	char *buffer;
   44.24 +	int fd, len, err;
   44.25 +
   44.26 +	parser = XML_ParserCreate(NULL);
   44.27 +	XML_SetElementHandler(parser, start, end);
   44.28 +	XML_SetUserData(parser, data);
   44.29 +
   44.30 +	fd = open(filename, O_RDONLY);
   44.31 +	if (fd < 0) {
   44.32 +		fprintf(stderr, "failed to open %s: %m\n", filename);
   44.33 +		exit(-1);
   44.34 +	}
   44.35 +
   44.36 +	while (1) {
   44.37 +		buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
   44.38 +		len = read(fd, buffer, XML_BUFFER_SIZE);
   44.39 +		if (len == 0)
   44.40 +			break;
   44.41 +		err = XML_ParseBuffer(parser, len, len == 0);
   44.42 +		if (err == XML_STATUS_ERROR) {
   44.43 +			fprintf(stderr, "parse error at line %lu:\n%s\n",
   44.44 +				XML_GetCurrentLineNumber(parser),
   44.45 +				XML_ErrorString(XML_GetErrorCode(parser)));
   44.46 +			exit(-1);
   44.47 +		}
   44.48 +	}
   44.49 +
   44.50 +	if (fd < 0) {
   44.51 +		fprintf(stderr, "read: %m\n");
   44.52 +		exit(-1);
   44.53 +	}
   44.54 +
   44.55 +	close(fd);
   44.56 +}
   44.57 +
   44.58 +struct test_context {
   44.59 +	struct razor_set *system_set, *repo_set, *result_set;
   44.60 +
   44.61 +	struct razor_importer *importer;
   44.62 +	struct razor_set **importer_set;
   44.63 +
   44.64 +	struct razor_transaction *trans;
   44.65 +
   44.66 +	char *install_pkgs[3], *remove_pkgs[3];
   44.67 +	int n_install_pkgs, n_remove_pkgs;
   44.68 +
   44.69 +	int unsat;
   44.70 +	int in_result;
   44.71 +
   44.72 +	int debug, errors;
   44.73 +};
   44.74 +
   44.75 +static void
   44.76 +get_atts(const char **atts, ...)
   44.77 +{
   44.78 +	va_list ap;
   44.79 +	const char *name, **ptr;
   44.80 +	int i;
   44.81 +
   44.82 +	va_start(ap, atts);
   44.83 +	while (name = va_arg(ap, const char *), name != NULL) {
   44.84 +		ptr = va_arg(ap, const char **);
   44.85 +		*ptr = NULL;
   44.86 +		for (i = 0; atts[i]; i += 2) {
   44.87 +			if (strcmp(atts[i], name) == 0)
   44.88 +				*ptr = atts[i + 1];
   44.89 +		}
   44.90 +	}
   44.91 +	va_end(ap);
   44.92 +}
   44.93 +
   44.94 +static enum razor_version_relation
   44.95 +parse_relation (const char *rel_str)
   44.96 +{
   44.97 +	if (!rel_str)
   44.98 +		return -1;
   44.99 +	if (rel_str[0] == 'L')
  44.100 +		return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
  44.101 +	else if (rel_str[0] == 'G')
  44.102 +		return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
  44.103 +	else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
  44.104 +		return RAZOR_VERSION_EQUAL;
  44.105 +	else
  44.106 +		return -1;
  44.107 +}
  44.108 +
  44.109 +static void
  44.110 +start_test(struct test_context *ctx, const char **atts)
  44.111 +{
  44.112 +	const char *name = NULL;
  44.113 +
  44.114 +	get_atts(atts, "name", &name, NULL);
  44.115 +	if (!name) {
  44.116 +		fprintf(stderr, "Test with no name\n");
  44.117 +		exit(1);
  44.118 +	}
  44.119 +	printf("%s\n", name);
  44.120 +}
  44.121 +
  44.122 +static void
  44.123 +end_test(struct test_context *ctx)
  44.124 +{
  44.125 +	if (ctx->system_set) {
  44.126 +		razor_set_destroy(ctx->system_set);
  44.127 +		ctx->system_set = NULL;
  44.128 +	}
  44.129 +	if (ctx->repo_set) {
  44.130 +		razor_set_destroy(ctx->repo_set);
  44.131 +		ctx->repo_set = NULL;
  44.132 +	}
  44.133 +	if (ctx->result_set) {
  44.134 +		razor_set_destroy(ctx->result_set);
  44.135 +		ctx->result_set = NULL;
  44.136 +	}
  44.137 +	if (ctx->trans) {
  44.138 +		razor_transaction_destroy(ctx->trans);
  44.139 +		ctx->trans = NULL;
  44.140 +	}
  44.141 +}
  44.142 +
  44.143 +static void
  44.144 +start_set(struct test_context *ctx, const char **atts)
  44.145 +{
  44.146 +	const char *name = NULL;
  44.147 +
  44.148 +	ctx->importer = razor_importer_new();
  44.149 +	get_atts(atts, "name", &name, NULL);
  44.150 +	if (!name)
  44.151 +		ctx->importer_set = &ctx->result_set;
  44.152 +	else if (!strcmp(name, "system"))
  44.153 +		ctx->importer_set = &ctx->system_set;
  44.154 +	else if (!strcmp(name, "repo"))
  44.155 +		ctx->importer_set = &ctx->repo_set;
  44.156 +	else {
  44.157 +		fprintf(stderr, "  bad set name '%s'\n", name);
  44.158 +		exit(1);
  44.159 +	}
  44.160 +}
  44.161 +
  44.162 +static void
  44.163 +end_set(struct test_context *ctx)
  44.164 +{
  44.165 +	*ctx->importer_set = razor_importer_finish(ctx->importer);
  44.166 +	ctx->importer = NULL;
  44.167 +}
  44.168 +
  44.169 +static void
  44.170 +start_package(struct test_context *ctx, const char **atts)
  44.171 +{
  44.172 +	const char *name = NULL, *version = NULL, *arch = NULL;
  44.173 +
  44.174 +	get_atts(atts, "name", &name,
  44.175 +		 "version", &version,
  44.176 +		 "arch", &arch,
  44.177 +		 NULL);
  44.178 +
  44.179 +	if (!name) {
  44.180 +		fprintf(stderr, "  package with no name\n");
  44.181 +		exit(1);
  44.182 +	}
  44.183 +
  44.184 +	razor_importer_begin_package(ctx->importer, name, version, arch);
  44.185 +	razor_importer_add_property(ctx->importer, name,
  44.186 +				    RAZOR_VERSION_EQUAL, version,
  44.187 +				    RAZOR_PROPERTY_PROVIDES);
  44.188 +}
  44.189 +
  44.190 +static void
  44.191 +end_package(struct test_context *ctx)
  44.192 +{
  44.193 +	razor_importer_finish_package(ctx->importer);
  44.194 +}
  44.195 +
  44.196 +static void
  44.197 +add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
  44.198 +{
  44.199 +	razor_importer_add_property(ctx->importer, name,
  44.200 +				    rel, version, type);
  44.201 +}
  44.202 +
  44.203 +static void
  44.204 +check_unsatisfiable_property(struct test_context *ctx,
  44.205 +			     enum razor_property_type type,
  44.206 +			     const char *name,
  44.207 +			     enum razor_version_relation rel,
  44.208 +			     const char *version)
  44.209 +{
  44.210 +	static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
  44.211 +
  44.212 +	if (!version)
  44.213 +		version = "";
  44.214 +
  44.215 +	if (razor_transaction_unsatisfied_property(ctx->trans,
  44.216 +						   name, rel, version, type))
  44.217 +		return;
  44.218 +
  44.219 +	fprintf(stderr, "  didn't get unsatisfiable '%s %s %s'\n",
  44.220 +		name, relation_string[rel], version);
  44.221 +	ctx->errors++;
  44.222 +}
  44.223 +
  44.224 +static void
  44.225 +start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
  44.226 +{
  44.227 +	const char *name = NULL, *rel_str = NULL, *version = NULL;
  44.228 +	enum razor_version_relation rel;
  44.229 +
  44.230 +	get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
  44.231 +	if (name == NULL) {
  44.232 +		fprintf(stderr, "  no name specified for property\n");
  44.233 +		exit(1);
  44.234 +	}
  44.235 +	if (version) {
  44.236 +		rel = parse_relation(rel_str);
  44.237 +		if (rel == -1) {
  44.238 +			fprintf(stderr, "  bad or missing version relation for property %s\n", name);
  44.239 +			exit(1);
  44.240 +		}
  44.241 +	} else
  44.242 +		rel = RAZOR_VERSION_EQUAL;
  44.243 +
  44.244 +	if (ctx->unsat)
  44.245 +		check_unsatisfiable_property(ctx, type, name, rel, version);
  44.246 +	else
  44.247 +		add_property(ctx, type, name, rel, version);
  44.248 +}
  44.249 +
  44.250 +static void
  44.251 +start_transaction(struct test_context *ctx, const char **atts)
  44.252 +{
  44.253 +	ctx->n_install_pkgs = 0;
  44.254 +	ctx->n_remove_pkgs = 0;
  44.255 +}
  44.256 +
  44.257 +static void
  44.258 +end_transaction(struct test_context *ctx)
  44.259 +{
  44.260 +	struct razor_package *pkg;
  44.261 +	int errors, i;
  44.262 +
  44.263 +	ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
  44.264 +	for (i = 0; i < ctx->n_install_pkgs; i++) {
  44.265 +		pkg = razor_set_get_package(ctx->repo_set,
  44.266 +					    ctx->install_pkgs[i]);
  44.267 +		razor_transaction_install_package(ctx->trans, pkg);
  44.268 +	}
  44.269 +	for (i = 0; i < ctx->n_remove_pkgs; i++) {
  44.270 +		pkg = razor_set_get_package(ctx->system_set,
  44.271 +					    ctx->remove_pkgs[i]);
  44.272 +		if (!pkg)
  44.273 +			pkg = razor_set_get_package(ctx->repo_set,
  44.274 +						    ctx->remove_pkgs[i]);
  44.275 +
  44.276 +		razor_transaction_remove_package(ctx->trans, pkg);
  44.277 +	}
  44.278 +
  44.279 +	errors = razor_transaction_resolve(ctx->trans);
  44.280 +	printf("\n");
  44.281 +
  44.282 +	while (ctx->n_install_pkgs--)
  44.283 +		free(ctx->install_pkgs[ctx->n_install_pkgs]);
  44.284 +	while (ctx->n_remove_pkgs--)
  44.285 +		free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
  44.286 +
  44.287 +	if (!errors) {
  44.288 +		struct razor_set *new;
  44.289 +		new = razor_transaction_finish(ctx->trans);
  44.290 +		ctx->trans = NULL;
  44.291 +		ctx->system_set = new;
  44.292 +	}
  44.293 +}
  44.294 +
  44.295 +static void
  44.296 +start_install_or_update(struct test_context *ctx, const char **atts)
  44.297 +{
  44.298 +	const char *name = NULL;
  44.299 +
  44.300 +	get_atts(atts, "name", &name, NULL);
  44.301 +	if (!name) {
  44.302 +		fprintf(stderr, "  install/update with no name\n");
  44.303 +		exit(1);
  44.304 +	}
  44.305 +
  44.306 +	ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
  44.307 +}
  44.308 +
  44.309 +static void
  44.310 +start_remove(struct test_context *ctx, const char **atts)
  44.311 +{
  44.312 +	const char *name = NULL;
  44.313 +
  44.314 +	get_atts(atts, "name", &name, NULL);
  44.315 +	if (!name) {
  44.316 +		fprintf(stderr, "  remove with no name\n");
  44.317 +		exit(1);
  44.318 +	}
  44.319 +
  44.320 +	ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
  44.321 +}
  44.322 +
  44.323 +static void
  44.324 +start_result(struct test_context *ctx, const char **atts)
  44.325 +{
  44.326 +	ctx->in_result = 1;
  44.327 +}
  44.328 +
  44.329 +static void
  44.330 +diff_callback(const char *name,
  44.331 +	      const char *old_version,
  44.332 +	      const char *new_version,
  44.333 +	      const char *arch,
  44.334 +	      void *data)
  44.335 +{
  44.336 +	struct test_context *ctx = data;
  44.337 +
  44.338 +	ctx->errors++;
  44.339 +	if (old_version) {
  44.340 +		fprintf(stderr, "  result set should not contain %s %s\n",
  44.341 +			name, old_version);
  44.342 +	} else {
  44.343 +		fprintf(stderr, "  result set should contain %s %s\n",
  44.344 +			name, new_version);
  44.345 +	}
  44.346 +}
  44.347 +
  44.348 +static void
  44.349 +end_result(struct test_context *ctx)
  44.350 +{
  44.351 +	ctx->in_result = 0;
  44.352 +
  44.353 +	if (ctx->result_set) {
  44.354 +		if (!ctx->system_set)
  44.355 +			ctx->system_set = razor_set_create();
  44.356 +		razor_set_diff(ctx->system_set, ctx->result_set,
  44.357 +			       diff_callback, ctx);
  44.358 +	}
  44.359 +}
  44.360 +
  44.361 +static void
  44.362 +start_unsatisfiable(struct test_context *ctx, const char **atts)
  44.363 +{
  44.364 +	if (ctx->result_set) {
  44.365 +		fprintf(stderr, "Expected to fail, but didn't\n");
  44.366 +		exit(1);
  44.367 +	}
  44.368 +
  44.369 +	ctx->unsat = 1;
  44.370 +}
  44.371 +
  44.372 +static void
  44.373 +end_unsatisfiable(struct test_context *ctx)
  44.374 +{
  44.375 +	ctx->unsat = 0;
  44.376 +}
  44.377 +
  44.378 +static void
  44.379 +start_test_element(void *data, const char *element, const char **atts)
  44.380 +{
  44.381 +	struct test_context *ctx = data;
  44.382 +
  44.383 +	if (strcmp(element, "tests") == 0) {
  44.384 +		;
  44.385 +	} else if (strcmp(element, "test") == 0) {
  44.386 +		start_test(ctx, atts);
  44.387 +	} else if (strcmp(element, "set") == 0) {
  44.388 +		start_set(ctx, atts);
  44.389 +	} else if (strcmp(element, "transaction") == 0) {
  44.390 +		start_transaction(ctx, atts);
  44.391 +	} else if (strcmp(element, "install") == 0) {
  44.392 +		start_install_or_update(ctx, atts);
  44.393 +	} else if (strcmp(element, "install") == 0) {
  44.394 +		start_install_or_update(ctx, atts);
  44.395 +	} else if (strcmp(element, "remove") == 0) {
  44.396 +		start_remove(ctx, atts);
  44.397 +	} else if (strcmp(element, "result") == 0) {
  44.398 +		start_result(ctx, atts);
  44.399 +	} else if (strcmp(element, "unsatisfiable") == 0) {
  44.400 +		start_unsatisfiable(ctx, atts);
  44.401 +	} else if (strcmp(element, "package") == 0) {
  44.402 +		start_package(ctx, atts);
  44.403 +	} else if (strcmp(element, "requires") == 0) {
  44.404 +		start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
  44.405 +	} else if (strcmp(element, "provides") == 0) {
  44.406 +		start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
  44.407 +	} else if (strcmp(element, "conflicts") == 0) {
  44.408 +		start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
  44.409 +	} else if (strcmp(element, "obsoletes") == 0) {
  44.410 +		start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
  44.411 +	} else {
  44.412 +		fprintf(stderr, "Unrecognized element '%s'\n", element);
  44.413 +		exit(1);
  44.414 +	}
  44.415 +}
  44.416 +
  44.417 +static void
  44.418 +end_test_element (void *data, const char *element)
  44.419 +{
  44.420 +	struct test_context *ctx = data;
  44.421 +
  44.422 +	if (strcmp(element, "test") == 0) {
  44.423 +		end_test(ctx);
  44.424 +	} else if (strcmp(element, "set") == 0) {
  44.425 +		end_set(ctx);
  44.426 +	} else if (strcmp(element, "package") == 0) {
  44.427 +		end_package(ctx);
  44.428 +	} else if (strcmp(element, "transaction") == 0) {
  44.429 +		end_transaction(ctx);
  44.430 +	} else if (strcmp(element, "result") == 0) {
  44.431 +		end_result(ctx);
  44.432 +	} else if (strcmp(element, "unsatisfiable") == 0) {
  44.433 +		end_unsatisfiable(ctx);
  44.434 +	}
  44.435 +}
  44.436 +
  44.437 +int main(int argc, char *argv[])
  44.438 +{
  44.439 +	struct test_context ctx;
  44.440 +	const char *test_file;
  44.441 +
  44.442 +	memset(&ctx, 0, sizeof ctx);
  44.443 +
  44.444 +	if (argc > 3) {
  44.445 +		fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
  44.446 +		exit(-1);
  44.447 +	}
  44.448 +
  44.449 +	if (argc >= 2 && !strcmp (argv[1], "-d")) {
  44.450 +		ctx.debug = 1;
  44.451 +		argc--;
  44.452 +		argv++;
  44.453 +	}
  44.454 +	if (argc == 2)
  44.455 +		test_file = argv[1];
  44.456 +	else
  44.457 +		test_file = "test.xml";
  44.458 +
  44.459 +	parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
  44.460 +
  44.461 +	if (ctx.errors) {
  44.462 +		fprintf(stderr, "\n%d errors\n", ctx.errors);
  44.463 +		return 1;
  44.464 +	} else
  44.465 +		return 0;
  44.466 +}
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/src/test.xml	Fri Jun 20 19:04:47 2008 -0400
    45.3 @@ -0,0 +1,858 @@
    45.4 +<tests>
    45.5 +
    45.6 +    <test name="testEmpty">
    45.7 +	<set name="system"/>
    45.8 +	<set name="repo">
    45.9 +	    <package name="zsh" version="1-1" arch="i386"/>
   45.10 +	</set>
   45.11 +	<transaction>
   45.12 +	    <install name="zsh"/>
   45.13 +	    <remove name="zsh"/>
   45.14 +	</transaction>
   45.15 +	<result>
   45.16 +	    <set/>
   45.17 +	</result>
   45.18 +    </test>
   45.19 +
   45.20 +    <test name="testInstallSinglePackageNoRequires">
   45.21 +	<set name="system"/>
   45.22 +	<set name="repo">
   45.23 +	    <package name="zsh" version="1-1" arch="i386"/>
   45.24 +	</set>
   45.25 +	<transaction>
   45.26 +	    <install name="zsh"/>
   45.27 +	</transaction>
   45.28 +	<result>
   45.29 +	    <set>
   45.30 +		<package name="zsh" version="1-1" arch="i386"/>
   45.31 +	    </set>
   45.32 +	</result>
   45.33 +    </test>
   45.34 +
   45.35 +    <test name="testInstallSinglePackageRequireNotProvided">
   45.36 +	<set name="system"/>
   45.37 +	<set name="repo">
   45.38 +	    <package name="zsh" version="1-1" arch="i386">
   45.39 +		<requires name="zip"/>
   45.40 +	    </package>
   45.41 +	</set>
   45.42 +	<transaction>
   45.43 +	    <install name="zsh"/>
   45.44 +	</transaction>
   45.45 +	<result>
   45.46 +	    <unsatisfiable>
   45.47 +		<requires name="zip"/>
   45.48 +	    </unsatisfiable>
   45.49 +	</result>
   45.50 +    </test>
   45.51 +
   45.52 +    <test name="testInstallSinglePackageRequireInstalled">
   45.53 +	<set name="system">
   45.54 +	    <package name="zip" version="1-1" arch="i386"/>
   45.55 +	</set>
   45.56 +	<set name="repo">
   45.57 +	    <package name="zsh" version="1-1" arch="i386">
   45.58 +		<requires name="zip"/>
   45.59 +	    </package>
   45.60 +	</set>
   45.61 +	<transaction>
   45.62 +	    <install name="zsh"/>
   45.63 +	</transaction>
   45.64 +	<result>
   45.65 +	    <set>
   45.66 +		<package name="zip" version="1-1" arch="i386"/>
   45.67 +		<package name="zsh" version="1-1" arch="i386"/>
   45.68 +	    </set>
   45.69 +	</result>
   45.70 +    </test>
   45.71 +
   45.72 +    <test name="testInstallSinglePackageRequireInstalledRequireNotProvided">
   45.73 +	<set name="system">
   45.74 +	    <package name="zip" version="1-2" arch="i386"/>
   45.75 +	</set>
   45.76 +	<set name="repo">
   45.77 +	    <package name="zsh" version="1-1" arch="i386">
   45.78 +		<requires name="zip"/>
   45.79 +		<!-- This may be a bug in the python test: it looks
   45.80 +		     like they meant to have zip require zap, not zsh.
   45.81 +		     But the install succeeds if you do that...
   45.82 +		  -->
   45.83 +		<requires name="zap"/>
   45.84 +	    </package>
   45.85 +	</set>
   45.86 +	<transaction>
   45.87 +	    <install name="zsh"/>
   45.88 +	</transaction>
   45.89 +	<result>
   45.90 +	    <unsatisfiable>
   45.91 +		<requires name="zap"/>
   45.92 +	    </unsatisfiable>
   45.93 +	</result>
   45.94 +    </test>
   45.95 +
   45.96 +    <test name="testInstallSinglePackageRequireInstalledRequireInstall">
   45.97 +	<set name="system">
   45.98 +	    <package name="zip" version="1-3" arch="i386">
   45.99 +		<requires name="zap"/>
  45.100 +	    </package>
  45.101 +	</set>
  45.102 +	<set name="repo">
  45.103 +	    <package name="zsh" version="1-1" arch="i386">
  45.104 +		<requires name="zip"/>
  45.105 +	    </package>
  45.106 +	    <package name="zap" version="1-2" arch="i386"/>
  45.107 +	</set>
  45.108 +	<transaction>
  45.109 +	    <install name="zsh"/>
  45.110 +	    <install name="zap"/>
  45.111 +	</transaction>
  45.112 +	<result>
  45.113 +	    <set>
  45.114 +		<package name="zap" version="1-2" arch="i386"/>
  45.115 +		<package name="zip" version="1-3" arch="i386"/>
  45.116 +		<package name="zsh" version="1-1" arch="i386"/>
  45.117 +	    </set>
  45.118 +	</result>
  45.119 +    </test>
  45.120 +
  45.121 +    <test name="testInstallSinglePackageRequireVer1NotProvided">
  45.122 +	<set name="system">
  45.123 +	    <package name="zip" version="1.0-2" arch="i386"/>
  45.124 +	</set>
  45.125 +	<set name="repo">
  45.126 +	    <package name="zsh" version="1-1" arch="i386">
  45.127 +		<requires name="zip" relation="EQ" version="1.3-2"/>
  45.128 +	    </package>
  45.129 +	</set>
  45.130 +	<transaction>
  45.131 +	    <install name="zsh"/>
  45.132 +	</transaction>
  45.133 +	<result>
  45.134 +	    <unsatisfiable>
  45.135 +		<requires name="zip" relation="EQ" version="1.3-2"/>
  45.136 +	    </unsatisfiable>
  45.137 +	</result>
  45.138 +    </test>
  45.139 +
  45.140 +    <test name="testInstallSinglePackageRequireVer1Installed">
  45.141 +	<set name="system">
  45.142 +	    <package name="zip" version="1.3-2" arch="i386"/>
  45.143 +	</set>
  45.144 +	<set name="repo">
  45.145 +	    <package name="zsh" version="1-1" arch="i386">
  45.146 +		<requires name="zip" relation="EQ" version="1.3-2"/>
  45.147 +	    </package>
  45.148 +	</set>
  45.149 +	<transaction>
  45.150 +	    <install name="zsh"/>
  45.151 +	</transaction>
  45.152 +	<result>
  45.153 +	    <set>
  45.154 +		<package name="zip" version="1.3-2" arch="i386"/>
  45.155 +		<package name="zsh" version="1-1" arch="i386"/>
  45.156 +	    </set>
  45.157 +	</result>
  45.158 +    </test>
  45.159 +
  45.160 +    <test name="testInstallSinglePackageRequireVer2NotProvided">
  45.161 +	<set name="system">
  45.162 +	    <package name="zip" version="1.3-2" arch="i386"/>
  45.163 +	</set>
  45.164 +	<set name="repo">
  45.165 +	    <package name="zsh" version="1-1" arch="i386">
  45.166 +		<requires name="zip" relation="EQ" version="1.3-4"/>
  45.167 +	    </package>
  45.168 +	</set>
  45.169 +	<transaction>
  45.170 +	    <install name="zsh"/>
  45.171 +	</transaction>
  45.172 +	<result>
  45.173 +	    <unsatisfiable>
  45.174 +		<requires name="zip" relation="EQ" version="1.3-4"/>
  45.175 +	    </unsatisfiable>
  45.176 +	</result>
  45.177 +    </test>
  45.178 +
  45.179 +    <test name="testInstallSinglePackageRequireVer2Installed">
  45.180 +	<set name="system">
  45.181 +	    <package name="zip" version="1.3-4" arch="i386"/>
  45.182 +	</set>
  45.183 +	<set name="repo">
  45.184 +	    <package name="zsh" version="1-1" arch="i386">
  45.185 +		<requires name="zip" relation="EQ" version="1.3-4"/>
  45.186 +	    </package>
  45.187 +	</set>
  45.188 +	<transaction>
  45.189 +	    <install name="zsh"/>
  45.190 +	</transaction>
  45.191 +	<result>
  45.192 +	    <set>
  45.193 +		<package name="zip" version="1.3-4" arch="i386"/>
  45.194 +		<package name="zsh" version="1-1" arch="i386"/>
  45.195 +	    </set>
  45.196 +	</result>
  45.197 +    </test>
  45.198 +
  45.199 +    <test name="testInstallSinglePackageRequireVer3NotProvided">
  45.200 +	<set name="system">
  45.201 +	    <package name="zip" version="0:1.3-4" arch="i386"/>
  45.202 +	</set>
  45.203 +	<set name="repo">
  45.204 +	    <package name="zsh" version="1-1" arch="i386">
  45.205 +		<requires name="zip" relation="GE" version="1:1.3-4"/>
  45.206 +	    </package>
  45.207 +	</set>
  45.208 +	<transaction>
  45.209 +	    <install name="zsh"/>
  45.210 +	</transaction>
  45.211 +	<result>
  45.212 +	    <unsatisfiable>
  45.213 +		<requires name="zip" relation="GE" version="1:1.3-4"/>
  45.214 +	    </unsatisfiable>
  45.215 +	</result>
  45.216 +    </test>
  45.217 +
  45.218 +    <test name="testInstallSinglePackageRequireVer3Installed">
  45.219 +	<set name="system">
  45.220 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  45.221 +	</set>
  45.222 +	<set name="repo">
  45.223 +	    <package name="zsh" version="1-1" arch="i386">
  45.224 +		<requires name="zip" relation="GE" version="2:1.3-4"/>
  45.225 +	    </package>
  45.226 +	</set>
  45.227 +	<transaction>
  45.228 +	    <install name="zsh"/>
  45.229 +	</transaction>
  45.230 +	<result>
  45.231 +	    <set>
  45.232 +		<package name="zip" version="2:1.3-4" arch="i386"/>
  45.233 +		<package name="zsh" version="1-1" arch="i386"/>
  45.234 +	    </set>
  45.235 +	</result>
  45.236 +    </test>
  45.237 +
  45.238 +    <test name="testInstallSinglePackageRequireVer4NotProvided">
  45.239 +	<set name="system">
  45.240 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  45.241 +	</set>
  45.242 +	<set name="repo">
  45.243 +	    <package name="zsh" version="1-1" arch="i386">
  45.244 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.245 +	    </package>
  45.246 +	</set>
  45.247 +	<transaction>
  45.248 +	    <install name="zsh"/>
  45.249 +	</transaction>
  45.250 +	<result>
  45.251 +	    <unsatisfiable>
  45.252 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.253 +	    </unsatisfiable>
  45.254 +	</result>
  45.255 +    </test>
  45.256 +
  45.257 +    <test name="testInstallSinglePackageRequireVer4_1Installed">
  45.258 +	<set name="system">
  45.259 +	    <package name="zip" version="2:1.0-4" arch="i386"/>
  45.260 +	</set>
  45.261 +	<set name="repo">
  45.262 +	    <package name="zsh" version="1-1" arch="i386">
  45.263 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.264 +	    </package>
  45.265 +	</set>
  45.266 +	<transaction>
  45.267 +	    <install name="zsh"/>
  45.268 +	</transaction>
  45.269 +	<result>
  45.270 +	    <set>
  45.271 +		<package name="zip" version="2:1.0-4" arch="i386"/>
  45.272 +		<package name="zsh" version="1-1" arch="i386"/>
  45.273 +	    </set>
  45.274 +	</result>
  45.275 +    </test>
  45.276 +
  45.277 +    <test name="testInstallSinglePackageRequireVer4_2Installed">
  45.278 +	<set name="system">
  45.279 +	    <package name="zip" version="2:1.3-3" arch="i386"/>
  45.280 +	</set>
  45.281 +	<set name="repo">
  45.282 +	    <package name="zsh" version="1-1" arch="i386">
  45.283 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.284 +	    </package>
  45.285 +	</set>
  45.286 +	<transaction>
  45.287 +	    <install name="zsh"/>
  45.288 +	</transaction>
  45.289 +	<result>
  45.290 +	    <set>
  45.291 +		<package name="zip" version="2:1.3-3" arch="i386"/>
  45.292 +		<package name="zsh" version="1-1" arch="i386"/>
  45.293 +	    </set>
  45.294 +	</result>
  45.295 +    </test>
  45.296 +
  45.297 +    <test name="testInstallSinglePackageRequireVer4_3Installed">
  45.298 +	<set name="system">
  45.299 +	    <package name="zip" version="1.3-4" arch="i386"/>
  45.300 +	</set>
  45.301 +	<set name="repo">
  45.302 +	    <package name="zsh" version="1-1" arch="i386">
  45.303 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.304 +	    </package>
  45.305 +	</set>
  45.306 +	<transaction>
  45.307 +	    <install name="zsh"/>
  45.308 +	</transaction>
  45.309 +	<result>
  45.310 +	    <set>
  45.311 +		<package name="zip" version="1.3-4" arch="i386"/>
  45.312 +		<package name="zsh" version="1-1" arch="i386"/>
  45.313 +	    </set>
  45.314 +	</result>
  45.315 +    </test>
  45.316 +
  45.317 +    <test name="testInstallSinglePackageRequireVer4_4Installed">
  45.318 +	<set name="system">
  45.319 +	    <package name="zip" version="1:1.3-4" arch="i386"/>
  45.320 +	</set>
  45.321 +	<set name="repo">
  45.322 +	    <package name="zsh" version="1-1" arch="i386">
  45.323 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.324 +	    </package>
  45.325 +	</set>
  45.326 +	<transaction>
  45.327 +	    <install name="zsh"/>
  45.328 +	</transaction>
  45.329 +	<result>
  45.330 +	    <set>
  45.331 +		<package name="zip" version="1:1.3-4" arch="i386"/>
  45.332 +		<package name="zsh" version="1-1" arch="i386"/>
  45.333 +	    </set>
  45.334 +	</result>
  45.335 +    </test>
  45.336 +
  45.337 +    <test name="testInstallSinglePackageRequireVer4_5Installed">
  45.338 +	<set name="system">
  45.339 +	    <package name="zip" version="2:0.3-4" arch="i386"/>
  45.340 +	</set>
  45.341 +	<set name="repo">
  45.342 +	    <package name="zsh" version="1-1" arch="i386">
  45.343 +		<requires name="zip" relation="LT" version="2:1.3-4"/>
  45.344 +	    </package>
  45.345 +	</set>
  45.346 +	<transaction>
  45.347 +	    <install name="zsh"/>
  45.348 +	</transaction>
  45.349 +	<result>
  45.350 +	    <set>
  45.351 +		<package name="zip" version="2:0.3-4" arch="i386"/>
  45.352 +		<package name="zsh" version="1-1" arch="i386"/>
  45.353 +	    </set>
  45.354 +	</result>
  45.355 +    </test>
  45.356 +
  45.357 +    <test name="testInstallSinglePackageRequireXtraBadVer">
  45.358 +	<set name="system">
  45.359 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  45.360 +	</set>
  45.361 +	<set name="repo">
  45.362 +	    <package name="zsh" version="1-1" arch="i386">
  45.363 +		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  45.364 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  45.365 +	    </package>
  45.366 +	    <package name="zap" version="0:1.3-4" arch="i386"/>
  45.367 +	</set>
  45.368 +	<transaction>
  45.369 +	    <install name="zsh"/>
  45.370 +	</transaction>
  45.371 +	<result>
  45.372 +	    <unsatisfiable>
  45.373 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  45.374 +	    </unsatisfiable>
  45.375 +	</result>
  45.376 +    </test>
  45.377 +
  45.378 +    <test name="testInstallSinglePackageRequireXtra">
  45.379 +	<set name="system">
  45.380 +	    <package name="zip" version="2:1.3-4" arch="i386"/>
  45.381 +	</set>
  45.382 +	<set name="repo">
  45.383 +	    <package name="zsh" version="1-1" arch="i386">
  45.384 +		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  45.385 +		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  45.386 +	    </package>
  45.387 +	    <package name="zap" version="4:2.6-8" arch="i386"/>
  45.388 +	</set>
  45.389 +	<transaction>
  45.390 +	    <install name="zsh"/>
  45.391 +	</transaction>
  45.392 +	<result>
  45.393 +	    <set>
  45.394 +		<package name="zap" version="4:2.6-8" arch="i386"/>
  45.395 +		<package name="zip" version="2:1.3-4" arch="i386"/>
  45.396 +		<package name="zsh" version="1-1" arch="i386"/>
  45.397 +	    </set>
  45.398 +	</result>
  45.399 +    </test>
  45.400 +
  45.401 +    <test name="testInstallSinglePackageRequireInstalledRequireXtra">
  45.402 +	<set name="system">
  45.403 +	    <package name="zip" version="2:1.3-4" arch="i386">
  45.404 +		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  45.405 +	    </package>
  45.406 +	</set>
  45.407 +	<set name="repo">
  45.408 +	    <package name="zsh" version="1-1" arch="i386">
  45.409 +		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  45.410 +	    </package>
  45.411 +	    <!-- This may be a bug in the python test; it doesn't
  45.412 +	         actually matter whether or not zap is available
  45.413 +	      -->
  45.414 +	    <package name="zap" version="4:2.6-8" arch="i386"/>
  45.415 +	</set>
  45.416 +	<transaction>
  45.417 +	    <install name="zsh"/>
  45.418 +	</transaction>
  45.419 +	<result>
  45.420 +	    <set>
  45.421 +		<package name="zip" version="2:1.3-4" arch="i386"/>
  45.422 +		<package name="zsh" version="1-1" arch="i386"/>
  45.423 +	    </set>
  45.424 +	</result>
  45.425 +    </test>
  45.426 +
  45.427 +    <test name="testInstallSinglePackageRequireUpgradeRequireXtraErr">
  45.428 +	<set name="system">
  45.429 +	    <package name="zip" version="2:1.3-4" arch="i386">
  45.430 +		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  45.431 +	    </package>
  45.432 +	</set>
  45.433 +	<set name="repo">
  45.434 +	    <package name="zsh" version="1-1" arch="i386">
  45.435 +		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  45.436 +	    </package>
  45.437 +	    <package name="zip" version="4:2.6-8" arch="i386">
  45.438 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  45.439 +	    </package>
  45.440 +	    <package name="zap" version="2:1.3-4" arch="i386">
  45.441 +		<requires name="zsh" relation="EQ" version="2:4-8"/>
  45.442 +	    </package>
  45.443 +	</set>
  45.444 +	<transaction>
  45.445 +	    <install name="zsh"/>
  45.446 +	</transaction>
  45.447 +	<result>
  45.448 +	    <unsatisfiable>
  45.449 +		<requires name="zsh" relation="EQ" version="2:4-8"/>
  45.450 +	    </unsatisfiable>
  45.451 +	</result>
  45.452 +    </test>
  45.453 +
  45.454 +    <test name="testInstallSinglePackageRequireUpgradeRequireXtraOk">
  45.455 +	<set name="system">
  45.456 +	    <package name="zip" version="2:1.3-4" arch="i386">
  45.457 +		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  45.458 +	    </package>
  45.459 +	</set>
  45.460 +	<set name="repo">
  45.461 +	    <package name="zsh" version="1-1" arch="i386">
  45.462 +		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  45.463 +	    </package>
  45.464 +	    <package name="zip" version="4:2.6-8" arch="i386">
  45.465 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  45.466 +	    </package>
  45.467 +	    <package name="zap" version="2:1.3-4" arch="i386"/>
  45.468 +	</set>
  45.469 +	<transaction>
  45.470 +	    <install name="zsh"/>
  45.471 +	</transaction>
  45.472 +	<result>
  45.473 +	    <set>
  45.474 +		<package name="zap" version="2:1.3-4" arch="i386"/>
  45.475 +		<package name="zip" version="4:2.6-8" arch="i386"/>
  45.476 +		<package name="zsh" version="1-1" arch="i386"/>
  45.477 +	    </set>
  45.478 +	</result>
  45.479 +    </test>
  45.480 +
  45.481 +    <test name="testInstallSinglePackageRequireMultiXtra">
  45.482 +	<set name="system"/>
  45.483 +	<set name="repo">
  45.484 +	    <package name="zsh" version="1-1" arch="i386">
  45.485 +		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  45.486 +	    </package>
  45.487 +	    <package name="zip" version="4:2.6-8" arch="i386">
  45.488 +		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  45.489 +	    </package>
  45.490 +	    <package name="zap" version="2:1.3-4" arch="i386"/>
  45.491 +	</set>
  45.492 +	<transaction>
  45.493 +	    <install name="zsh"/>
  45.494 +	</transaction>
  45.495 +	<result>
  45.496 +	    <set>
  45.497 +		<package name="zap" version="2:1.3-4" arch="i386"/>
  45.498 +		<package name="zip" version="4:2.6-8" arch="i386"/>
  45.499 +		<package name="zsh" version="1-1" arch="i386"/>
  45.500 +	    </set>
  45.501 +	</result>
  45.502 +    </test>
  45.503 +
  45.504 +    <test name="testInstallSinglePackageRequireInstalledMultiLib">
  45.505 +	<set name="system">
  45.506 +	    <package name="zip" version="1-3" arch="i386"/>
  45.507 +	</set>
  45.508 +	<set name="repo">
  45.509 +	    <package name="zsh" version="1-1" arch="x86_64">
  45.510 +		<requires name="zip"/>
  45.511 +	    </package>
  45.512 +	    <package name="zip" version="1-3" arch="x86_64"/>
  45.513 +	</set>
  45.514 +	<transaction>
  45.515 +	    <install name="zsh"/>
  45.516 +	</transaction>
  45.517 +	<result>
  45.518 +	    <set>
  45.519 +		<package name="zip" version="1-3" arch="i386"/>
  45.520 +		<package name="zsh" version="1-1" arch="x86_64"/>
  45.521 +	    </set>
  45.522 +	</result>
  45.523 +    </test>
  45.524 +
  45.525 +    <test name="testInstallSinglePackageRequireXtra1MultiLib">
  45.526 +	<set name="system"/>
  45.527 +	<set name="repo">
  45.528 +	    <package name="zsh" version="1-1" arch="x86_64">
  45.529 +		<requires name="zip"/>
  45.530 +	    </package>
  45.531 +	    <package name="zip" version="1-3" arch="i386"/>
  45.532 +	</set>
  45.533 +	<transaction>
  45.534 +	    <install name="zsh"/>
  45.535 +	</transaction>
  45.536 +	<result>
  45.537 +	    <set>
  45.538 +		<package name="zip" version="1-3" arch="i386"/>
  45.539 +		<package name="zsh" version="1-1" arch="x86_64"/>
  45.540 +	    </set>
  45.541 +	</result>
  45.542 +    </test>
  45.543 +
  45.544 +    <test name="testInstallSinglePackageRequireXtra2_64MultiLib">
  45.545 +	<set name="system"/>
  45.546 +	<set name="repo">
  45.547 +	    <package name="zsh" version="1-1" arch="x86_64">
  45.548 +		<requires name="zip"/>
  45.549 +	    </package>
  45.550 +	    <package name="zip" version="1-3" arch="i386"/>
  45.551 +	    <package name="zip" version="1-3" arch="x86_64"/>
  45.552 +	</set>
  45.553 +	<transaction>
  45.554 +	    <install name="zsh"/>
  45.555 +	</transaction>
  45.556 +	<result>
  45.557 +	    <set>
  45.558 +		<package name="zsh" version="1-1" arch="x86_64"/>
  45.559 +		<package name="zip" version="1-3" arch="x86_64"/>
  45.560 +	    </set>
  45.561 +	</result>
  45.562 +    </test>
  45.563 +
  45.564 +    <test name="testInstallSinglePackageRequireXtra2_32MultiLib">
  45.565 +	<set name="system"/>
  45.566 +	<set name="repo">
  45.567 +	    <package name="zsh" version="1-1" arch="i386">
  45.568 +		<requires name="zip"/>
  45.569 +	    </package>
  45.570 +	    <package name="zip" version="1-3" arch="i386"/>
  45.571 +	    <package name="zip" version="1-3" arch="x86_64"/>
  45.572 +	</set>
  45.573 +	<transaction>
  45.574 +	    <install name="zsh"/>
  45.575 +	</transaction>
  45.576 +	<result>
  45.577 +	    <set>
  45.578 +		<package name="zip" version="1-3" arch="i386"/>
  45.579 +		<package name="zsh" version="1-1" arch="i386"/>
  45.580 +	    </set>
  45.581 +	</result>
  45.582 +    </test>
  45.583 +
  45.584 +    <test name="testUpdateSinglePackage">
  45.585 +	<set name="system">
  45.586 +	    <package name="zsh" version="1-1" arch="i386"/>
  45.587 +	</set>
  45.588 +	<set name="repo">
  45.589 +	    <package name="zsh" version="1-3" arch="i386"/>
  45.590 +	</set>
  45.591 +	<transaction>
  45.592 +	    <install name="zsh"/>
  45.593 +	</transaction>
  45.594 +	<result>
  45.595 +	    <set>
  45.596 +		<package name="zsh" version="1-3" arch="i386"/>
  45.597 +	    </set>
  45.598 +	</result>
  45.599 +    </test>
  45.600 +
  45.601 +    <test name="testUpdateForDependency">
  45.602 +	<set name="system">
  45.603 +	    <package name="zip" version="0:1-1" arch="i386"/>
  45.604 +	</set>
  45.605 +	<set name="repo">
  45.606 +	    <package name="zsh" version="0:1-1" arch="i386">
  45.607 +		<requires name="zip" relation="EQ" version="0:2-1"/>
  45.608 +	    </package>
  45.609 +	    <package name="zip" version="0:2-1" arch="i386"/>
  45.610 +	</set>
  45.611 +	<transaction>
  45.612 +	    <install name="zsh"/>
  45.613 +	</transaction>
  45.614 +	<result>
  45.615 +	    <set>
  45.616 +		<package name="zip" version="0:2-1" arch="i386"/>
  45.617 +		<package name="zsh" version="0:1-1" arch="i386"/>
  45.618 +	    </set>
  45.619 +	</result>
  45.620 +    </test>
  45.621 +
  45.622 +    <test name="testUpdateSplitPackage">
  45.623 +	<set name="system">
  45.624 +	    <package name="zip" version="0:1-1" arch="i386">
  45.625 +		<provides name="libzip" relation="EQ" version="0:1-1"/>
  45.626 +	    </package>
  45.627 +	</set>
  45.628 +	<set name="repo">
  45.629 +	    <package name="zsh" version="0:1-1" arch="i386">
  45.630 +		<requires name="libzip" relation="EQ" version="0:2-1"/>
  45.631 +	    </package>
  45.632 +	    <package name="zip" version="0:2-1" arch="i386">
  45.633 +		<requires name="zip-libs" relation="EQ" version="0:2-1"/>
  45.634 +	    </package>
  45.635 +	    <package name="zip-libs" version="0:2-1" arch="i386">
  45.636 +		<provides name="libzip" relation="EQ" version="0:2-1"/>
  45.637 +	    </package>
  45.638 +	</set>
  45.639 +	<transaction>
  45.640 +	    <install name="zsh"/>
  45.641 +	</transaction>
  45.642 +	<result>
  45.643 +	    <set>
  45.644 +		<package name="zip" version="0:1-1" arch="i386"/>
  45.645 +		<package name="zip-libs" version="0:2-1" arch="i386"/>
  45.646 +		<package name="zsh" version="0:1-1" arch="i386"/>
  45.647 +	    </set>
  45.648 +	</result>
  45.649 +    </test>
  45.650 +
  45.651 +    <test name="testUpdateSinglePackageNewRequires">
  45.652 +	<set name="system">
  45.653 +	    <package name="zsh" version="1-1" arch="i386"/>
  45.654 +	</set>
  45.655 +	<set name="repo">
  45.656 +	    <package name="zsh" version="1-3" arch="i386">
  45.657 +		<requires name="zip"/>
  45.658 +	    </package>
  45.659 +	    <package name="zip" version="1-3" arch="x86_64"/>
  45.660 +	</set>
  45.661 +	<transaction>
  45.662 +	    <install name="zsh"/>
  45.663 +	</transaction>
  45.664 +	<result>
  45.665 +	    <set>
  45.666 +		<package name="zsh" version="1-3" arch="i386"/>
  45.667 +		<package name="zip" version="1-3" arch="x86_64"/>
  45.668 +	    </set>
  45.669 +	</result>
  45.670 +    </test>
  45.671 +
  45.672 +    <test name="testUpdateSinglePackageOldRequires">
  45.673 +	<set name="system">
  45.674 +	    <package name="zsh" version="1-1" arch="i386">
  45.675 +		<requires name="zip"/>
  45.676 +	    </package>
  45.677 +	    <package name="zip" version="1-3" arch="x86_64"/>
  45.678 +	</set>
  45.679 +	<set name="repo">
  45.680 +	    <package name="zsh" version="1-3" arch="i386">
  45.681 +		<requires name="zip"/>
  45.682 +	    </package>
  45.683 +	</set>
  45.684 +	<transaction>
  45.685 +	    <install name="zsh"/>
  45.686 +	</transaction>
  45.687 +	<result>
  45.688 +	    <set>
  45.689 +		<package name="zip" version="1-3" arch="x86_64"/>
  45.690 +		<package name="zsh" version="1-3" arch="i386"/>
  45.691 +	    </set>
  45.692 +	</result>
  45.693 +    </test>
  45.694 +
  45.695 +    <test name="testUpdateSinglePackageOldRequiresGone">
  45.696 +	<set name="system">
  45.697 +	    <package name="zsh" version="1-1" arch="i386">
  45.698 +		<requires name="zip"/>
  45.699 +	    </package>
  45.700 +	    <package name="zip" version="1-3" arch="x86_64"/>
  45.701 +	</set>
  45.702 +	<set name="repo">
  45.703 +	    <package name="zsh" version="1-3" arch="i386"/>
  45.704 +	</set>
  45.705 +	<transaction>
  45.706 +	    <install name="zsh"/>
  45.707 +	</transaction>
  45.708 +	<result>
  45.709 +	    <set>
  45.710 +		<package name="zip" version="1-3" arch="x86_64"/>
  45.711 +		<package name="zsh" version="1-3" arch="i386"/>
  45.712 +	    </set>
  45.713 +	</result>
  45.714 +    </test>
  45.715 +
  45.716 +    <test name="testUpdateSinglePackageObsoletesOldRequirement">
  45.717 +	<set name="system">
  45.718 +	    <package name="zsh" version="1-1" arch="i386">
  45.719 +		<requires name="zip"/>
  45.720 +	    </package>
  45.721 +	    <package name="zip" version="1-1" arch="i386"/>
  45.722 +	</set>
  45.723 +	<set name="repo">
  45.724 +	    <package name="zsh" version="1-3" arch="i386">
  45.725 +		<!-- depsolvetests.py actually adds the obsoletes
  45.726 +		     to the installed zsh rather than the new zsh,
  45.727 +		     but I'm assuming that's a bug -->
  45.728 +		<obsoletes name="zip"/>
  45.729 +	    </package>
  45.730 +	</set>
  45.731 +	<transaction>
  45.732 +	    <install name="zsh"/>
  45.733 +	</transaction>
  45.734 +	<result>
  45.735 +	    <set>
  45.736 +		<package name="zsh" version="1-3" arch="i386"/>
  45.737 +	    </set>
  45.738 +	</result>
  45.739 +    </test>
  45.740 +
  45.741 +    <test name="testUpdateForConflict">
  45.742 +	<set name="system">
  45.743 +	    <package name="zip" version="0:1-1" arch="i386"/>
  45.744 +	</set>
  45.745 +	<set name="repo">
  45.746 +	    <package name="zsh" version="0:1-1" arch="i386">
  45.747 +		<conflicts name="zip" relation="LE" version="0:1-1"/>
  45.748 +	    </package>
  45.749 +	    <package name="zip" version="0:2-1" arch="i386"/>
  45.750 +	</set>
  45.751 +	<transaction>
  45.752 +	    <install name="zsh"/>
  45.753 +	</transaction>
  45.754 +	<result>
  45.755 +	    <set>
  45.756 +		<package name="zip" version="0:2-1" arch="i386"/>
  45.757 +		<package name="zsh" version="0:1-1" arch="i386"/>
  45.758 +	    </set>
  45.759 +	</result>
  45.760 +    </test>
  45.761 +
  45.762 +    <test name="testUpdateForConflict2">
  45.763 +	<set name="system">
  45.764 +	    <package name="zip" version="0:1-1" arch="i386">
  45.765 +		<conflicts name="zsh" relation="LE" version="0:1-1"/>
  45.766 +	    </package>
  45.767 +	</set>
  45.768 +	<set name="repo">
  45.769 +	    <package name="zsh" version="0:1-1" arch="i386"/>
  45.770 +	    <package name="zip" version="0:2-1" arch="i386"/>
  45.771 +	</set>
  45.772 +	<transaction>
  45.773 +	    <install name="zsh"/>
  45.774 +	</transaction>
  45.775 +	<result>
  45.776 +	    <set>
  45.777 +		<package name="zsh" version="0:1-1" arch="i386"/>
  45.778 +		<package name="zip" version="0:2-1" arch="i386"/>
  45.779 +	    </set>
  45.780 +	</result>
  45.781 +    </test>
  45.782 +
  45.783 +    <test name="testUpdateForConflictProvide">
  45.784 +	<set name="system">
  45.785 +	    <package name="zip" version="0:1-1" arch="i386">
  45.786 +		<provides name="zippy" relation="EQ" version="0:1-1"/>
  45.787 +	    </package>
  45.788 +	</set>
  45.789 +	<set name="repo">
  45.790 +	    <package name="zsh" version="0:1-1" arch="i386">
  45.791 +		<conflicts name="zippy" relation="LE" version="0:1-1"/>
  45.792 +	    </package>
  45.793 +	    <package name="zip" version="0:2-1" arch="i386"/>
  45.794 +	</set>
  45.795 +	<transaction>
  45.796 +	    <install name="zsh"/>
  45.797 +	</transaction>
  45.798 +	<result>
  45.799 +	    <set>
  45.800 +		<package name="zip" version="0:2-1" arch="i386"/>
  45.801 +		<package name="zsh" version="0:1-1" arch="i386"/>
  45.802 +	    </set>
  45.803 +	</result>
  45.804 +    </test>
  45.805 +
  45.806 +    <test name="testUpdateForConflictProvide2">
  45.807 +	<set name="system">
  45.808 +	    <package name="zip" version="0:1-1" arch="i386">
  45.809 +		<conflicts name="zippy" relation="GT" version="0:1-1"/>
  45.810 +		<conflicts name="zippy" relation="LT" version="0:1-1"/>
  45.811 +	    </package>
  45.812 +	</set>
  45.813 +	<set name="repo">
  45.814 +	    <package name="zsh" version="0:1-1" arch="i386">
  45.815 +		<provides name="zippy" relation="EQ" version="0:2-1"/>
  45.816 +	    </package>
  45.817 +	    <package name="zip" version="0:2-1" arch="i386">
  45.818 +		<conflicts name="zippy" relation="GT" version="0:2-1"/>
  45.819 +		<conflicts name="zippy" relation="LT" version="0:2-1"/>
  45.820 +	    </package>
  45.821 +	</set>
  45.822 +	<transaction>
  45.823 +	    <install name="zsh"/>
  45.824 +	</transaction>
  45.825 +	<result>
  45.826 +	    <set>
  45.827 +		<package name="zip" version="0:2-1" arch="i386"/>
  45.828 +		<package name="zsh" version="0:1-1" arch="i386"/>
  45.829 +	    </set>
  45.830 +	</result>
  45.831 +    </test>
  45.832 +
  45.833 +    <test name="testEraseSinglePackage">
  45.834 +	<set name="system">
  45.835 +	    <package name="zsh" version="0:1-1" arch="i386"/>
  45.836 +	</set>
  45.837 +	<set name="repo"/>
  45.838 +	<transaction>
  45.839 +	    <remove name="zsh"/>
  45.840 +	</transaction>
  45.841 +	<result>
  45.842 +	    <set/>
  45.843 +	</result>
  45.844 +    </test>
  45.845 +
  45.846 +    <test name="testEraseSinglePackageRequiredByOneInstalled">
  45.847 +	<set name="system">
  45.848 +	    <package name="zippy" version="0:1-1" arch="i386">
  45.849 +		<requires name="zsh"/>
  45.850 +	    </package>
  45.851 +	    <package name="zsh" version="0:1-1" arch="i386"/>
  45.852 +	</set>
  45.853 +	<set name="repo"/>
  45.854 +	<transaction>
  45.855 +	    <remove name="zsh"/>
  45.856 +	</transaction>
  45.857 +	<result>
  45.858 +	    <set/>
  45.859 +	</result>
  45.860 +    </test>
  45.861 +</tests>
    46.1 --- a/test-driver.c	Sun Jun 15 18:16:20 2008 -0400
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,461 +0,0 @@
    46.4 -#include <stdio.h>
    46.5 -#include <string.h>
    46.6 -#include <stdarg.h>
    46.7 -#include <unistd.h>
    46.8 -#include <fcntl.h>
    46.9 -#include <errno.h>
   46.10 -#include <expat.h>
   46.11 -
   46.12 -#include "razor.h"
   46.13 -
   46.14 -#define XML_BUFFER_SIZE 4096
   46.15 -
   46.16 -static void
   46.17 -parse_xml_file(const char *filename,
   46.18 -	       XML_StartElementHandler start,
   46.19 -	       XML_EndElementHandler end,
   46.20 -	       void *data)
   46.21 -{
   46.22 -	XML_Parser parser;
   46.23 -	char *buffer;
   46.24 -	int fd, len, err;
   46.25 -
   46.26 -	parser = XML_ParserCreate(NULL);
   46.27 -	XML_SetElementHandler(parser, start, end);
   46.28 -	XML_SetUserData(parser, data);
   46.29 -
   46.30 -	fd = open(filename, O_RDONLY);
   46.31 -	if (fd < 0) {
   46.32 -		fprintf(stderr, "failed to open %s: %m\n", filename);
   46.33 -		exit(-1);
   46.34 -	}
   46.35 -
   46.36 -	while (1) {
   46.37 -		buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
   46.38 -		len = read(fd, buffer, XML_BUFFER_SIZE);
   46.39 -		if (len == 0)
   46.40 -			break;
   46.41 -		err = XML_ParseBuffer(parser, len, len == 0);
   46.42 -		if (err == XML_STATUS_ERROR) {
   46.43 -			fprintf(stderr, "parse error at line %lu:\n%s\n",
   46.44 -				XML_GetCurrentLineNumber(parser),
   46.45 -				XML_ErrorString(XML_GetErrorCode(parser)));
   46.46 -			exit(-1);
   46.47 -		}
   46.48 -	}
   46.49 -
   46.50 -	if (fd < 0) {
   46.51 -		fprintf(stderr, "read: %m\n");
   46.52 -		exit(-1);
   46.53 -	}
   46.54 -
   46.55 -	close(fd);
   46.56 -}
   46.57 -
   46.58 -struct test_context {
   46.59 -	struct razor_set *system_set, *repo_set, *result_set;
   46.60 -
   46.61 -	struct razor_importer *importer;
   46.62 -	struct razor_set **importer_set;
   46.63 -
   46.64 -	struct razor_transaction *trans;
   46.65 -
   46.66 -	char *install_pkgs[3], *remove_pkgs[3];
   46.67 -	int n_install_pkgs, n_remove_pkgs;
   46.68 -
   46.69 -	int unsat;
   46.70 -	int in_result;
   46.71 -
   46.72 -	int debug, errors;
   46.73 -};
   46.74 -
   46.75 -static void
   46.76 -get_atts(const char **atts, ...)
   46.77 -{
   46.78 -	va_list ap;
   46.79 -	const char *name, **ptr;
   46.80 -	int i;
   46.81 -
   46.82 -	va_start(ap, atts);
   46.83 -	while (name = va_arg(ap, const char *), name != NULL) {
   46.84 -		ptr = va_arg(ap, const char **);
   46.85 -		*ptr = NULL;
   46.86 -		for (i = 0; atts[i]; i += 2) {
   46.87 -			if (strcmp(atts[i], name) == 0)
   46.88 -				*ptr = atts[i + 1];
   46.89 -		}
   46.90 -	}
   46.91 -	va_end(ap);
   46.92 -}
   46.93 -
   46.94 -static enum razor_version_relation
   46.95 -parse_relation (const char *rel_str)
   46.96 -{
   46.97 -	if (!rel_str)
   46.98 -		return -1;
   46.99 -	if (rel_str[0] == 'L')
  46.100 -		return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
  46.101 -	else if (rel_str[0] == 'G')
  46.102 -		return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
  46.103 -	else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
  46.104 -		return RAZOR_VERSION_EQUAL;
  46.105 -	else
  46.106 -		return -1;
  46.107 -}
  46.108 -
  46.109 -static void
  46.110 -start_test(struct test_context *ctx, const char **atts)
  46.111 -{
  46.112 -	const char *name = NULL;
  46.113 -
  46.114 -	get_atts(atts, "name", &name, NULL);
  46.115 -	if (!name) {
  46.116 -		fprintf(stderr, "Test with no name\n");
  46.117 -		exit(1);
  46.118 -	}
  46.119 -	printf("%s\n", name);
  46.120 -}
  46.121 -
  46.122 -static void
  46.123 -end_test(struct test_context *ctx)
  46.124 -{
  46.125 -	if (ctx->system_set) {
  46.126 -		razor_set_destroy(ctx->system_set);
  46.127 -		ctx->system_set = NULL;
  46.128 -	}
  46.129 -	if (ctx->repo_set) {
  46.130 -		razor_set_destroy(ctx->repo_set);
  46.131 -		ctx->repo_set = NULL;
  46.132 -	}
  46.133 -	if (ctx->result_set) {
  46.134 -		razor_set_destroy(ctx->result_set);
  46.135 -		ctx->result_set = NULL;
  46.136 -	}
  46.137 -	if (ctx->trans) {
  46.138 -		razor_transaction_destroy(ctx->trans);
  46.139 -		ctx->trans = NULL;
  46.140 -	}
  46.141 -}
  46.142 -
  46.143 -static void
  46.144 -start_set(struct test_context *ctx, const char **atts)
  46.145 -{
  46.146 -	const char *name = NULL;
  46.147 -
  46.148 -	ctx->importer = razor_importer_new();
  46.149 -	get_atts(atts, "name", &name, NULL);
  46.150 -	if (!name)
  46.151 -		ctx->importer_set = &ctx->result_set;
  46.152 -	else if (!strcmp(name, "system"))
  46.153 -		ctx->importer_set = &ctx->system_set;
  46.154 -	else if (!strcmp(name, "repo"))
  46.155 -		ctx->importer_set = &ctx->repo_set;
  46.156 -	else {
  46.157 -		fprintf(stderr, "  bad set name '%s'\n", name);
  46.158 -		exit(1);
  46.159 -	}
  46.160 -}
  46.161 -
  46.162 -static void
  46.163 -end_set(struct test_context *ctx)
  46.164 -{
  46.165 -	*ctx->importer_set = razor_importer_finish(ctx->importer);
  46.166 -	ctx->importer = NULL;
  46.167 -}
  46.168 -
  46.169 -static void
  46.170 -start_package(struct test_context *ctx, const char **atts)
  46.171 -{
  46.172 -	const char *name = NULL, *version = NULL, *arch = NULL;
  46.173 -
  46.174 -	get_atts(atts, "name", &name,
  46.175 -		 "version", &version,
  46.176 -		 "arch", &arch,
  46.177 -		 NULL);
  46.178 -
  46.179 -	if (!name) {
  46.180 -		fprintf(stderr, "  package with no name\n");
  46.181 -		exit(1);
  46.182 -	}
  46.183 -
  46.184 -	razor_importer_begin_package(ctx->importer, name, version, arch);
  46.185 -	razor_importer_add_property(ctx->importer, name,
  46.186 -				    RAZOR_VERSION_EQUAL, version,
  46.187 -				    RAZOR_PROPERTY_PROVIDES);
  46.188 -}
  46.189 -
  46.190 -static void
  46.191 -end_package(struct test_context *ctx)
  46.192 -{
  46.193 -	razor_importer_finish_package(ctx->importer);
  46.194 -}
  46.195 -
  46.196 -static void
  46.197 -add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
  46.198 -{
  46.199 -	razor_importer_add_property(ctx->importer, name,
  46.200 -				    rel, version, type);
  46.201 -}
  46.202 -
  46.203 -static void
  46.204 -check_unsatisfiable_property(struct test_context *ctx,
  46.205 -			     enum razor_property_type type,
  46.206 -			     const char *name,
  46.207 -			     enum razor_version_relation rel,
  46.208 -			     const char *version)
  46.209 -{
  46.210 -	if (!version)
  46.211 -		version = "";
  46.212 -
  46.213 -	if (razor_transaction_unsatisfied_property(ctx->trans,
  46.214 -						   name, rel, version))
  46.215 -		return;
  46.216 -
  46.217 -	fprintf(stderr, "  didn't get unsatisfiable '%s %s %s'\n",
  46.218 -		name, razor_version_relations[rel], version);
  46.219 -	ctx->errors++;
  46.220 -}
  46.221 -
  46.222 -static void
  46.223 -start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
  46.224 -{
  46.225 -	const char *name = NULL, *rel_str = NULL, *version = NULL;
  46.226 -	enum razor_version_relation rel;
  46.227 -
  46.228 -	get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
  46.229 -	if (name == NULL) {
  46.230 -		fprintf(stderr, "  no name specified for property\n");
  46.231 -		exit(1);
  46.232 -	}
  46.233 -	if (version) {
  46.234 -		rel = parse_relation(rel_str);
  46.235 -		if (rel == -1) {
  46.236 -			fprintf(stderr, "  bad or missing version relation for property %s\n", name);
  46.237 -			exit(1);
  46.238 -		}
  46.239 -	} else
  46.240 -		rel = RAZOR_VERSION_EQUAL;
  46.241 -	
  46.242 -	if (ctx->unsat)
  46.243 -		check_unsatisfiable_property(ctx, type, name, rel, version);
  46.244 -	else
  46.245 -		add_property(ctx, type, name, rel, version);
  46.246 -}
  46.247 -
  46.248 -static void
  46.249 -start_transaction(struct test_context *ctx, const char **atts)
  46.250 -{
  46.251 -	ctx->n_install_pkgs = 0;
  46.252 -	ctx->n_remove_pkgs = 0;
  46.253 -}
  46.254 -
  46.255 -static void
  46.256 -end_transaction(struct test_context *ctx)
  46.257 -{
  46.258 -	struct razor_package *pkg;
  46.259 -	int errors, i;
  46.260 -
  46.261 -	ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
  46.262 -	for (i = 0; i < ctx->n_install_pkgs; i++) {
  46.263 -		pkg = razor_set_get_package(ctx->repo_set,
  46.264 -					    ctx->install_pkgs[i]);
  46.265 -		razor_transaction_install_package(ctx->trans, pkg);
  46.266 -	}		
  46.267 -	for (i = 0; i < ctx->n_remove_pkgs; i++) {
  46.268 -		pkg = razor_set_get_package(ctx->system_set,
  46.269 -					    ctx->remove_pkgs[i]);
  46.270 -		if (!pkg)
  46.271 -			pkg = razor_set_get_package(ctx->repo_set,
  46.272 -						    ctx->remove_pkgs[i]);
  46.273 -
  46.274 -		razor_transaction_remove_package(ctx->trans, pkg);
  46.275 -	}		
  46.276 -
  46.277 -	errors = razor_transaction_resolve(ctx->trans);
  46.278 -	printf("\n");
  46.279 -
  46.280 -	while (ctx->n_install_pkgs--)
  46.281 -		free(ctx->install_pkgs[ctx->n_install_pkgs]);
  46.282 -	while (ctx->n_remove_pkgs--)
  46.283 -		free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
  46.284 -
  46.285 -	if (!errors) {
  46.286 -		struct razor_set *new;
  46.287 -		new = razor_transaction_finish(ctx->trans);
  46.288 -		ctx->trans = NULL;
  46.289 -		ctx->system_set = new;
  46.290 -	}
  46.291 -}
  46.292 -
  46.293 -static void
  46.294 -start_install_or_update(struct test_context *ctx, const char **atts)
  46.295 -{
  46.296 -	const char *name = NULL;
  46.297 -
  46.298 -	get_atts(atts, "name", &name, NULL);
  46.299 -	if (!name) {
  46.300 -		fprintf(stderr, "  install/update with no name\n");
  46.301 -		exit(1);
  46.302 -	}
  46.303 -
  46.304 -	ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
  46.305 -}
  46.306 -
  46.307 -static void
  46.308 -start_remove(struct test_context *ctx, const char **atts)
  46.309 -{
  46.310 -	const char *name = NULL;
  46.311 -
  46.312 -	get_atts(atts, "name", &name, NULL);
  46.313 -	if (!name) {
  46.314 -		fprintf(stderr, "  remove with no name\n");
  46.315 -		exit(1);
  46.316 -	}
  46.317 -
  46.318 -	ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
  46.319 -}
  46.320 -
  46.321 -static void
  46.322 -start_result(struct test_context *ctx, const char **atts)
  46.323 -{
  46.324 -	ctx->in_result = 1;
  46.325 -}
  46.326 -
  46.327 -static void
  46.328 -diff_callback(const char *name,
  46.329 -	      const char *old_version,
  46.330 -	      const char *new_version,
  46.331 -	      const char *arch,
  46.332 -	      void *data)
  46.333 -{
  46.334 -	struct test_context *ctx = data;
  46.335 -
  46.336 -	ctx->errors++;
  46.337 -	if (old_version) {
  46.338 -		fprintf(stderr, "  result set should not contain %s %s\n",
  46.339 -			name, old_version);
  46.340 -	} else {
  46.341 -		fprintf(stderr, "  result set should contain %s %s\n",
  46.342 -			name, new_version);
  46.343 -	}
  46.344 -}
  46.345 -
  46.346 -static void
  46.347 -end_result(struct test_context *ctx)
  46.348 -{
  46.349 -	ctx->in_result = 0;
  46.350 -
  46.351 -	if (ctx->result_set) {
  46.352 -		if (!ctx->system_set)
  46.353 -			ctx->system_set = razor_set_create();
  46.354 -		razor_set_diff(ctx->system_set, ctx->result_set,
  46.355 -			       diff_callback, ctx);
  46.356 -	}
  46.357 -}
  46.358 -
  46.359 -static void
  46.360 -start_unsatisfiable(struct test_context *ctx, const char **atts)
  46.361 -{
  46.362 -	if (ctx->result_set) {
  46.363 -		fprintf(stderr, "Expected to fail, but didn't\n");
  46.364 -		exit(1);
  46.365 -	}
  46.366 -
  46.367 -	ctx->unsat = 1;
  46.368 -}
  46.369 -
  46.370 -static void
  46.371 -end_unsatisfiable(struct test_context *ctx)
  46.372 -{
  46.373 -	ctx->unsat = 0;
  46.374 -}
  46.375 -
  46.376 -static void
  46.377 -start_test_element(void *data, const char *element, const char **atts)
  46.378 -{
  46.379 -	struct test_context *ctx = data;
  46.380 -
  46.381 -	if (strcmp(element, "tests") == 0) {
  46.382 -		;
  46.383 -	} else if (strcmp(element, "test") == 0) {
  46.384 -		start_test(ctx, atts);
  46.385 -	} else if (strcmp(element, "set") == 0) {
  46.386 -		start_set(ctx, atts);
  46.387 -	} else if (strcmp(element, "transaction") == 0) {
  46.388 -		start_transaction(ctx, atts);
  46.389 -	} else if (strcmp(element, "install") == 0) {
  46.390 -		start_install_or_update(ctx, atts);
  46.391 -	} else if (strcmp(element, "install") == 0) {
  46.392 -		start_install_or_update(ctx, atts);
  46.393 -	} else if (strcmp(element, "remove") == 0) {
  46.394 -		start_remove(ctx, atts);
  46.395 -	} else if (strcmp(element, "result") == 0) {
  46.396 -		start_result(ctx, atts);
  46.397 -	} else if (strcmp(element, "unsatisfiable") == 0) {
  46.398 -		start_unsatisfiable(ctx, atts);
  46.399 -	} else if (strcmp(element, "package") == 0) {
  46.400 -		start_package(ctx, atts);
  46.401 -	} else if (strcmp(element, "requires") == 0) {
  46.402 -		start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
  46.403 -	} else if (strcmp(element, "provides") == 0) {
  46.404 -		start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
  46.405 -	} else if (strcmp(element, "conflicts") == 0) {
  46.406 -		start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
  46.407 -	} else if (strcmp(element, "obsoletes") == 0) {
  46.408 -		start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
  46.409 -	} else {
  46.410 -		fprintf(stderr, "Unrecognized element '%s'\n", element);
  46.411 -		exit(1);
  46.412 -	}
  46.413 -}
  46.414 -
  46.415 -static void
  46.416 -end_test_element (void *data, const char *element)
  46.417 -{
  46.418 -	struct test_context *ctx = data;
  46.419 -
  46.420 -	if (strcmp(element, "test") == 0) {
  46.421 -		end_test(ctx);
  46.422 -	} else if (strcmp(element, "set") == 0) {
  46.423 -		end_set(ctx);
  46.424 -	} else if (strcmp(element, "package") == 0) {
  46.425 -		end_package(ctx);
  46.426 -	} else if (strcmp(element, "transaction") == 0) {
  46.427 -		end_transaction(ctx);
  46.428 -	} else if (strcmp(element, "result") == 0) {
  46.429 -		end_result(ctx);
  46.430 -	} else if (strcmp(element, "unsatisfiable") == 0) {
  46.431 -		end_unsatisfiable(ctx);
  46.432 -	}
  46.433 -}
  46.434 -
  46.435 -int main(int argc, char *argv[])
  46.436 -{
  46.437 -	struct test_context ctx;
  46.438 -	const char *test_file;
  46.439 -
  46.440 -	memset(&ctx, 0, sizeof ctx);
  46.441 -
  46.442 -	if (argc > 3) {
  46.443 -		fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
  46.444 -		exit(-1);			
  46.445 -	}
  46.446 -
  46.447 -	if (argc >= 2 && !strcmp (argv[1], "-d")) {
  46.448 -		ctx.debug = 1;
  46.449 -		argc--;
  46.450 -		argv++;
  46.451 -	}
  46.452 -	if (argc == 2)
  46.453 -		test_file = argv[1];
  46.454 -	else
  46.455 -		test_file = "test.xml";
  46.456 -
  46.457 -	parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
  46.458 -
  46.459 -	if (ctx.errors) {
  46.460 -		fprintf(stderr, "\n%d errors\n", ctx.errors);
  46.461 -		return 1;
  46.462 -	} else
  46.463 -		return 0;
  46.464 -}
    47.1 --- a/test.xml	Sun Jun 15 18:16:20 2008 -0400
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,858 +0,0 @@
    47.4 -<tests>
    47.5 -
    47.6 -    <test name="testEmpty">
    47.7 -	<set name="system"/>
    47.8 -	<set name="repo">
    47.9 -	    <package name="zsh" version="1-1" arch="i386"/>
   47.10 -	</set>
   47.11 -	<transaction>
   47.12 -	    <install name="zsh"/>
   47.13 -	    <remove name="zsh"/>
   47.14 -	</transaction>
   47.15 -	<result>
   47.16 -	    <set/>
   47.17 -	</result>
   47.18 -    </test>
   47.19 -
   47.20 -    <test name="testInstallSinglePackageNoRequires">
   47.21 -	<set name="system"/>
   47.22 -	<set name="repo">
   47.23 -	    <package name="zsh" version="1-1" arch="i386"/>
   47.24 -	</set>
   47.25 -	<transaction>
   47.26 -	    <install name="zsh"/>
   47.27 -	</transaction>
   47.28 -	<result>
   47.29 -	    <set>
   47.30 -		<package name="zsh" version="1-1" arch="i386"/>
   47.31 -	    </set>
   47.32 -	</result>
   47.33 -    </test>
   47.34 -
   47.35 -    <test name="testInstallSinglePackageRequireNotProvided">
   47.36 -	<set name="system"/>
   47.37 -	<set name="repo">
   47.38 -	    <package name="zsh" version="1-1" arch="i386">
   47.39 -		<requires name="zip"/>
   47.40 -	    </package>
   47.41 -	</set>
   47.42 -	<transaction>
   47.43 -	    <install name="zsh"/>
   47.44 -	</transaction>
   47.45 -	<result>
   47.46 -	    <unsatisfiable>
   47.47 -		<requires name="zip"/>
   47.48 -	    </unsatisfiable>
   47.49 -	</result>
   47.50 -    </test>
   47.51 -
   47.52 -    <test name="testInstallSinglePackageRequireInstalled">
   47.53 -	<set name="system">
   47.54 -	    <package name="zip" version="1-1" arch="i386"/>
   47.55 -	</set>
   47.56 -	<set name="repo">
   47.57 -	    <package name="zsh" version="1-1" arch="i386">
   47.58 -		<requires name="zip"/>
   47.59 -	    </package>
   47.60 -	</set>
   47.61 -	<transaction>
   47.62 -	    <install name="zsh"/>
   47.63 -	</transaction>
   47.64 -	<result>
   47.65 -	    <set>
   47.66 -		<package name="zip" version="1-1" arch="i386"/>
   47.67 -		<package name="zsh" version="1-1" arch="i386"/>
   47.68 -	    </set>
   47.69 -	</result>
   47.70 -    </test>
   47.71 -
   47.72 -    <test name="testInstallSinglePackageRequireInstalledRequireNotProvided">
   47.73 -	<set name="system">
   47.74 -	    <package name="zip" version="1-2" arch="i386"/>
   47.75 -	</set>
   47.76 -	<set name="repo">
   47.77 -	    <package name="zsh" version="1-1" arch="i386">
   47.78 -		<requires name="zip"/>
   47.79 -		<!-- This may be a bug in the python test: it looks
   47.80 -		     like they meant to have zip require zap, not zsh.
   47.81 -		     But the install succeeds if you do that...
   47.82 -		  -->
   47.83 -		<requires name="zap"/>
   47.84 -	    </package>
   47.85 -	</set>
   47.86 -	<transaction>
   47.87 -	    <install name="zsh"/>
   47.88 -	</transaction>
   47.89 -	<result>
   47.90 -	    <unsatisfiable>
   47.91 -		<requires name="zap"/>
   47.92 -	    </unsatisfiable>
   47.93 -	</result>
   47.94 -    </test>
   47.95 -
   47.96 -    <test name="testInstallSinglePackageRequireInstalledRequireInstall">
   47.97 -	<set name="system">
   47.98 -	    <package name="zip" version="1-3" arch="i386">
   47.99 -		<requires name="zap"/>
  47.100 -	    </package>
  47.101 -	</set>
  47.102 -	<set name="repo">
  47.103 -	    <package name="zsh" version="1-1" arch="i386">
  47.104 -		<requires name="zip"/>
  47.105 -	    </package>
  47.106 -	    <package name="zap" version="1-2" arch="i386"/>
  47.107 -	</set>
  47.108 -	<transaction>
  47.109 -	    <install name="zsh"/>
  47.110 -	    <install name="zap"/>
  47.111 -	</transaction>
  47.112 -	<result>
  47.113 -	    <set>
  47.114 -		<package name="zap" version="1-2" arch="i386"/>
  47.115 -		<package name="zip" version="1-3" arch="i386"/>
  47.116 -		<package name="zsh" version="1-1" arch="i386"/>
  47.117 -	    </set>
  47.118 -	</result>
  47.119 -    </test>
  47.120 -
  47.121 -    <test name="testInstallSinglePackageRequireVer1NotProvided">
  47.122 -	<set name="system">
  47.123 -	    <package name="zip" version="1.0-2" arch="i386"/>
  47.124 -	</set>
  47.125 -	<set name="repo">
  47.126 -	    <package name="zsh" version="1-1" arch="i386">
  47.127 -		<requires name="zip" relation="EQ" version="1.3-2"/>
  47.128 -	    </package>
  47.129 -	</set>
  47.130 -	<transaction>
  47.131 -	    <install name="zsh"/>
  47.132 -	</transaction>
  47.133 -	<result>
  47.134 -	    <unsatisfiable>
  47.135 -		<requires name="zip" relation="EQ" version="1.3-2"/>
  47.136 -	    </unsatisfiable>
  47.137 -	</result>
  47.138 -    </test>
  47.139 -
  47.140 -    <test name="testInstallSinglePackageRequireVer1Installed">
  47.141 -	<set name="system">
  47.142 -	    <package name="zip" version="1.3-2" arch="i386"/>
  47.143 -	</set>
  47.144 -	<set name="repo">
  47.145 -	    <package name="zsh" version="1-1" arch="i386">
  47.146 -		<requires name="zip" relation="EQ" version="1.3-2"/>
  47.147 -	    </package>
  47.148 -	</set>
  47.149 -	<transaction>
  47.150 -	    <install name="zsh"/>
  47.151 -	</transaction>
  47.152 -	<result>
  47.153 -	    <set>
  47.154 -		<package name="zip" version="1.3-2" arch="i386"/>
  47.155 -		<package name="zsh" version="1-1" arch="i386"/>
  47.156 -	    </set>
  47.157 -	</result>
  47.158 -    </test>
  47.159 -
  47.160 -    <test name="testInstallSinglePackageRequireVer2NotProvided">
  47.161 -	<set name="system">
  47.162 -	    <package name="zip" version="1.3-2" arch="i386"/>
  47.163 -	</set>
  47.164 -	<set name="repo">
  47.165 -	    <package name="zsh" version="1-1" arch="i386">
  47.166 -		<requires name="zip" relation="EQ" version="1.3-4"/>
  47.167 -	    </package>
  47.168 -	</set>
  47.169 -	<transaction>
  47.170 -	    <install name="zsh"/>
  47.171 -	</transaction>
  47.172 -	<result>
  47.173 -	    <unsatisfiable>
  47.174 -		<requires name="zip" relation="EQ" version="1.3-4"/>
  47.175 -	    </unsatisfiable>
  47.176 -	</result>
  47.177 -    </test>
  47.178 -
  47.179 -    <test name="testInstallSinglePackageRequireVer2Installed">
  47.180 -	<set name="system">
  47.181 -	    <package name="zip" version="1.3-4" arch="i386"/>
  47.182 -	</set>
  47.183 -	<set name="repo">
  47.184 -	    <package name="zsh" version="1-1" arch="i386">
  47.185 -		<requires name="zip" relation="EQ" version="1.3-4"/>
  47.186 -	    </package>
  47.187 -	</set>
  47.188 -	<transaction>
  47.189 -	    <install name="zsh"/>
  47.190 -	</transaction>
  47.191 -	<result>
  47.192 -	    <set>
  47.193 -		<package name="zip" version="1.3-4" arch="i386"/>
  47.194 -		<package name="zsh" version="1-1" arch="i386"/>
  47.195 -	    </set>
  47.196 -	</result>
  47.197 -    </test>
  47.198 -
  47.199 -    <test name="testInstallSinglePackageRequireVer3NotProvided">
  47.200 -	<set name="system">
  47.201 -	    <package name="zip" version="0:1.3-4" arch="i386"/>
  47.202 -	</set>
  47.203 -	<set name="repo">
  47.204 -	    <package name="zsh" version="1-1" arch="i386">
  47.205 -		<requires name="zip" relation="GE" version="1:1.3-4"/>
  47.206 -	    </package>
  47.207 -	</set>
  47.208 -	<transaction>
  47.209 -	    <install name="zsh"/>
  47.210 -	</transaction>
  47.211 -	<result>
  47.212 -	    <unsatisfiable>
  47.213 -		<requires name="zip" relation="GE" version="1:1.3-4"/>
  47.214 -	    </unsatisfiable>
  47.215 -	</result>
  47.216 -    </test>
  47.217 -
  47.218 -    <test name="testInstallSinglePackageRequireVer3Installed">
  47.219 -	<set name="system">
  47.220 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  47.221 -	</set>
  47.222 -	<set name="repo">
  47.223 -	    <package name="zsh" version="1-1" arch="i386">
  47.224 -		<requires name="zip" relation="GE" version="2:1.3-4"/>
  47.225 -	    </package>
  47.226 -	</set>
  47.227 -	<transaction>
  47.228 -	    <install name="zsh"/>
  47.229 -	</transaction>
  47.230 -	<result>
  47.231 -	    <set>
  47.232 -		<package name="zip" version="2:1.3-4" arch="i386"/>
  47.233 -		<package name="zsh" version="1-1" arch="i386"/>
  47.234 -	    </set>
  47.235 -	</result>
  47.236 -    </test>
  47.237 -
  47.238 -    <test name="testInstallSinglePackageRequireVer4NotProvided">
  47.239 -	<set name="system">
  47.240 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  47.241 -	</set>
  47.242 -	<set name="repo">
  47.243 -	    <package name="zsh" version="1-1" arch="i386">
  47.244 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.245 -	    </package>
  47.246 -	</set>
  47.247 -	<transaction>
  47.248 -	    <install name="zsh"/>
  47.249 -	</transaction>
  47.250 -	<result>
  47.251 -	    <unsatisfiable>
  47.252 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.253 -	    </unsatisfiable>
  47.254 -	</result>
  47.255 -    </test>
  47.256 -
  47.257 -    <test name="testInstallSinglePackageRequireVer4_1Installed">
  47.258 -	<set name="system">
  47.259 -	    <package name="zip" version="2:1.0-4" arch="i386"/>
  47.260 -	</set>
  47.261 -	<set name="repo">
  47.262 -	    <package name="zsh" version="1-1" arch="i386">
  47.263 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.264 -	    </package>
  47.265 -	</set>
  47.266 -	<transaction>
  47.267 -	    <install name="zsh"/>
  47.268 -	</transaction>
  47.269 -	<result>
  47.270 -	    <set>
  47.271 -		<package name="zip" version="2:1.0-4" arch="i386"/>
  47.272 -		<package name="zsh" version="1-1" arch="i386"/>
  47.273 -	    </set>
  47.274 -	</result>
  47.275 -    </test>
  47.276 -
  47.277 -    <test name="testInstallSinglePackageRequireVer4_2Installed">
  47.278 -	<set name="system">
  47.279 -	    <package name="zip" version="2:1.3-3" arch="i386"/>
  47.280 -	</set>
  47.281 -	<set name="repo">
  47.282 -	    <package name="zsh" version="1-1" arch="i386">
  47.283 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.284 -	    </package>
  47.285 -	</set>
  47.286 -	<transaction>
  47.287 -	    <install name="zsh"/>
  47.288 -	</transaction>
  47.289 -	<result>
  47.290 -	    <set>
  47.291 -		<package name="zip" version="2:1.3-3" arch="i386"/>
  47.292 -		<package name="zsh" version="1-1" arch="i386"/>
  47.293 -	    </set>
  47.294 -	</result>
  47.295 -    </test>
  47.296 -
  47.297 -    <test name="testInstallSinglePackageRequireVer4_3Installed">
  47.298 -	<set name="system">
  47.299 -	    <package name="zip" version="1.3-4" arch="i386"/>
  47.300 -	</set>
  47.301 -	<set name="repo">
  47.302 -	    <package name="zsh" version="1-1" arch="i386">
  47.303 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.304 -	    </package>
  47.305 -	</set>
  47.306 -	<transaction>
  47.307 -	    <install name="zsh"/>
  47.308 -	</transaction>
  47.309 -	<result>
  47.310 -	    <set>
  47.311 -		<package name="zip" version="1.3-4" arch="i386"/>
  47.312 -		<package name="zsh" version="1-1" arch="i386"/>
  47.313 -	    </set>
  47.314 -	</result>
  47.315 -    </test>
  47.316 -
  47.317 -    <test name="testInstallSinglePackageRequireVer4_4Installed">
  47.318 -	<set name="system">
  47.319 -	    <package name="zip" version="1:1.3-4" arch="i386"/>
  47.320 -	</set>
  47.321 -	<set name="repo">
  47.322 -	    <package name="zsh" version="1-1" arch="i386">
  47.323 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.324 -	    </package>
  47.325 -	</set>
  47.326 -	<transaction>
  47.327 -	    <install name="zsh"/>
  47.328 -	</transaction>
  47.329 -	<result>
  47.330 -	    <set>
  47.331 -		<package name="zip" version="1:1.3-4" arch="i386"/>
  47.332 -		<package name="zsh" version="1-1" arch="i386"/>
  47.333 -	    </set>
  47.334 -	</result>
  47.335 -    </test>
  47.336 -
  47.337 -    <test name="testInstallSinglePackageRequireVer4_5Installed">
  47.338 -	<set name="system">
  47.339 -	    <package name="zip" version="2:0.3-4" arch="i386"/>
  47.340 -	</set>
  47.341 -	<set name="repo">
  47.342 -	    <package name="zsh" version="1-1" arch="i386">
  47.343 -		<requires name="zip" relation="LT" version="2:1.3-4"/>
  47.344 -	    </package>
  47.345 -	</set>
  47.346 -	<transaction>
  47.347 -	    <install name="zsh"/>
  47.348 -	</transaction>
  47.349 -	<result>
  47.350 -	    <set>
  47.351 -		<package name="zip" version="2:0.3-4" arch="i386"/>
  47.352 -		<package name="zsh" version="1-1" arch="i386"/>
  47.353 -	    </set>
  47.354 -	</result>
  47.355 -    </test>
  47.356 -
  47.357 -    <test name="testInstallSinglePackageRequireXtraBadVer">
  47.358 -	<set name="system">
  47.359 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  47.360 -	</set>
  47.361 -	<set name="repo">
  47.362 -	    <package name="zsh" version="1-1" arch="i386">
  47.363 -		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  47.364 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  47.365 -	    </package>
  47.366 -	    <package name="zap" version="0:1.3-4" arch="i386"/>
  47.367 -	</set>
  47.368 -	<transaction>
  47.369 -	    <install name="zsh"/>
  47.370 -	</transaction>
  47.371 -	<result>
  47.372 -	    <unsatisfiable>
  47.373 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  47.374 -	    </unsatisfiable>
  47.375 -	</result>
  47.376 -    </test>
  47.377 -
  47.378 -    <test name="testInstallSinglePackageRequireXtra">
  47.379 -	<set name="system">
  47.380 -	    <package name="zip" version="2:1.3-4" arch="i386"/>
  47.381 -	</set>
  47.382 -	<set name="repo">
  47.383 -	    <package name="zsh" version="1-1" arch="i386">
  47.384 -		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  47.385 -		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  47.386 -	    </package>
  47.387 -	    <package name="zap" version="4:2.6-8" arch="i386"/>
  47.388 -	</set>
  47.389 -	<transaction>
  47.390 -	    <install name="zsh"/>
  47.391 -	</transaction>
  47.392 -	<result>
  47.393 -	    <set>
  47.394 -		<package name="zap" version="4:2.6-8" arch="i386"/>
  47.395 -		<package name="zip" version="2:1.3-4" arch="i386"/>
  47.396 -		<package name="zsh" version="1-1" arch="i386"/>
  47.397 -	    </set>
  47.398 -	</result>
  47.399 -    </test>
  47.400 -
  47.401 -    <test name="testInstallSinglePackageRequireInstalledRequireXtra">
  47.402 -	<set name="system">
  47.403 -	    <package name="zip" version="2:1.3-4" arch="i386">
  47.404 -		<requires name="zap" relation="EQ" version="4:2.6-8"/>
  47.405 -	    </package>
  47.406 -	</set>
  47.407 -	<set name="repo">
  47.408 -	    <package name="zsh" version="1-1" arch="i386">
  47.409 -		<requires name="zip" relation="EQ" version="2:1.3-4"/>
  47.410 -	    </package>
  47.411 -	    <!-- This may be a bug in the python test; it doesn't
  47.412 -	         actually matter whether or not zap is available
  47.413 -	      -->
  47.414 -	    <package name="zap" version="4:2.6-8" arch="i386"/>
  47.415 -	</set>
  47.416 -	<transaction>
  47.417 -	    <install name="zsh"/>
  47.418 -	</transaction>
  47.419 -	<result>
  47.420 -	    <set>
  47.421 -		<package name="zip" version="2:1.3-4" arch="i386"/>
  47.422 -		<package name="zsh" version="1-1" arch="i386"/>
  47.423 -	    </set>
  47.424 -	</result>
  47.425 -    </test>
  47.426 -
  47.427 -    <test name="testInstallSinglePackageRequireUpgradeRequireXtraErr">
  47.428 -	<set name="system">
  47.429 -	    <package name="zip" version="2:1.3-4" arch="i386">
  47.430 -		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  47.431 -	    </package>
  47.432 -	</set>
  47.433 -	<set name="repo">
  47.434 -	    <package name="zsh" version="1-1" arch="i386">
  47.435 -		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  47.436 -	    </package>
  47.437 -	    <package name="zip" version="4:2.6-8" arch="i386">
  47.438 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  47.439 -	    </package>
  47.440 -	    <package name="zap" version="2:1.3-4" arch="i386">
  47.441 -		<requires name="zsh" relation="EQ" version="2:4-8"/>
  47.442 -	    </package>
  47.443 -	</set>
  47.444 -	<transaction>
  47.445 -	    <install name="zsh"/>
  47.446 -	</transaction>
  47.447 -	<result>
  47.448 -	    <unsatisfiable>
  47.449 -		<requires name="zsh" relation="EQ" version="2:4-8"/>
  47.450 -	    </unsatisfiable>
  47.451 -	</result>
  47.452 -    </test>
  47.453 -
  47.454 -    <test name="testInstallSinglePackageRequireUpgradeRequireXtraOk">
  47.455 -	<set name="system">
  47.456 -	    <package name="zip" version="2:1.3-4" arch="i386">
  47.457 -		<requires name="zap" relation="EQ" version="2:1.3-3"/>
  47.458 -	    </package>
  47.459 -	</set>
  47.460 -	<set name="repo">
  47.461 -	    <package name="zsh" version="1-1" arch="i386">
  47.462 -		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  47.463 -	    </package>
  47.464 -	    <package name="zip" version="4:2.6-8" arch="i386">
  47.465 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  47.466 -	    </package>
  47.467 -	    <package name="zap" version="2:1.3-4" arch="i386"/>
  47.468 -	</set>
  47.469 -	<transaction>
  47.470 -	    <install name="zsh"/>
  47.471 -	</transaction>
  47.472 -	<result>
  47.473 -	    <set>
  47.474 -		<package name="zap" version="2:1.3-4" arch="i386"/>
  47.475 -		<package name="zip" version="4:2.6-8" arch="i386"/>
  47.476 -		<package name="zsh" version="1-1" arch="i386"/>
  47.477 -	    </set>
  47.478 -	</result>
  47.479 -    </test>
  47.480 -
  47.481 -    <test name="testInstallSinglePackageRequireMultiXtra">
  47.482 -	<set name="system"/>
  47.483 -	<set name="repo">
  47.484 -	    <package name="zsh" version="1-1" arch="i386">
  47.485 -		<requires name="zip" relation="EQ" version="4:2.6-8"/>
  47.486 -	    </package>
  47.487 -	    <package name="zip" version="4:2.6-8" arch="i386">
  47.488 -		<requires name="zap" relation="EQ" version="2:1.3-4"/>
  47.489 -	    </package>
  47.490 -	    <package name="zap" version="2:1.3-4" arch="i386"/>
  47.491 -	</set>
  47.492 -	<transaction>
  47.493 -	    <install name="zsh"/>
  47.494 -	</transaction>
  47.495 -	<result>
  47.496 -	    <set>
  47.497 -		<package name="zap" version="2:1.3-4" arch="i386"/>
  47.498 -		<package name="zip" version="4:2.6-8" arch="i386"/>
  47.499 -		<package name="zsh" version="1-1" arch="i386"/>
  47.500 -	    </set>
  47.501 -	</result>
  47.502 -    </test>
  47.503 -
  47.504 -    <test name="testInstallSinglePackageRequireInstalledMultiLib">
  47.505 -	<set name="system">
  47.506 -	    <package name="zip" version="1-3" arch="i386"/>
  47.507 -	</set>
  47.508 -	<set name="repo">
  47.509 -	    <package name="zsh" version="1-1" arch="x86_64">
  47.510 -		<requires name="zip"/>
  47.511 -	    </package>
  47.512 -	    <package name="zip" version="1-3" arch="x86_64"/>
  47.513 -	</set>
  47.514 -	<transaction>
  47.515 -	    <install name="zsh"/>
  47.516 -	</transaction>
  47.517 -	<result>
  47.518 -	    <set>
  47.519 -		<package name="zip" version="1-3" arch="i386"/>
  47.520 -		<package name="zsh" version="1-1" arch="x86_64"/>
  47.521 -	    </set>
  47.522 -	</result>
  47.523 -    </test>
  47.524 -
  47.525 -    <test name="testInstallSinglePackageRequireXtra1MultiLib">
  47.526 -	<set name="system"/>
  47.527 -	<set name="repo">
  47.528 -	    <package name="zsh" version="1-1" arch="x86_64">
  47.529 -		<requires name="zip"/>
  47.530 -	    </package>
  47.531 -	    <package name="zip" version="1-3" arch="i386"/>
  47.532 -	</set>
  47.533 -	<transaction>
  47.534 -	    <install name="zsh"/>
  47.535 -	</transaction>
  47.536 -	<result>
  47.537 -	    <set>
  47.538 -		<package name="zip" version="1-3" arch="i386"/>
  47.539 -		<package name="zsh" version="1-1" arch="x86_64"/>
  47.540 -	    </set>
  47.541 -	</result>
  47.542 -    </test>
  47.543 -
  47.544 -    <test name="testInstallSinglePackageRequireXtra2_64MultiLib">
  47.545 -	<set name="system"/>
  47.546 -	<set name="repo">
  47.547 -	    <package name="zsh" version="1-1" arch="x86_64">
  47.548 -		<requires name="zip"/>
  47.549 -	    </package>
  47.550 -	    <package name="zip" version="1-3" arch="i386"/>
  47.551 -	    <package name="zip" version="1-3" arch="x86_64"/>
  47.552 -	</set>
  47.553 -	<transaction>
  47.554 -	    <install name="zsh"/>
  47.555 -	</transaction>
  47.556 -	<result>
  47.557 -	    <set>
  47.558 -		<package name="zsh" version="1-1" arch="x86_64"/>
  47.559 -		<package name="zip" version="1-3" arch="x86_64"/>
  47.560 -	    </set>
  47.561 -	</result>
  47.562 -    </test>
  47.563 -
  47.564 -    <test name="testInstallSinglePackageRequireXtra2_32MultiLib">
  47.565 -	<set name="system"/>
  47.566 -	<set name="repo">
  47.567 -	    <package name="zsh" version="1-1" arch="i386">
  47.568 -		<requires name="zip"/>
  47.569 -	    </package>
  47.570 -	    <package name="zip" version="1-3" arch="i386"/>
  47.571 -	    <package name="zip" version="1-3" arch="x86_64"/>
  47.572 -	</set>
  47.573 -	<transaction>
  47.574 -	    <install name="zsh"/>
  47.575 -	</transaction>
  47.576 -	<result>
  47.577 -	    <set>
  47.578 -		<package name="zip" version="1-3" arch="i386"/>
  47.579 -		<package name="zsh" version="1-1" arch="i386"/>
  47.580 -	    </set>
  47.581 -	</result>
  47.582 -    </test>
  47.583 -
  47.584 -    <test name="testUpdateSinglePackage">
  47.585 -	<set name="system">
  47.586 -	    <package name="zsh" version="1-1" arch="i386"/>
  47.587 -	</set>
  47.588 -	<set name="repo">
  47.589 -	    <package name="zsh" version="1-3" arch="i386"/>
  47.590 -	</set>
  47.591 -	<transaction>
  47.592 -	    <install name="zsh"/>
  47.593 -	</transaction>
  47.594 -	<result>
  47.595 -	    <set>
  47.596 -		<package name="zsh" version="1-3" arch="i386"/>
  47.597 -	    </set>
  47.598 -	</result>
  47.599 -    </test>
  47.600 -
  47.601 -    <test name="testUpdateForDependency">
  47.602 -	<set name="system">
  47.603 -	    <package name="zip" version="0:1-1" arch="i386"/>
  47.604 -	</set>
  47.605 -	<set name="repo">
  47.606 -	    <package name="zsh" version="0:1-1" arch="i386">
  47.607 -		<requires name="zip" relation="EQ" version="0:2-1"/>
  47.608 -	    </package>
  47.609 -	    <package name="zip" version="0:2-1" arch="i386"/>
  47.610 -	</set>
  47.611 -	<transaction>
  47.612 -	    <install name="zsh"/>
  47.613 -	</transaction>
  47.614 -	<result>
  47.615 -	    <set>
  47.616 -		<package name="zip" version="0:2-1" arch="i386"/>
  47.617 -		<package name="zsh" version="0:1-1" arch="i386"/>
  47.618 -	    </set>
  47.619 -	</result>
  47.620 -    </test>
  47.621 -
  47.622 -    <test name="testUpdateSplitPackage">
  47.623 -	<set name="system">
  47.624 -	    <package name="zip" version="0:1-1" arch="i386">
  47.625 -		<provides name="libzip" relation="EQ" version="0:1-1"/>
  47.626 -	    </package>
  47.627 -	</set>
  47.628 -	<set name="repo">
  47.629 -	    <package name="zsh" version="0:1-1" arch="i386">
  47.630 -		<requires name="libzip" relation="EQ" version="0:2-1"/>
  47.631 -	    </package>
  47.632 -	    <package name="zip" version="0:2-1" arch="i386">
  47.633 -		<requires name="zip-libs" relation="EQ" version="0:2-1"/>
  47.634 -	    </package>
  47.635 -	    <package name="zip-libs" version="0:2-1" arch="i386">
  47.636 -		<provides name="libzip" relation="EQ" version="0:2-1"/>
  47.637 -	    </package>
  47.638 -	</set>
  47.639 -	<transaction>
  47.640 -	    <install name="zsh"/>
  47.641 -	</transaction>
  47.642 -	<result>
  47.643 -	    <set>
  47.644 -		<package name="zip" version="0:1-1" arch="i386"/>
  47.645 -		<package name="zip-libs" version="0:2-1" arch="i386"/>
  47.646 -		<package name="zsh" version="0:1-1" arch="i386"/>
  47.647 -	    </set>
  47.648 -	</result>
  47.649 -    </test>
  47.650 -
  47.651 -    <test name="testUpdateSinglePackageNewRequires">
  47.652 -	<set name="system">
  47.653 -	    <package name="zsh" version="1-1" arch="i386"/>
  47.654 -	</set>
  47.655 -	<set name="repo">
  47.656 -	    <package name="zsh" version="1-3" arch="i386">
  47.657 -		<requires name="zip"/>
  47.658 -	    </package>
  47.659 -	    <package name="zip" version="1-3" arch="x86_64"/>
  47.660 -	</set>
  47.661 -	<transaction>
  47.662 -	    <install name="zsh"/>
  47.663 -	</transaction>
  47.664 -	<result>
  47.665 -	    <set>
  47.666 -		<package name="zsh" version="1-3" arch="i386"/>
  47.667 -		<package name="zip" version="1-3" arch="x86_64"/>
  47.668 -	    </set>
  47.669 -	</result>
  47.670 -    </test>
  47.671 -
  47.672 -    <test name="testUpdateSinglePackageOldRequires">
  47.673 -	<set name="system">
  47.674 -	    <package name="zsh" version="1-1" arch="i386">
  47.675 -		<requires name="zip"/>
  47.676 -	    </package>
  47.677 -	    <package name="zip" version="1-3" arch="x86_64"/>
  47.678 -	</set>
  47.679 -	<set name="repo">
  47.680 -	    <package name="zsh" version="1-3" arch="i386">
  47.681 -		<requires name="zip"/>
  47.682 -	    </package>
  47.683 -	</set>
  47.684 -	<transaction>
  47.685 -	    <install name="zsh"/>
  47.686 -	</transaction>
  47.687 -	<result>
  47.688 -	    <set>
  47.689 -		<package name="zip" version="1-3" arch="x86_64"/>
  47.690 -		<package name="zsh" version="1-3" arch="i386"/>
  47.691 -	    </set>
  47.692 -	</result>
  47.693 -    </test>
  47.694 -
  47.695 -    <test name="testUpdateSinglePackageOldRequiresGone">
  47.696 -	<set name="system">
  47.697 -	    <package name="zsh" version="1-1" arch="i386">
  47.698 -		<requires name="zip"/>
  47.699 -	    </package>
  47.700 -	    <package name="zip" version="1-3" arch="x86_64"/>
  47.701 -	</set>
  47.702 -	<set name="repo">
  47.703 -	    <package name="zsh" version="1-3" arch="i386"/>
  47.704 -	</set>
  47.705 -	<transaction>
  47.706 -	    <install name="zsh"/>
  47.707 -	</transaction>
  47.708 -	<result>
  47.709 -	    <set>
  47.710 -		<package name="zip" version="1-3" arch="x86_64"/>
  47.711 -		<package name="zsh" version="1-3" arch="i386"/>
  47.712 -	    </set>
  47.713 -	</result>
  47.714 -    </test>
  47.715 -
  47.716 -    <test name="testUpdateSinglePackageObsoletesOldRequirement">
  47.717 -	<set name="system">
  47.718 -	    <package name="zsh" version="1-1" arch="i386">
  47.719 -		<requires name="zip"/>
  47.720 -	    </package>
  47.721 -	    <package name="zip" version="1-1" arch="i386"/>
  47.722 -	</set>
  47.723 -	<set name="repo">
  47.724 -	    <package name="zsh" version="1-3" arch="i386">
  47.725 -		<!-- depsolvetests.py actually adds the obsoletes
  47.726 -		     to the installed zsh rather than the new zsh,
  47.727 -		     but I'm assuming that's a bug -->
  47.728 -		<obsoletes name="zip"/>
  47.729 -	    </package>
  47.730 -	</set>
  47.731 -	<transaction>
  47.732 -	    <install name="zsh"/>
  47.733 -	</transaction>
  47.734 -	<result>
  47.735 -	    <set>
  47.736 -		<package name="zsh" version="1-3" arch="i386"/>
  47.737 -	    </set>
  47.738 -	</result>
  47.739 -    </test>
  47.740 -
  47.741 -    <test name="testUpdateForConflict">
  47.742 -	<set name="system">
  47.743 -	    <package name="zip" version="0:1-1" arch="i386"/>
  47.744 -	</set>
  47.745 -	<set name="repo">
  47.746 -	    <package name="zsh" version="0:1-1" arch="i386">
  47.747 -		<conflicts name="zip" relation="LE" version="0:1-1"/>
  47.748 -	    </package>
  47.749 -	    <package name="zip" version="0:2-1" arch="i386"/>
  47.750 -	</set>
  47.751 -	<transaction>
  47.752 -	    <install name="zsh"/>
  47.753 -	</transaction>
  47.754 -	<result>
  47.755 -	    <set>
  47.756 -		<package name="zip" version="0:2-1" arch="i386"/>
  47.757 -		<package name="zsh" version="0:1-1" arch="i386"/>
  47.758 -	    </set>
  47.759 -	</result>
  47.760 -    </test>
  47.761 -
  47.762 -    <test name="testUpdateForConflict2">
  47.763 -	<set name="system">
  47.764 -	    <package name="zip" version="0:1-1" arch="i386">
  47.765 -		<conflicts name="zsh" relation="LE" version="0:1-1"/>
  47.766 -	    </package>
  47.767 -	</set>
  47.768 -	<set name="repo">
  47.769 -	    <package name="zsh" version="0:1-1" arch="i386"/>
  47.770 -	    <package name="zip" version="0:2-1" arch="i386"/>
  47.771 -	</set>
  47.772 -	<transaction>
  47.773 -	    <install name="zsh"/>
  47.774 -	</transaction>
  47.775 -	<result>
  47.776 -	    <set>
  47.777 -		<package name="zsh" version="0:1-1" arch="i386"/>
  47.778 -		<package name="zip" version="0:2-1" arch="i386"/>
  47.779 -	    </set>
  47.780 -	</result>
  47.781 -    </test>
  47.782 -
  47.783 -    <test name="testUpdateForConflictProvide">
  47.784 -	<set name="system">
  47.785 -	    <package name="zip" version="0:1-1" arch="i386">
  47.786 -		<provides name="zippy" relation="EQ" version="0:1-1"/>
  47.787 -	    </package>
  47.788 -	</set>
  47.789 -	<set name="repo">
  47.790 -	    <package name="zsh" version="0:1-1" arch="i386">
  47.791 -		<conflicts name="zippy" relation="LE" version="0:1-1"/>
  47.792 -	    </package>
  47.793 -	    <package name="zip" version="0:2-1" arch="i386"/>
  47.794 -	</set>
  47.795 -	<transaction>
  47.796 -	    <install name="zsh"/>
  47.797 -	</transaction>
  47.798 -	<result>
  47.799 -	    <set>
  47.800 -		<package name="zip" version="0:2-1" arch="i386"/>
  47.801 -		<package name="zsh" version="0:1-1" arch="i386"/>
  47.802 -	    </set>
  47.803 -	</result>
  47.804 -    </test>
  47.805 -
  47.806 -    <test name="testUpdateForConflictProvide2">
  47.807 -	<set name="system">
  47.808 -	    <package name="zip" version="0:1-1" arch="i386">
  47.809 -		<conflicts name="zippy" relation="GT" version="0:1-1"/>
  47.810 -		<conflicts name="zippy" relation="LT" version="0:1-1"/>
  47.811 -	    </package>
  47.812 -	</set>
  47.813 -	<set name="repo">
  47.814 -	    <package name="zsh" version="0:1-1" arch="i386">
  47.815 -		<provides name="zippy" relation="EQ" version="0:2-1"/>
  47.816 -	    </package>
  47.817 -	    <package name="zip" version="0:2-1" arch="i386">
  47.818 -		<conflicts name="zippy" relation="GT" version="0:2-1"/>
  47.819 -		<conflicts name="zippy" relation="LT" version="0:2-1"/>
  47.820 -	    </package>
  47.821 -	</set>
  47.822 -	<transaction>
  47.823 -	    <install name="zsh"/>
  47.824 -	</transaction>
  47.825 -	<result>
  47.826 -	    <set>
  47.827 -		<package name="zip" version="0:2-1" arch="i386"/>
  47.828 -		<package name="zsh" version="0:1-1" arch="i386"/>
  47.829 -	    </set>
  47.830 -	</result>
  47.831 -    </test>
  47.832 -
  47.833 -    <test name="testEraseSinglePackage">
  47.834 -	<set name="system">
  47.835 -	    <package name="zsh" version="0:1-1" arch="i386"/>
  47.836 -	</set>
  47.837 -	<set name="repo"/>
  47.838 -	<transaction>
  47.839 -	    <remove name="zsh"/>
  47.840 -	</transaction>
  47.841 -	<result>
  47.842 -	    <set/>
  47.843 -	</result>
  47.844 -    </test>
  47.845 -
  47.846 -    <test name="testEraseSinglePackageRequiredByOneInstalled">
  47.847 -	<set name="system">
  47.848 -	    <package name="zippy" version="0:1-1" arch="i386">
  47.849 -		<requires name="zsh"/>
  47.850 -	    </package>
  47.851 -	    <package name="zsh" version="0:1-1" arch="i386"/>
  47.852 -	</set>
  47.853 -	<set name="repo"/>
  47.854 -	<transaction>
  47.855 -	    <remove name="zsh"/>
  47.856 -	</transaction>
  47.857 -	<result>
  47.858 -	    <set/>
  47.859 -	</result>
  47.860 -    </test>
  47.861 -</tests>
    48.1 --- a/types.c	Sun Jun 15 18:16:20 2008 -0400
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,277 +0,0 @@
    48.4 -#include <stdlib.h>
    48.5 -#include <string.h>
    48.6 -
    48.7 -#include "types.h"
    48.8 -
    48.9 -void
   48.10 -array_init(struct array *array)
   48.11 -{
   48.12 -	memset(array, 0, sizeof *array);
   48.13 -}
   48.14 -
   48.15 -void
   48.16 -array_release(struct array *array)
   48.17 -{
   48.18 -	free(array->data);
   48.19 -}
   48.20 -
   48.21 -void *
   48.22 -array_add(struct array *array, int size)
   48.23 -{
   48.24 -	int alloc;
   48.25 -	void *data, *p;
   48.26 -
   48.27 -	if (array->alloc > 0)
   48.28 -		alloc = array->alloc;
   48.29 -	else
   48.30 -		alloc = 16;
   48.31 -
   48.32 -	while (alloc < array->size + size)
   48.33 -		alloc *= 2;
   48.34 -
   48.35 -	if (array->alloc < alloc) {
   48.36 -		data = realloc(array->data, alloc);
   48.37 -		if (data == NULL)
   48.38 -			return 0;
   48.39 -		array->data = data;
   48.40 -		array->alloc = alloc;
   48.41 -	}
   48.42 -
   48.43 -	p = array->data + array->size;
   48.44 -	array->size += size;
   48.45 -
   48.46 -	return p;
   48.47 -}
   48.48 -
   48.49 -/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
   48.50 -#define RAZOR_ENTRY_LAST 0x80
   48.51 -#define RAZOR_IMMEDIATE  0x80
   48.52 -#define RAZOR_EMPTY_LIST 0xff
   48.53 -
   48.54 -void
   48.55 -list_set_empty(struct list_head *head)
   48.56 -{
   48.57 -	head->list_ptr = ~0;
   48.58 -	head->flags = RAZOR_EMPTY_LIST;
   48.59 -}
   48.60 -
   48.61 -void
   48.62 -list_set_ptr(struct list_head *head, uint32_t ptr)
   48.63 -{
   48.64 -	head->list_ptr = ptr;
   48.65 -	head->flags = 0;
   48.66 -}
   48.67 -
   48.68 -void
   48.69 -list_set_array(struct list_head *head, struct array *pool,
   48.70 -	       struct array *items, int force_indirect)
   48.71 -{
   48.72 -	struct list *p;
   48.73 -
   48.74 -	if (!force_indirect) {
   48.75 -		if (items->size == 0) {
   48.76 -			list_set_empty(head);
   48.77 -			return;
   48.78 -		} else if (items->size == sizeof (uint32_t)) {
   48.79 -			head->list_ptr = *(uint32_t *) items->data;
   48.80 -			head->flags = RAZOR_IMMEDIATE;
   48.81 -			return;
   48.82 -		}
   48.83 -	}
   48.84 -
   48.85 -	p = array_add(pool, items->size);
   48.86 -	memcpy(p, items->data, items->size);
   48.87 -	p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
   48.88 -	list_set_ptr(head, p - (struct list *) pool->data);
   48.89 -}
   48.90 -
   48.91 -struct list *
   48.92 -list_first(struct list_head *head, struct array *pool)
   48.93 -{
   48.94 -	if (head->flags == RAZOR_EMPTY_LIST)
   48.95 -		return NULL;
   48.96 -	else if (head->flags == RAZOR_IMMEDIATE)
   48.97 -		return (struct list *) head;
   48.98 -	else
   48.99 -		return (struct list *) pool->data + head->list_ptr;
  48.100 -}
  48.101 -
  48.102 -struct list *
  48.103 -list_next(struct list *list)
  48.104 -{
  48.105 -	if (list->flags)
  48.106 -		return NULL;
  48.107 -	return ++list;
  48.108 -}
  48.109 -
  48.110 -void
  48.111 -list_remap_pool(struct array *pool, uint32_t *map)
  48.112 -{
  48.113 -	struct list *p, *end;
  48.114 -
  48.115 -	end = pool->data + pool->size;
  48.116 -	for (p = pool->data; p < end; p++)
  48.117 -		p->data = map[p->data];
  48.118 -}
  48.119 -
  48.120 -void
  48.121 -list_remap_head(struct list_head *head, uint32_t *map)
  48.122 -{
  48.123 -	if (head->flags == RAZOR_IMMEDIATE)
  48.124 -		head->list_ptr = map[head->list_ptr];
  48.125 -}
  48.126 -
  48.127 -
  48.128 -void
  48.129 -hashtable_init(struct hashtable *table, struct array *pool)
  48.130 -{
  48.131 -	array_init(&table->buckets);
  48.132 -	table->pool = pool;
  48.133 -}
  48.134 -
  48.135 -void
  48.136 -hashtable_release(struct hashtable *table)
  48.137 -{
  48.138 -	array_release(&table->buckets);
  48.139 -}
  48.140 -
  48.141 -static unsigned int
  48.142 -hash_string(const char *key)
  48.143 -{
  48.144 -	const char *p;
  48.145 -	unsigned int hash = 0;
  48.146 -
  48.147 -	for (p = key; *p; p++)
  48.148 -		hash = (hash * 617) ^ *p;
  48.149 -
  48.150 -	return hash;
  48.151 -}
  48.152 -
  48.153 -uint32_t
  48.154 -hashtable_lookup(struct hashtable *table, const char *key)
  48.155 -{
  48.156 -	unsigned int mask, start, i;
  48.157 -	uint32_t *b;
  48.158 -	char *pool;
  48.159 -
  48.160 -	pool = table->pool->data;
  48.161 -	mask = table->buckets.alloc - 1;
  48.162 -	start = hash_string(key) * sizeof(uint32_t);
  48.163 -
  48.164 -	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  48.165 -		b = table->buckets.data + ((start + i) & mask);
  48.166 -
  48.167 -		if (*b == 0)
  48.168 -			return 0;
  48.169 -
  48.170 -		if (strcmp(key, &pool[*b]) == 0)
  48.171 -			return *b;
  48.172 -	}
  48.173 -
  48.174 -	return 0;
  48.175 -}
  48.176 -
  48.177 -static void
  48.178 -do_insert(struct hashtable *table, uint32_t value)
  48.179 -{
  48.180 -	unsigned int mask, start, i;
  48.181 -	uint32_t *b;
  48.182 -	const char *key;
  48.183 -
  48.184 -	key = (char *) table->pool->data + value;
  48.185 -	mask = table->buckets.alloc - 1;
  48.186 -	start = hash_string(key) * sizeof(uint32_t);
  48.187 -
  48.188 -	for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
  48.189 -		b = table->buckets.data + ((start + i) & mask);
  48.190 -		if (*b == 0) {
  48.191 -			*b = value;
  48.192 -			break;
  48.193 -		}
  48.194 -	}
  48.195 -}
  48.196 -
  48.197 -static uint32_t
  48.198 -add_to_string_pool(struct hashtable *table, const char *key)
  48.199 -{
  48.200 -	int len;
  48.201 -	char *p;
  48.202 -
  48.203 -	len = strlen(key) + 1;
  48.204 -	p = array_add(table->pool, len);
  48.205 -	memcpy(p, key, len);
  48.206 -
  48.207 -	return p - (char *) table->pool->data;
  48.208 -}
  48.209 -
  48.210 -uint32_t
  48.211 -hashtable_insert(struct hashtable *table, const char *key)
  48.212 -{
  48.213 -	uint32_t value, *buckets, *b, *end;
  48.214 -	int alloc;
  48.215 -
  48.216 -	alloc = table->buckets.alloc;
  48.217 -	array_add(&table->buckets, 4 * sizeof *buckets);
  48.218 -	if (alloc != table->buckets.alloc) {
  48.219 -		end = table->buckets.data + alloc;
  48.220 -		memset(end, 0, table->buckets.alloc - alloc);
  48.221 -		for (b = table->buckets.data; b < end; b++) {
  48.222 -			value = *b;
  48.223 -			if (value != 0) {
  48.224 -				*b = 0;
  48.225 -				do_insert(table, value);
  48.226 -			}
  48.227 -		}
  48.228 -	}
  48.229 -
  48.230 -	value = add_to_string_pool(table, key);
  48.231 -	do_insert (table, value);
  48.232 -
  48.233 -	return value;
  48.234 -}
  48.235 -
  48.236 -uint32_t
  48.237 -hashtable_tokenize(struct hashtable *table, const char *string)
  48.238 -{
  48.239 -	uint32_t token;
  48.240 -
  48.241 -	if (string == NULL)
  48.242 -		string = "";
  48.243 -
  48.244 -	token = hashtable_lookup(table, string);
  48.245 -	if (token != 0)
  48.246 -		return token;
  48.247 -
  48.248 -	return hashtable_insert(table, string);
  48.249 -}
  48.250 -
  48.251 -
  48.252 -void
  48.253 -bitarray_init(struct bitarray *bitarray, int size, int initial_value)
  48.254 -{
  48.255 -	int bytes = ((size + 31) / 32) * 4;
  48.256 -
  48.257 -	bitarray->bits = malloc(bytes);
  48.258 -	memset(bitarray->bits, initial_value ? 0xff : 0x00, bytes);
  48.259 -}
  48.260 -
  48.261 -void
  48.262 -bitarray_release(struct bitarray *bitarray)
  48.263 -{
  48.264 -	free(bitarray->bits);
  48.265 -}
  48.266 -
  48.267 -void
  48.268 -bitarray_set(struct bitarray *bitarray, int bit, int value)
  48.269 -{
  48.270 -	if (value)
  48.271 -		bitarray->bits[bit >> 5] |= 1 << (bit & 31);
  48.272 -	else
  48.273 -		bitarray->bits[bit >> 5] &= ~(1 << (bit & 31));
  48.274 -}
  48.275 -
  48.276 -int
  48.277 -bitarray_get(struct bitarray *bitarray, int bit)
  48.278 -{
  48.279 -	return (bitarray->bits[bit >> 5] & (1 << (bit & 31))) != 0;
  48.280 -}
    49.1 --- a/types.h	Sun Jun 15 18:16:20 2008 -0400
    49.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3 @@ -1,59 +0,0 @@
    49.4 -#ifndef _RAZOR_TYPES_H_
    49.5 -#define _RAZOR_TYPES_H_
    49.6 -
    49.7 -#include <stdint.h>
    49.8 -
    49.9 -struct array {
   49.10 -	void *data;
   49.11 -	int size, alloc;
   49.12 -};
   49.13 -
   49.14 -void array_init(struct array *array);
   49.15 -void array_release(struct array *array);
   49.16 -void *array_add(struct array *array, int size);
   49.17 -
   49.18 -
   49.19 -struct list_head {
   49.20 -	uint list_ptr : 24;
   49.21 -	uint flags    : 8;
   49.22 -};
   49.23 -
   49.24 -struct list {
   49.25 -	uint data  : 24;
   49.26 -	uint flags : 8;
   49.27 -};
   49.28 -
   49.29 -void list_set_empty(struct list_head *head);
   49.30 -void list_set_ptr(struct list_head *head, uint32_t ptr);
   49.31 -void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
   49.32 -
   49.33 -struct list *list_first(struct list_head *head, struct array *pool);
   49.34 -struct list *list_next(struct list *list);
   49.35 -
   49.36 -void list_remap_pool(struct array *pool, uint32_t *map);
   49.37 -void list_remap_head(struct list_head *list, uint32_t *map);
   49.38 -
   49.39 -
   49.40 -struct hashtable {
   49.41 -	struct array buckets;
   49.42 -	struct array *pool;
   49.43 -};
   49.44 -
   49.45 -void hashtable_init(struct hashtable *table, struct array *pool);
   49.46 -void hashtable_release(struct hashtable *table);
   49.47 -uint32_t hashtable_insert(struct hashtable *table, const char *key);
   49.48 -uint32_t hashtable_lookup(struct hashtable *table, const char *key);
   49.49 -uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
   49.50 -
   49.51 -
   49.52 -struct bitarray {
   49.53 -	uint32_t *bits;
   49.54 -};
   49.55 -
   49.56 -void bitarray_init(struct bitarray *bitarray, int size, int intial_value);
   49.57 -void bitarray_release(struct bitarray *bitarray);
   49.58 -void bitarray_set(struct bitarray *bitarray, int bit, int value);
   49.59 -int bitarray_get(struct bitarray *bitarray, int bit);
   49.60 -
   49.61 -
   49.62 -#endif /* _RAZOR_TYPES_H_ */
    50.1 --- a/util.c	Sun Jun 15 18:16:20 2008 -0400
    50.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3 @@ -1,167 +0,0 @@
    50.4 -#include <limits.h>
    50.5 -#include <string.h>
    50.6 -#include <sys/stat.h>
    50.7 -#include <stdlib.h>
    50.8 -#include <stdio.h>
    50.9 -#include <stdint.h>
   50.10 -#include <unistd.h>
   50.11 -
   50.12 -#include "razor-internal.h"
   50.13 -
   50.14 -int
   50.15 -razor_create_dir(const char *root, const char *path)
   50.16 -{
   50.17 -	char buffer[PATH_MAX], *p;
   50.18 -	const char *slash, *next;
   50.19 -	struct stat buf;
   50.20 -
   50.21 -	/* Create all sub-directories in dir. We know root exists and
   50.22 -	 * is a dir, root does not end in a '/', and path has a
   50.23 -	 * leading '/'. */
   50.24 -
   50.25 -	strcpy(buffer, root);
   50.26 -	p = buffer + strlen(buffer);
   50.27 -	slash = path;
   50.28 -	for (slash = path; *slash != '\0'; slash = next) {
   50.29 -		next = strchr(slash + 1, '/');
   50.30 -		if (next == NULL)
   50.31 -			break;
   50.32 -
   50.33 -		memcpy(p, slash, next - slash);
   50.34 -		p += next - slash;
   50.35 -		*p = '\0';
   50.36 -
   50.37 -		if (stat(buffer, &buf) == 0) {
   50.38 -			if (!S_ISDIR(buf.st_mode)) {
   50.39 -				fprintf(stderr,
   50.40 -					"%s exists but is not a directory\n",
   50.41 -					buffer);
   50.42 -				return -1;
   50.43 -			}
   50.44 -		} else if (mkdir(buffer, 0777) < 0) {
   50.45 -			fprintf(stderr, "failed to make directory %s: %m\n",
   50.46 -				buffer);
   50.47 -			return -1;
   50.48 -		}
   50.49 -
   50.50 -		/* FIXME: What to do about permissions for dirs we
   50.51 -		 * have to create but are not in the cpio archive? */
   50.52 -	}
   50.53 -
   50.54 -	return 0;
   50.55 -}
   50.56 -
   50.57 -int
   50.58 -razor_write(int fd, const void *data, size_t size)
   50.59 -{
   50.60 -	size_t rest;
   50.61 -	ssize_t written;
   50.62 -	const unsigned char *p;
   50.63 -
   50.64 -	rest = size;
   50.65 -	p = data;
   50.66 -	while (rest > 0) {
   50.67 -		written = write(fd, p, rest);
   50.68 -		if (written < 0) {
   50.69 -			fprintf(stderr, "write error: %m\n");
   50.70 -			return -1;
   50.71 -		}
   50.72 -		rest -= written;
   50.73 -		p += written;
   50.74 -	}
   50.75 -
   50.76 -	return 0;
   50.77 -}
   50.78 -
   50.79 -struct qsort_context {
   50.80 -	size_t size;
   50.81 -	razor_compare_with_data_func_t compare;
   50.82 -	void *data;
   50.83 -};
   50.84 -
   50.85 -static void
   50.86 -qsort_swap(void *p1, void *p2, size_t size)
   50.87 -{
   50.88 -	char buffer[size];
   50.89 -
   50.90 -	memcpy(buffer, p1, size);
   50.91 -	memcpy(p1, p2, size);
   50.92 -	memcpy(p2, buffer, size);
   50.93 -}
   50.94 -
   50.95 -static void
   50.96 -__qsort_with_data(void *base, size_t nelem, uint32_t *map,
   50.97 -		  struct qsort_context *ctx)
   50.98 -{
   50.99 -	void *p, *start, *end, *pivot;
  50.100 -	uint32_t *mp, *mstart, *mend, tmp;
  50.101 -	int left, right, result;
  50.102 -	size_t size = ctx->size;
  50.103 -
  50.104 -	p = base;
  50.105 -	start = base;
  50.106 -	end = base + nelem * size;
  50.107 -	mp = map;
  50.108 -	mstart = map;
  50.109 -	mend = map + nelem;
  50.110 -	pivot = base + (random() % nelem) * size;
  50.111 -
  50.112 -	while (p < end) {
  50.113 -		result = ctx->compare(p, pivot, ctx->data);
  50.114 -		if (result < 0) {
  50.115 -			qsort_swap(p, start, size);
  50.116 -			tmp = *mp;
  50.117 -			*mp = *mstart;
  50.118 -			*mstart = tmp;
  50.119 -			if (start == pivot)
  50.120 -				pivot = p;
  50.121 -			start += size;
  50.122 -			mstart++;
  50.123 -			p += size;
  50.124 -			mp++;
  50.125 -		} else if (result == 0) {
  50.126 -			p += size;
  50.127 -			mp++;
  50.128 -		} else {
  50.129 - 			end -= size;
  50.130 -			mend--;
  50.131 -			qsort_swap(p, end, size);
  50.132 -			tmp = *mp;
  50.133 -			*mp = *mend;
  50.134 -			*mend = tmp;
  50.135 -			if (end == pivot)
  50.136 -				pivot = p;
  50.137 -		}
  50.138 -	}
  50.139 -
  50.140 -	left = (start - base) / size;
  50.141 -	right = (base + nelem * size - end) / size;
  50.142 -	if (left > 1)
  50.143 -		__qsort_with_data(base, left, map, ctx);
  50.144 -	if (right > 1)
  50.145 -		__qsort_with_data(end, right, mend, ctx);
  50.146 -}
  50.147 -
  50.148 -uint32_t *
  50.149 -razor_qsort_with_data(void *base, size_t nelem, size_t size,
  50.150 -		      razor_compare_with_data_func_t compare, void *data)
  50.151 -{
  50.152 -	struct qsort_context ctx;
  50.153 -	uint32_t *map;
  50.154 -	int i;
  50.155 -
  50.156 -	if (nelem == 0)
  50.157 -		return NULL;
  50.158 -
  50.159 -	ctx.size = size;
  50.160 -	ctx.compare = compare;
  50.161 -	ctx.data = data;
  50.162 -
  50.163 -	map = malloc(nelem * sizeof (uint32_t));
  50.164 -	for (i = 0; i < nelem; i++)
  50.165 -		map[i] = i;
  50.166 -
  50.167 -	__qsort_with_data(base, nelem, map, &ctx);
  50.168 -
  50.169 -	return map;
  50.170 -}
    51.1 --- a/yum.c	Sun Jun 15 18:16:20 2008 -0400
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,366 +0,0 @@
    51.4 -/*
    51.5 - * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
    51.6 - * Copyright (C) 2008  Red Hat, Inc
    51.7 - *
    51.8 - * This program is free software; you can redistribute it and/or modify
    51.9 - * it under the terms of the GNU General Public License as published by
   51.10 - * the Free Software Foundation; either version 2 of the License, or
   51.11 - * (at your option) any later version.
   51.12 - *
   51.13 - * This program is distributed in the hope that it will be useful,
   51.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   51.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   51.16 - * GNU General Public License for more details.
   51.17 - *
   51.18 - * You should have received a copy of the GNU General Public License along
   51.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
   51.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   51.21 - */
   51.22 -
   51.23 -#define _GNU_SOURCE
   51.24 -
   51.25 -#include <string.h>
   51.26 -#include <stdio.h>
   51.27 -#include <sys/stat.h>
   51.28 -#include <sys/mman.h>
   51.29 -#include <unistd.h>
   51.30 -#include <fcntl.h>
   51.31 -#include <errno.h>
   51.32 -
   51.33 -#include <expat.h>
   51.34 -#include <zlib.h>
   51.35 -#include "razor.h"
   51.36 -
   51.37 -/* Import a yum filelist as a razor package set. */
   51.38 -
   51.39 -enum {
   51.40 -	YUM_STATE_BEGIN,
   51.41 -	YUM_STATE_PACKAGE_NAME,
   51.42 -	YUM_STATE_PACKAGE_ARCH,
   51.43 -	YUM_STATE_SUMMARY,
   51.44 -	YUM_STATE_DESCRIPTION,
   51.45 -	YUM_STATE_URL,
   51.46 -	YUM_STATE_LICENSE,
   51.47 -	YUM_STATE_CHECKSUM,
   51.48 -	YUM_STATE_REQUIRES,
   51.49 -	YUM_STATE_PROVIDES,
   51.50 -	YUM_STATE_OBSOLETES,
   51.51 -	YUM_STATE_CONFLICTS,
   51.52 -	YUM_STATE_FILE
   51.53 -};
   51.54 -
   51.55 -struct yum_context {
   51.56 -	XML_Parser primary_parser;
   51.57 -	XML_Parser filelists_parser;
   51.58 -	XML_Parser current_parser;
   51.59 -
   51.60 -	struct razor_importer *importer;
   51.61 -	struct import_property_context *current_property_context;
   51.62 -	char name[256], arch[64], summary[512], description[4096];
   51.63 -	char url[256], license[64], buffer[512], *p;
   51.64 -	char pkgid[128];
   51.65 -	int state;
   51.66 -};
   51.67 -
   51.68 -static enum razor_version_relation
   51.69 -yum_to_razor_flags (const char *flags)
   51.70 -{
   51.71 -	/* FIXME? */
   51.72 -	if (!flags)
   51.73 -		return RAZOR_VERSION_EQUAL;
   51.74 -
   51.75 -	if (flags[0] == 'L') {
   51.76 -		if (flags[1] == 'T')
   51.77 -			return RAZOR_VERSION_LESS;
   51.78 -		else
   51.79 -			return RAZOR_VERSION_LESS_OR_EQUAL;
   51.80 -	} else if (flags[0] == 'G') {
   51.81 -		if (flags[1] == 'T')
   51.82 -			return RAZOR_VERSION_GREATER;
   51.83 -		else
   51.84 -			return RAZOR_VERSION_GREATER_OR_EQUAL;
   51.85 -	} else
   51.86 -		return RAZOR_VERSION_EQUAL;
   51.87 -}
   51.88 -
   51.89 -static void
   51.90 -yum_primary_start_element(void *data, const char *name, const char **atts)
   51.91 -{
   51.92 -	struct yum_context *ctx = data;
   51.93 -	const char *n, *epoch, *version, *release, *flags;
   51.94 -	char buffer[128];
   51.95 -	int i;
   51.96 -
   51.97 -	if (strcmp(name, "name") == 0) {
   51.98 -		ctx->state = YUM_STATE_PACKAGE_NAME;
   51.99 -		ctx->p = ctx->name;
  51.100 -	} else if (strcmp(name, "arch") == 0) {
  51.101 -		ctx->state = YUM_STATE_PACKAGE_ARCH;
  51.102 -		ctx->p = ctx->arch;
  51.103 -	} else if (strcmp(name, "version") == 0) {
  51.104 -		epoch = NULL;
  51.105 -		version = NULL;
  51.106 -		release = NULL;
  51.107 -		for (i = 0; atts[i]; i += 2) {
  51.108 -			if (strcmp(atts[i], "epoch") == 0)
  51.109 -				epoch = atts[i + 1];
  51.110 -			else if (strcmp(atts[i], "ver") == 0)
  51.111 -				version = atts[i + 1];
  51.112 -			else if (strcmp(atts[i], "rel") == 0)
  51.113 -				release = atts[i + 1];
  51.114 -		}
  51.115 -		if (version == NULL || release == NULL) {
  51.116 -			fprintf(stderr, "invalid version tag, "
  51.117 -				"missing version or  release attribute\n");
  51.118 -			return;
  51.119 -		}
  51.120 -
  51.121 -		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  51.122 -		razor_importer_begin_package(ctx->importer,
  51.123 -					     ctx->name, buffer, ctx->arch);
  51.124 -	} else if (strcmp(name, "summary") == 0) {
  51.125 -		ctx->p = ctx->summary;
  51.126 -		ctx->state = YUM_STATE_SUMMARY;
  51.127 -	} else if (strcmp(name, "description") == 0) {
  51.128 -		ctx->p = ctx->description;
  51.129 -		ctx->state = YUM_STATE_DESCRIPTION;
  51.130 -	} else if (strcmp(name, "url") == 0) {
  51.131 -		ctx->p = ctx->url;
  51.132 -		ctx->state = YUM_STATE_URL;
  51.133 -	} else if (strcmp(name, "checksum") == 0) {
  51.134 -		ctx->p = ctx->pkgid;
  51.135 -		ctx->state = YUM_STATE_CHECKSUM;
  51.136 -	} else if (strcmp(name, "rpm:license") == 0) {
  51.137 -		ctx->p = ctx->license;
  51.138 -		ctx->state = YUM_STATE_LICENSE;
  51.139 -	} else if (strcmp(name, "rpm:requires") == 0) {
  51.140 -		ctx->state = YUM_STATE_REQUIRES;
  51.141 -	} else if (strcmp(name, "rpm:provides") == 0) {
  51.142 -		ctx->state = YUM_STATE_PROVIDES;
  51.143 -	} else if (strcmp(name, "rpm:obsoletes") == 0) {
  51.144 -		ctx->state = YUM_STATE_OBSOLETES;
  51.145 -	} else if (strcmp(name, "rpm:conflicts") == 0) {
  51.146 -		ctx->state = YUM_STATE_CONFLICTS;
  51.147 -	} else if (strcmp(name, "rpm:entry") == 0 &&
  51.148 -		   ctx->state != YUM_STATE_BEGIN) {
  51.149 -		n = NULL;
  51.150 -		epoch = NULL;
  51.151 -		version = NULL;
  51.152 -		release = NULL;
  51.153 -		flags = NULL;
  51.154 -		for (i = 0; atts[i]; i += 2) {
  51.155 -			if (strcmp(atts[i], "name") == 0)
  51.156 -				n = atts[i + 1];
  51.157 -			else if (strcmp(atts[i], "epoch") == 0)
  51.158 -				epoch = atts[i + 1];
  51.159 -			else if (strcmp(atts[i], "ver") == 0)
  51.160 -				version = atts[i + 1];
  51.161 -			else if (strcmp(atts[i], "rel") == 0)
  51.162 -				release = atts[i + 1];
  51.163 -			else if (strcmp(atts[i], "flags") == 0)
  51.164 -				flags = atts[i + 1];
  51.165 -		}
  51.166 -
  51.167 -		if (n == NULL) {
  51.168 -			fprintf(stderr, "invalid rpm:entry, "
  51.169 -				"missing name or version attributes\n");
  51.170 -			return;
  51.171 -		}
  51.172 -
  51.173 -		razor_build_evr(buffer, sizeof buffer, epoch, version, release);
  51.174 -		switch (ctx->state) {
  51.175 -		case YUM_STATE_REQUIRES:
  51.176 -			razor_importer_add_property(ctx->importer, n,
  51.177 -						    yum_to_razor_flags (flags),
  51.178 -						    buffer,
  51.179 -						    RAZOR_PROPERTY_REQUIRES);
  51.180 -			break;
  51.181 -		case YUM_STATE_PROVIDES:
  51.182 -			razor_importer_add_property(ctx->importer, n,
  51.183 -						    yum_to_razor_flags (flags),
  51.184 -						    buffer,
  51.185 -						    RAZOR_PROPERTY_PROVIDES);
  51.186 -			break;
  51.187 -		case YUM_STATE_OBSOLETES:
  51.188 -			razor_importer_add_property(ctx->importer, n,
  51.189 -						    yum_to_razor_flags (flags),
  51.190 -						    buffer,
  51.191 -						    RAZOR_PROPERTY_OBSOLETES);
  51.192 -			break;
  51.193 -		case YUM_STATE_CONFLICTS:
  51.194 -			razor_importer_add_property(ctx->importer, n,
  51.195 -						    yum_to_razor_flags (flags),
  51.196 -						    buffer,
  51.197 -						    RAZOR_PROPERTY_CONFLICTS);
  51.198 -			break;
  51.199 -		}
  51.200 -	}
  51.201 -}
  51.202 -
  51.203 -static void
  51.204 -yum_primary_end_element (void *data, const char *name)
  51.205 -{
  51.206 -	struct yum_context *ctx = data;
  51.207 -
  51.208 -	switch (ctx->state) {
  51.209 -	case YUM_STATE_PACKAGE_NAME:
  51.210 -	case YUM_STATE_PACKAGE_ARCH:
  51.211 -	case YUM_STATE_SUMMARY:
  51.212 -	case YUM_STATE_DESCRIPTION:
  51.213 -	case YUM_STATE_URL:
  51.214 -	case YUM_STATE_LICENSE:
  51.215 -	case YUM_STATE_CHECKSUM:
  51.216 -	case YUM_STATE_FILE:
  51.217 -		ctx->state = YUM_STATE_BEGIN;
  51.218 -		break;
  51.219 -	}
  51.220 -
  51.221 -	if (strcmp(name, "package") == 0) {
  51.222 -		razor_importer_add_details(ctx->importer, ctx->summary,
  51.223 -					   ctx->description, ctx->url,
  51.224 -					   ctx->license);
  51.225 -
  51.226 -		XML_StopParser(ctx->current_parser, XML_TRUE);
  51.227 -		ctx->current_parser = ctx->filelists_parser;
  51.228 -	}
  51.229 -}
  51.230 -
  51.231 -static void
  51.232 -yum_character_data (void *data, const XML_Char *s, int len)
  51.233 -{
  51.234 -	struct yum_context *ctx = data;
  51.235 -
  51.236 -	switch (ctx->state) {
  51.237 -	case YUM_STATE_PACKAGE_NAME:
  51.238 -	case YUM_STATE_PACKAGE_ARCH:
  51.239 -	case YUM_STATE_SUMMARY:
  51.240 -	case YUM_STATE_DESCRIPTION:
  51.241 -	case YUM_STATE_URL:
  51.242 -	case YUM_STATE_LICENSE:
  51.243 -	case YUM_STATE_CHECKSUM:
  51.244 -	case YUM_STATE_FILE:
  51.245 -		memcpy(ctx->p, s, len);
  51.246 -		ctx->p += len;
  51.247 -		*ctx->p = '\0';
  51.248 -		break;
  51.249 -	}
  51.250 -}
  51.251 -
  51.252 -static void
  51.253 -yum_filelists_start_element(void *data, const char *name, const char **atts)
  51.254 -{
  51.255 -	struct yum_context *ctx = data;
  51.256 -	const char *pkg, *pkgid;
  51.257 -	int i;
  51.258 -
  51.259 -	if (strcmp(name, "package") == 0) {
  51.260 -		pkg = NULL;
  51.261 -		pkgid = NULL;
  51.262 -		for (i = 0; atts[i]; i += 2) {
  51.263 -			if (strcmp(atts[i], "name") == 0)
  51.264 -				pkg = atts[i + 1];
  51.265 -			else if (strcmp(atts[i], "pkgid") == 0)
  51.266 -				pkgid = atts[i + 1];
  51.267 -		}
  51.268 -		if (strcmp(pkgid, ctx->pkgid) != 0)
  51.269 -			fprintf(stderr, "primary.xml and filelists.xml "
  51.270 -				"mismatch for %s: %s vs %s",
  51.271 -				pkg, pkgid, ctx->pkgid);
  51.272 -	} else if (strcmp(name, "file") == 0) {
  51.273 -		ctx->state = YUM_STATE_FILE;
  51.274 -		ctx->p = ctx->buffer;
  51.275 -	}
  51.276 -}
  51.277 -
  51.278 -
  51.279 -static void
  51.280 -yum_filelists_end_element (void *data, const char *name)
  51.281 -{
  51.282 -	struct yum_context *ctx = data;
  51.283 -
  51.284 -	ctx->state = YUM_STATE_BEGIN;
  51.285 -	if (strcmp(name, "package") == 0) {
  51.286 -		XML_StopParser(ctx->current_parser, XML_TRUE);
  51.287 -		ctx->current_parser = ctx->primary_parser;
  51.288 -		razor_importer_finish_package(ctx->importer);
  51.289 -	} else if (strcmp(name, "file") == 0)
  51.290 -		razor_importer_add_file(ctx->importer, ctx->buffer);
  51.291 -
  51.292 -}
  51.293 -
  51.294 -#define XML_BUFFER_SIZE 4096
  51.295 -
  51.296 -struct razor_set *
  51.297 -razor_set_create_from_yum(void)
  51.298 -{
  51.299 -	struct yum_context ctx;
  51.300 -	void *buf;
  51.301 -	int len, ret;
  51.302 -	gzFile primary, filelists;
  51.303 -	XML_ParsingStatus status;
  51.304 -
  51.305 -	ctx.importer = razor_importer_new();	
  51.306 -	ctx.state = YUM_STATE_BEGIN;
  51.307 -
  51.308 -	ctx.primary_parser = XML_ParserCreate(NULL);
  51.309 -	XML_SetUserData(ctx.primary_parser, &ctx);
  51.310 -	XML_SetElementHandler(ctx.primary_parser,
  51.311 -			      yum_primary_start_element,
  51.312 -			      yum_primary_end_element);
  51.313 -	XML_SetCharacterDataHandler(ctx.primary_parser,
  51.314 -				    yum_character_data);
  51.315 -
  51.316 -	ctx.filelists_parser = XML_ParserCreate(NULL);
  51.317 -	XML_SetUserData(ctx.filelists_parser, &ctx);
  51.318 -	XML_SetElementHandler(ctx.filelists_parser,
  51.319 -			      yum_filelists_start_element,
  51.320 -			      yum_filelists_end_element);
  51.321 -	XML_SetCharacterDataHandler(ctx.filelists_parser,
  51.322 -				    yum_character_data);
  51.323 -
  51.324 -	primary = gzopen("primary.xml.gz", "rb");
  51.325 -	if (primary == NULL)
  51.326 -		return NULL;
  51.327 -	filelists = gzopen("filelists.xml.gz", "rb");
  51.328 -	if (filelists == NULL)
  51.329 -		return NULL;
  51.330 -
  51.331 -	ctx.current_parser = ctx.primary_parser;
  51.332 -
  51.333 -	do {
  51.334 -		XML_GetParsingStatus(ctx.current_parser, &status);
  51.335 -		switch (status.parsing) {
  51.336 -		case XML_SUSPENDED:
  51.337 -			ret = XML_ResumeParser(ctx.current_parser);
  51.338 -			break;
  51.339 -		case XML_PARSING:
  51.340 -		case XML_INITIALIZED:
  51.341 -			buf = XML_GetBuffer(ctx.current_parser,
  51.342 -					    XML_BUFFER_SIZE);
  51.343 -			if (ctx.current_parser == ctx.primary_parser)
  51.344 -				len = gzread(primary, buf, XML_BUFFER_SIZE);
  51.345 -			else
  51.346 -				len = gzread(filelists, buf, XML_BUFFER_SIZE);
  51.347 -			if (len < 0) {
  51.348 -				fprintf(stderr,
  51.349 -					"couldn't read input: %s\n",
  51.350 -					strerror(errno));
  51.351 -				return NULL;
  51.352 -			}
  51.353 -
  51.354 -			XML_ParseBuffer(ctx.current_parser, len, len == 0);
  51.355 -			break;
  51.356 -		case XML_FINISHED:
  51.357 -			break;
  51.358 -		}
  51.359 -	} while (status.parsing != XML_FINISHED);
  51.360 -
  51.361 -
  51.362 -	XML_ParserFree(ctx.primary_parser);
  51.363 -	XML_ParserFree(ctx.filelists_parser);
  51.364 -
  51.365 -	gzclose(primary);
  51.366 -	gzclose(filelists);
  51.367 -
  51.368 -	return razor_importer_finish(ctx.importer);
  51.369 -}