Autoconfify razor.
committer: Kristian H?gsberg <krh@redhat.com>
1.1 --- a/.gitignore Sun Jun 15 23:15:59 2008 -0400
1.2 +++ b/.gitignore Mon Jun 16 15:40:30 2008 -0400
1.3 @@ -1,10 +1,32 @@
1.4 -.gitignore
1.5 +aclocal.m4
1.6 +autom4te.cache
1.7 +compile
1.8 +config.guess
1.9 +config.h
1.10 +config.h.in
1.11 +config.log
1.12 +config.status
1.13 +config.sub
1.14 +configure
1.15 +depcomp
1.16 +INSTALL
1.17 +install-sh
1.18 +intltool-extract
1.19 +intltool-extract.in
1.20 +intltool-merge
1.21 +intltool-merge.in
1.22 +intltool-update
1.23 +intltool-update.in
1.24 +libtool
1.25 +ltmain.sh
1.26 +Makefile
1.27 +Makefile.in
1.28 +missing
1.29 +mkinstalldirs
1.30 +py-compile
1.31 +stamp-h1
1.32 *.o
1.33 +ChangeLog
1.34 +*.tar.gz
1.35 *~
1.36 -*.repo
1.37 -razor
1.38 -test-driver
1.39 -pkgs
1.40 -set
1.41 -primary.xml.gz
1.42 -filelists.xml.gz
1.43 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/AUTHORS Mon Jun 16 15:40:30 2008 -0400
2.3 @@ -0,0 +1,2 @@
2.4 +Kristian Høgsberg <krh@redhat.com>
2.5 +
3.1 --- a/DEPSOLVE.txt Sun Jun 15 23:15:59 2008 -0400
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,364 +0,0 @@
3.4 -YUM vs RAZOR
3.5 -------------
3.6 -
3.7 -At a very high level, yum's depsolver does something roughly
3.8 -equivalent to:
3.9 -
3.10 - - For each package being installed or removed
3.11 -
3.12 - - For each relevant property (provides, requires, conflicts,
3.13 - obsoletes):
3.14 -
3.15 - - Figure out what additional packages need to be added to
3.16 - or removed from the system to satisfy this property
3.17 -
3.18 -which ends up being roughly O(N^2 * M) where N is the total number of
3.19 -properties and M is the number of packages being acted on.
3.20 -
3.21 -(I just figured that out off the top of my head, and I'm not totally
3.22 -familiar with the yum code, so it may be wrong.)
3.23 -
3.24 -Razor's depsolver is something like:
3.25 -
3.26 - - do {
3.27 -
3.28 - - For each property to be added to or removed from the system:
3.29 -
3.30 - - Figure out what packages need to be added to or removed
3.31 - from the system to satisfy this property
3.32 -
3.33 - - } until we stop adding/remove more packages
3.34 -
3.35 -with the key being that it's very easy to find the PROVIDES
3.36 -corresponding to a REQUIRES and vice versa, because the property
3.37 -arrays are sorted, and so all properties with the same "name" will be
3.38 -adjacent to one another in the array, allowing many dependencies to be
3.39 -satisified in essentially constant time. (Actually... we've been
3.40 -calling it constant, but it's really O(log N) for heavily-depended-on
3.41 -packages, because the more packages you have, the more variations on
3.42 -"requires foo", "requires foo = 1.1", "requires foo > 1.0", etc you're
3.43 -going to have to scan through.)
3.44 -
3.45 -Ideally though, each iteration of the inner loop body happens in
3.46 -constant time, and thus the inner loop as a whole is O(N), and thus
3.47 -the depsolver as a whole is O(N * M) (or at least, less than
3.48 -O(N * M * log N).
3.49 -
3.50 -
3.51 -FILE DEPENDENCIES
3.52 ------------------
3.53 -
3.54 -Whenever we add a package with a file REQUIRES to a razor_set, we also
3.55 -add a PROVIDES for that file to the package or packages which provide
3.56 -that file. This means that if we later add another package that
3.57 -requires the same file (eg, /bin/sh or /usr/bin/perl), we can resolve
3.58 -its file requirement exactly like we would resolve a property
3.59 -requirement, in nearly constant time.
3.60 -
3.61 -When adding a *new* file requirement (ie, a requirement on a file that
3.62 -no existing package depends on), we still have to scan through the
3.63 -file tree, which is O(log N) in the number of files.
3.64 -
3.65 -(AFAICT, there's no reason yum couldn't do the same optimization.
3.66 -Also, AFAICT, yum currently sticks property dependencies and file
3.67 -dependencies into the same hash table, so that if any package in the
3.68 -transaction has a file dependency, it causes *property* dependencies
3.69 -to become slower to resolve as well...)
3.70 -
3.71 -
3.72 -THE RULES
3.73 ----------
3.74 -
3.75 -This is what we have figured out for transaction-solving rules;
3.76 -neither yum nor rpm's algorithm seems to be explained in full
3.77 -anywhere...
3.78 -
3.79 - 1. Every requested install in the initial package set must be
3.80 - satisfied as either a new install or an update:
3.81 -
3.82 - - if the requested package name is the name of an upstream
3.83 - package:
3.84 -
3.85 - - if there is not a corresponding already-installed
3.86 - package, then install the upstream package
3.87 -
3.88 - - else if the upstream package is newer than the
3.89 - already-installed package, then update the package
3.90 -
3.91 - - else it's an error (UP_TO_DATE)
3.92 -
3.93 - - else if the requested package name is the name of an
3.94 - already-installed package:
3.95 -
3.96 - - if there is an upstream package that obsoletes the
3.97 - already-installed package, then behave as though the
3.98 - user had requested that that package be installed
3.99 - instead.
3.100 -
3.101 - - else it's an error (UP_TO_DATE or INSTALL_UNAVAILABLE?)
3.102 -
3.103 - - else it's an error (INSTALL_UNAVAILABLE)
3.104 -
3.105 - 2. Every requested removal in the initial package set must be
3.106 - satisfied as a removal. If any requested package name is not
3.107 - the name of an installed package, it's an error
3.108 - (REMOVE_NOT_INSTALLED)
3.109 -
3.110 - REQUIRES processing:
3.111 -
3.112 - 3. If a package being installed or updated-to REQUIRES a property
3.113 - that is not provided by any installed or to-be-installed
3.114 - package, we need to find an installable package that provides
3.115 - that property. If we find one, install/update it. If not, it's
3.116 - an error (UNSATISFIABLE). (If we find an upstream package
3.117 - providing the property that corresponds to a system package
3.118 - that's being removed, then it's a CONTRADICTION.)
3.119 -
3.120 - 4. If an already-installed package REQUIRES a property which is
3.121 - only provided by a package that is being removed, then that
3.122 - package needs to be removed as well.
3.123 -
3.124 - 5. If an already-installed package REQUIRES a property which is
3.125 - only provided by a package that is being upgraded or obsoleted
3.126 - (to a new package which does not provide that property), then:
3.127 -
3.128 - - if there is an update for the installed package, then update
3.129 - the installed package
3.130 -
3.131 - - else if there is another installable package that provides
3.132 - the required property, then install that.
3.133 -
3.134 - - else it's an error (UNSATISFIABLE?)
3.135 -
3.136 - CONFLICTS processing
3.137 -
3.138 - 6. If a package being installed or updated-to CONFLICTS with a
3.139 - property provided by an installed package:
3.140 -
3.141 - - if there is an update for the installed package, which the
3.142 - new package does not conflict with, then update the
3.143 - installed package.
3.144 -
3.145 - - else it's an error (NEW_CONFLICT)
3.146 -
3.147 - 7. If an already-installed package CONFLICTS with a property
3.148 - provided by a to-be-installed package:
3.149 -
3.150 - - if there is an update for the installed package, which does
3.151 - not conflict with the new package, then update the installed
3.152 - package.
3.153 -
3.154 - - else it's an error (NEW_CONFLICT)
3.155 -
3.156 - 8. If a package being installed or updated-to CONFLICTS with a
3.157 - property provided by a to-be-installed package, then it's an
3.158 - error (CONTRADICTION).
3.159 -
3.160 - OBSOLETES processing. NOTE: OBSOLETES are only matched against
3.161 - package names, not against arbitrary provided properties
3.162 -
3.163 - 9. If a package being installed or updated-to OBSOLETES an
3.164 - installed package, then obsolete that package. (ie, remove it,
3.165 - but treat it as updated for purposes of dangling REQUIRES).
3.166 -
3.167 - 10. If an already-installed package OBSOLETES a to-be-installed
3.168 - package, then it's an error. (ALREADY_OBSOLETE)
3.169 -
3.170 - 11. If a package being installed or updated-to OBSOLETES another
3.171 - package being installed or updated-to, then it's an error
3.172 - (CONTRADICTION).
3.173 -
3.174 -
3.175 -
3.176 -THE DEPSOLVER
3.177 --------------
3.178 -
3.179 -We start with two razor_sets, system and upstream, and a list of
3.180 -requested installations and removals.
3.181 -
3.182 - FIXME: what about multiple upstream repos? Having to deal with
3.183 - arbitrary numbers of razor_sets is possible, but will probably be
3.184 - messy... It might be easier to either store all upstream repo data
3.185 - in a single .repo file, or else merge all upstream .repo files
3.186 - together into a single razor_set at startup. (Or some combination
3.187 - of those.)
3.188 -
3.189 -We create a bit array of the packages in each set, indicating which
3.190 -ones are installed; the system bitarray starts out all 1s, and the
3.191 -upstream bitarray all 0s. Each bit is only allowed to change state
3.192 -once during the transaction; an installed package can be removed, or
3.193 -an uninstalled package installed, but trying to reinstall a removed
3.194 -package, or uninstall a newly-installed package is an error. This
3.195 -means the packages break down into four categories:
3.196 -
3.197 - - installed (1 bit in the system bit array)
3.198 - - to-be-removed (0 bit in the system bit array)
3.199 - - to-be-installed (1 bit in the upstream bit array)
3.200 - - installable (0 bit in the upstream bit array)
3.201 -
3.202 -
3.203 -Depsolver algorithm:
3.204 -
3.205 - - Create new razor_transaction_packages ("rtp"s) for each
3.206 - requested install or remove. These will be "unresolved", because
3.207 - we haven't yet found the razor_packages that correspond to them.
3.208 -
3.209 - - while there are new rtps:
3.210 -
3.211 - - sort the new rtps
3.212 -
3.213 - - Walk the system property list, upstream property list, and
3.214 - new rtp list in parallel, and:
3.215 -
3.216 - - For each uninstalled PROVIDES:
3.217 -
3.218 - - If the property is a valid package name (that is,
3.219 - either it's a package providing its own name, or it
3.220 - has a matching OBSOLETES), and it matches the name
3.221 - of a new rtp of type INSTALL or FORCED_UPDATE with
3.222 - an unresolved new_package:
3.223 -
3.224 - - If the upstream package has the same version as
3.225 - the system package, we have an UP_TO_DATE error
3.226 - (FIXME: not quite right. This doesn't deal with
3.227 - the case where we try to update an application
3.228 - because of a library update, and it turns out
3.229 - there's no new version of the application, but
3.230 - there IS a compat package containing the old
3.231 - version of the library.)
3.232 -
3.233 - - Otherwise, set the rtp's new_package to point to
3.234 - the package providing this property and set the
3.235 - appropriate bit in the upstream bit array.
3.236 -
3.237 - - For each to-be-installed non-file REQUIRES:
3.238 -
3.239 - - See if there's an installed or to-be-installed
3.240 - package that PROVIDES that property.
3.241 -
3.242 - - If not, see if there's an installable package that
3.243 - PROVIDES that property, and create a new INSTALL rtp
3.244 - for it if so.
3.245 -
3.246 - - If not, see if there's a to-be-removed package that
3.247 - PROVIDES that property. (If we find such a package,
3.248 - we have a CONTRADICTION error.)
3.249 -
3.250 - - If none of the above, then we have an UNSATISFIABLE
3.251 - error
3.252 -
3.253 - - For each to-be-installed file REQUIRES:
3.254 -
3.255 - - (We create fake file PROVIDES to match file REQUIRES
3.256 - when importing/merging razor sets, so if there is
3.257 - already another installed package that REQUIRES this
3.258 - file, there will be a PROVIDES listed for it as well.)
3.259 -
3.260 - - See if there's an installed package that PROVIDES
3.261 - that file.
3.262 -
3.263 - - If not, do a binary search of the system file tree
3.264 - looking to see if some installed package provides
3.265 - that file but does not have a PROVIDES for it.
3.266 -
3.267 - - If not, see if there's an installable package that
3.268 - PROVIDES that property, and create a new INSTALL rtp
3.269 - for it if so.
3.270 -
3.271 - - (If we actually work with multiple upstream
3.272 - razor_sets, then we will need to search the upstream
3.273 - file trees at this point, because it's possible that
3.274 - a package in one upstream repo would require a file
3.275 - in another upstream repo. But if we merge the
3.276 - multiple upstream repos into a single razor_set at
3.277 - some point, then we would not need to do that,
3.278 - because it would be guaranteed that we would have
3.279 - already created a fake PROVIDES if any package
3.280 - provides the file.)
3.281 -
3.282 - - If no installed or installable package provides the
3.283 - file, see if there's a to-be-removed package that
3.284 - provides the file. (If we find such a package, we
3.285 - have a CONTRADICTION error.)
3.286 -
3.287 - - If none of the above, then we have an UNSATISFIABLE
3.288 - error
3.289 -
3.290 - - For each to-be-installed PROVIDES:
3.291 -
3.292 - - Check if the new PROVIDES conflicts with an
3.293 - installed CONFLICTS. If so, create a new
3.294 - FORCED_UPDATE rtp for the installed package, so we
3.295 - can try to upgrade it to a non-conflicting version.
3.296 - (If we can't, we'll have an OLD_CONFLICT error.)
3.297 -
3.298 - - Check if the new PROVIDES conflicts with an
3.299 - installed OBSOLETES *and* the PROVIDES property
3.300 - corresponds to the name of its package. (That is,
3.301 - OBSOLETES are only matched against package names,
3.302 - not arbitrary provided properties.) If so, we have
3.303 - an ALREADY_OBSOLETE error.
3.304 -
3.305 - - Check if the new PROVIDES conflicts with a
3.306 - to-be-installed CONFLICTS. If so, we have a
3.307 - CONTRADICTION error.
3.308 -
3.309 - - For each to-be-installed CONFLICTS:
3.310 -
3.311 - - Basically the reverse of the previous case: check if
3.312 - the new CONFLICTS conflicts with an installed
3.313 - PROVIDES. If so, create a new FORCED_UPDATE rtp for
3.314 - the installed package, so we can try to upgrade it
3.315 - to a non-conflicting version. (If we can't, we'll
3.316 - have an NEW_CONFLICT error.)
3.317 -
3.318 - - Check if the new CONFLICTS conflicts with a
3.319 - to-be-installed PROVIDES. If so, we have a
3.320 - CONTRADICTION error.
3.321 -
3.322 - - For each to-be-installed OBSOLETES:
3.323 -
3.324 - - Check if there's an installed package that PROVIDES
3.325 - that property. If so, create an OBSOLETED rtp for
3.326 - the installed package.
3.327 -
3.328 - - If not, check if there's a to-be-installed package
3.329 - that PROVIDES that property. If so, we have a
3.330 - CONTRADICTION error.
3.331 -
3.332 -
3.333 - - For each installed PROVIDES:
3.334 -
3.335 - - If the property is a valid package name (that is,
3.336 - it's a package providing its own name), and it
3.337 - matches the name of a new rtp with an unresolved
3.338 - old_package, then set the rtp's old_package to point
3.339 - to the package providing this property and clear the
3.340 - appropriate bit in the system bit array.
3.341 -
3.342 - - For each to-be-removed PROVIDES:
3.343 -
3.344 - - If there's also an identical to-be-installed
3.345 - PROVIDES, we're ok and can skip this
3.346 -
3.347 - - Otherwise, for each installed REQUIRES of this
3.348 - property:
3.349 -
3.350 - - Look for some other installed or to-be-installed
3.351 - property that satisfies the REQUIRES.
3.352 -
3.353 - - If there isn't one, then for each installed
3.354 - package in this REQUIRES's package list:
3.355 -
3.356 - - If the PROVIDES was lost because the old
3.357 - package was REMOVEd (not FORCED_UPDATE or
3.358 - OBSOLETED), then create a new REMOVE rtp for
3.359 - this package.
3.360 -
3.361 - - Otherwise, create a new FORCED_UPDATE rtp
3.362 - for this package.
3.363 -
3.364 - - (We don't need to look at to-be-installed REQUIRES
3.365 - of this property, because if there are any, they
3.366 - will cause a CONTRADICTION error when we try to
3.367 - re-satisfy them the next time through.)
4.1 --- a/Makefile Sun Jun 15 23:15:59 2008 -0400
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,27 +0,0 @@
4.4 -CFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes -g
4.5 -LDLIBS = librazor.a -lexpat -lz -g -lrpm -lcurl
4.6 -
4.7 -all : razor test-driver rpm-razor
4.8 -
4.9 -librazor_objs = razor.o yum.o rpm.o types.o util.o razor-root.o
4.10 -librazor.a : $(librazor_objs)
4.11 - ar cr $@ $(librazor_objs)
4.12 -
4.13 -razor : main.o librazor.a
4.14 -
4.15 -*.o : razor.h razor-internal.h
4.16 -razor.o : types.h
4.17 -
4.18 -test-driver : librazor.a test-driver.o
4.19 -
4.20 -rpm-razor : librazor.a rpm-razor.o
4.21 -
4.22 -test : test-driver
4.23 - ./test-driver test.xml
4.24 -
4.25 -reset : ./razor
4.26 - sudo rm -rf install
4.27 - ./razor init
4.28 -
4.29 -clean :
4.30 - rm -f *.o razor librazor.a
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/Makefile.am Mon Jun 16 15:40:30 2008 -0400
5.3 @@ -0,0 +1,38 @@
5.4 +## Process this file with automake to produce Makefile.in
5.5 +
5.6 +SUBDIRS = data docs librazor src po
5.7 +
5.8 +# Creating ChangeLog from git log (taken from cairo/Makefile.am):
5.9 +ChangeLog: $(srcdir)/ChangeLog
5.10 +
5.11 +$(srcdir)/ChangeLog:
5.12 + @if test -d "$(srcdir)/.git"; then \
5.13 + (cd "$(srcdir)" && \
5.14 + ./missing --run git-log --stat) | fmt --split-only > $@.tmp \
5.15 + && mv -f $@.tmp $@ \
5.16 + || ($(RM) $@.tmp; \
5.17 + echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
5.18 + (test -f $@ || echo git-log is required to generate this file >> $@)); \
5.19 + else \
5.20 + test -f $@ || \
5.21 + (echo A git checkout and git-log is required to generate ChangeLog >&2 && \
5.22 + echo A git checkout and git-log is required to generate this file >> $@); \
5.23 + fi
5.24 +
5.25 +.PHONY: ChangeLog $(srcdir)/ChangeLog
5.26 +
5.27 +EXTRA_DIST = \
5.28 + TODO \
5.29 + ChangeLog \
5.30 + intltool-extract.in \
5.31 + intltool-merge.in \
5.32 + intltool-update.in
5.33 +
5.34 +DISTCLEANFILES = \
5.35 + intltool-extract \
5.36 + intltool-merge \
5.37 + intltool-update
5.38 +
5.39 +clean-local :
5.40 + rm -f *~
5.41 +
6.1 --- a/REPO.txt Sun Jun 15 23:15:59 2008 -0400
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,172 +0,0 @@
6.4 -The repo file format / razor_set data structure
6.5 ------------------------------------------------
6.6 -
6.7 -The repo starts with a header, containing some number of sections,
6.8 -terminated by a section with type 0:
6.9 -
6.10 - struct razor_set_header {
6.11 - uint32_t magic;
6.12 - uint32_t version;
6.13 - struct razor_set_section sections[0];
6.14 - };
6.15 -
6.16 - struct razor_set_section {
6.17 - uint32_t type;
6.18 - uint32_t offset;
6.19 - uint32_t size;
6.20 - };
6.21 -
6.22 -razor_set_open() mmaps the repo file, and creates a struct razor_set:
6.23 -
6.24 - struct razor_set {
6.25 - struct array string_pool;
6.26 - struct array packages;
6.27 - struct array properties;
6.28 - struct array files;
6.29 - struct array package_pool;
6.30 - struct array property_pool;
6.31 - struct array file_pool;
6.32 - struct razor_set_header *header;
6.33 - };
6.34 -
6.35 -by finding the sections with those IDs and creating "struct array"s
6.36 -pointing to the right places in the mmapped data. (This is the only
6.37 -processing needed when reading in the file; everything else is used
6.38 -exactly as-is.)
6.39 -
6.40 -
6.41 -The sections
6.42 -------------
6.43 -
6.44 -RAZOR_STRING_POOL
6.45 -
6.46 - Stores one copy of each string that appears in the repo. (At
6.47 - the moment, this is: package names, package versions, property
6.48 - names, property versions, and (basenames of) filenames.) The
6.49 - strings are arbitrarily-sized, 0-terminated, and not in any
6.50 - particular order (although the empty string always ends up
6.51 - being at offset 0).
6.52 -
6.53 -RAZOR_PACKAGES
6.54 -
6.55 - Array of struct razor_package; one for each package in the
6.56 - set, sorted by name.
6.57 -
6.58 -RAZOR_PROPERTIES
6.59 -
6.60 - Array of struct razor_property; one for each unique property
6.61 - in the set, sorted by type, then name, then relation type (eg,
6.62 - "<" or ">="), then version. (Properties with no version have
6.63 - relation type RAZOR_VERSION_EQUAL, and version "".)
6.64 -
6.65 -RAZOR_FILES
6.66 -
6.67 - Array of struct razor_entry; one for each file owned by any
6.68 - package in the set. The current sort order (which is subject
6.69 - to change) is breadth-first, sorted by basename. So eg: /, /bin,
6.70 - /dev, /etc, /bin/false, /bin/true, /dev/null, /etc/passwd.
6.71 -
6.72 -RAZOR_PACKAGE_POOL
6.73 -
6.74 - Array of struct list, with each list item containing the index
6.75 - of a struct razor_package in the packages section. See the
6.76 - discussion of lists below.
6.77 -
6.78 -RAZOR_PROPERTY_POOL
6.79 -
6.80 - Array of struct list, with each list item containing the index
6.81 - of a struct razor_property in the properties section. See the
6.82 - discussion of lists below.
6.83 -
6.84 -RAZOR_FILE_POOL
6.85 -
6.86 - Array of struct list, with each list item containing the index
6.87 - of a struct razor_entry in the files section. See the
6.88 - discussion of lists below.
6.89 -
6.90 -
6.91 -Data types
6.92 -----------
6.93 -Note that the exact layout of bits involves some historical accidents.
6.94 -(Particularly the fact that the "name" field in most structs loses its
6.95 -high bits to a flags field.)
6.96 -
6.97 -struct list_head
6.98 - uint list_ptr : 24;
6.99 - uint flags : 8;
6.100 -
6.101 -struct list
6.102 - uint data : 24;
6.103 - uint flags : 8;
6.104 -
6.105 - Used to store lists of package, property, or file IDs. "struct
6.106 - list_head" stores the head of the list, which points to one or
6.107 - more "struct list"s in the appropriate "pool" section.
6.108 - ("struct list" should probably be called "struct list_item".)
6.109 -
6.110 - "list_first(&head, &pool)" returns a "struct list *" pointing
6.111 - to the first element of the list (or NULL for an empty list),
6.112 - and "list_next(list)" will return successive elements, until
6.113 - NULL is returned. Each "list->data" contains the index of a
6.114 - package, property, or file in the corresponding section of the
6.115 - set.
6.116 -
6.117 - Peeking underneath the abstraction, a list_head's "flags" is
6.118 - 0xff if the list is empty, 0x80 if it contains a single
6.119 - element, or 0x00 if it contains more than one element. In the
6.120 - single-element case, that element is actually stored in the
6.121 - list_head directly rather than being stored in a pool (and so
6.122 - list_first() just casts the list_head* to a list* and returns
6.123 - it). For multi-element lists, list_ptr is the index in the
6.124 - pool of the first element of this list; the list continues
6.125 - through successive elements of the pool until one with
6.126 - non-zero flags is reached, indicating the end of the list.
6.127 -
6.128 -struct razor_package
6.129 - uint name : 24;
6.130 - uint flags : 8;
6.131 - uint version : 32;
6.132 - struct list_head properties;
6.133 - struct list_head files;
6.134 -
6.135 - name and version are indexes into string_pool. properties is a
6.136 - list of all of the package's properties, and files is a list
6.137 - of its files. flags is currently only used during razor_set
6.138 - merging, to keep track of which set a package came from.
6.139 -
6.140 -struct razor_property
6.141 - uint name : 24;
6.142 - uint flags : 6;
6.143 - uint type : 2;
6.144 - uint relation : 32;
6.145 - uint version : 32;
6.146 - struct list_head packages;
6.147 -
6.148 - name and version are indexes into string_pool. type is an enum
6.149 - razor_property_type (eg, RAZOR_PROPERTY_REQUIRES), and
6.150 - relation is an enum razor_version_relation (eg,
6.151 - RAZOR_VERSION_GREATER_OR_EQUAL). packages is a list of the
6.152 - packages that have this property. flags is currently unused.
6.153 -
6.154 -struct razor_entry
6.155 - uint name : 24;
6.156 - uint flags : 8;
6.157 - uint start : 32;
6.158 - struct list_head packages;
6.159 -
6.160 - name is an index into string_pool, giving the basename of the
6.161 - file. start is either 0, or an index pointing to another
6.162 - razor_entry that is the first child of this entry (for a
6.163 - non-empty directory). (Entry 0 is always the root of the tree,
6.164 - so no entry could have entry 0 as a child.) flags is 0x80
6.165 - (RAZOR_ENTRY_LAST) if an entry is the last entry in its
6.166 - directory. Otherwise it is 0.
6.167 -
6.168 - Note that given a pointer to a struct_razor_entry (eg, from a
6.169 - package's "files" list), there is no way to reconstruct its
6.170 - full name without walking the entire files array up to that
6.171 - point. Because of this and other problems (fix_file_map()), it
6.172 - seems like razor_entry should be modified to include a pointer
6.173 - to its parent. (Storing full paths instead of just basenames
6.174 - would also fix this problem, but that would use much more
6.175 - memory.)
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/autogen.sh Mon Jun 16 15:40:30 2008 -0400
7.3 @@ -0,0 +1,95 @@
7.4 +#!/bin/sh
7.5 +# Run this to generate all the initial makefiles, etc.
7.6 +
7.7 +srcdir=`dirname $0`
7.8 +test -z "$srcdir" && srcdir=.
7.9 +
7.10 +DIE=0
7.11 +
7.12 +(test -f $srcdir/configure.ac) || {
7.13 + echo -n "**Error**: Directory $srcdir does not look like the"
7.14 + echo " top-level package directory"
7.15 + exit 1
7.16 +}
7.17 +
7.18 +(autoconf --version) < /dev/null > /dev/null 2>&1 || {
7.19 + echo
7.20 + echo "**Error**: You must have autoconf installed."
7.21 + echo "Download the appropriate package for your distribution,"
7.22 + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
7.23 + DIE=1
7.24 +}
7.25 +
7.26 +(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
7.27 + (libtool --version) < /dev/null > /dev/null 2>&1 || {
7.28 + echo
7.29 + echo "**Error**: You must have libtool installed."
7.30 + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
7.31 + DIE=1
7.32 + }
7.33 +}
7.34 +
7.35 +(automake --version) < /dev/null > /dev/null 2>&1 || {
7.36 + echo
7.37 + echo "**Error**: You must have automake installed."
7.38 + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
7.39 + DIE=1
7.40 + NO_AUTOMAKE=yes
7.41 +}
7.42 +
7.43 +
7.44 +# if no automake, don't bother testing for aclocal
7.45 +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
7.46 + echo
7.47 + echo "**Error**: Missing aclocal. The version of automake"
7.48 + echo "installed doesn't appear recent enough."
7.49 + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
7.50 + DIE=1
7.51 +}
7.52 +
7.53 +if test "$DIE" -eq 1; then
7.54 + exit 1
7.55 +fi
7.56 +
7.57 +if test -z "$*"; then
7.58 + echo "**Warning**: I am going to run configure with no arguments."
7.59 + echo "If you wish to pass any to it, please specify them on the"
7.60 + echo $0 " command line."
7.61 + echo
7.62 +fi
7.63 +
7.64 +case $CC in
7.65 +xlc )
7.66 + am_opt=--include-deps;;
7.67 +esac
7.68 +
7.69 + aclocalinclude="$ACLOCAL_FLAGS"
7.70 +
7.71 + if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then
7.72 + if test -z "$NO_LIBTOOLIZE" ; then
7.73 + echo "Running libtoolize..."
7.74 + libtoolize --force --copy
7.75 + fi
7.76 + fi
7.77 + echo "Running aclocal $aclocalinclude ..."
7.78 + aclocal $aclocalinclude
7.79 + if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then
7.80 + echo "Running autoheader..."
7.81 + autoheader
7.82 + fi
7.83 + echo "Running automake --gnu -Wno-portability $am_opt ..."
7.84 + automake --add-missing --gnu -Wno-portability $am_opt
7.85 + echo "Running autoconf ..."
7.86 + autoconf
7.87 +
7.88 +intltoolize --copy --force --automake || exit 1
7.89 +
7.90 +conf_flags="--enable-maintainer-mode"
7.91 +
7.92 +if test x$NOCONFIGURE = x; then
7.93 + echo "Running $srcdir/configure $conf_flags $@ ..."
7.94 + $srcdir/configure $conf_flags "$@" \
7.95 + && echo "Now type make to compile." || exit 1
7.96 +else
7.97 + echo "Skipping configure process."
7.98 +fi
8.1 --- a/bash-completion.sh Sun Jun 15 23:15:59 2008 -0400
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,47 +0,0 @@
8.4 -__razor_commands () {
8.5 - local IFS=$'\n'
8.6 - COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:list-package-files:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff:install:init:download" -- $1))
8.7 -}
8.8 -
8.9 -__razor_packages () {
8.10 - local IFS=$'\n'
8.11 -
8.12 - COMPREPLY=($(./razor list --only-names "$1*" | while read p; do echo "$p "; done))
8.13 -}
8.14 -
8.15 -__razor_upstream_packages () {
8.16 - local IFS=$'\n'
8.17 -
8.18 - COMPREPLY=($(RAZOR_REPO=rawhide.repo ./razor list --only-names "$1*" | while read p; do echo "$p "; done))
8.19 -}
8.20 -
8.21 -__razor_files() {
8.22 - COMPREPLY=($(./razor list-files "$1*"))
8.23 -}
8.24 -
8.25 -__razor_requires() {
8.26 - COMPREPLY=($(compgen -W "$(./razor list-requires)" -- $1))
8.27 -}
8.28 -
8.29 -__razor_provides() {
8.30 - COMPREPLY=($(compgen -W "$(./razor list-provides)" -- $1))
8.31 -}
8.32 -
8.33 -__razor() {
8.34 - local cur="${COMP_WORDS[COMP_CWORD]}"
8.35 -
8.36 - if [ $COMP_CWORD = 1 ]; then
8.37 - __razor_commands $cur
8.38 - else
8.39 - case "${COMP_WORDS[1]}" in
8.40 - list-requires|list-provides|list-package-files)
8.41 - __razor_packages $cur ;;
8.42 - list-files|list-file-packages) __razor_files $cur ;;
8.43 - what-requires) __razor_requires $cur ;;
8.44 - what-provides) __razor_provides $cur ;;
8.45 - install|download) __razor_upstream_packages $cur ;;
8.46 - esac
8.47 - fi
8.48 -}
8.49 -
8.50 -complete -o nospace -F __razor razor
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/configure.ac Mon Jun 16 15:40:30 2008 -0400
9.3 @@ -0,0 +1,201 @@
9.4 +dnl Process this file with autoconf to produce a configure script.
9.5 +
9.6 +AC_PREREQ(2.59c)
9.7 +AC_INIT(razor, 0.8, krh@redhat.com)
9.8 +AM_INIT_AUTOMAKE(razor, 0.1)
9.9 +AM_CONFIG_HEADER(config.h)
9.10 +AM_MAINTAINER_MODE
9.11 +
9.12 +# libtool versioning - this applies to all libraries in this package
9.13 +#
9.14 +# See http://sources.redhat.com/autobook/autobook/autobook_91.html#SEC91 for details
9.15 +#
9.16 +LT_CURRENT=1
9.17 +LT_REVISION=0
9.18 +LT_AGE=0
9.19 +AC_SUBST(LT_CURRENT)
9.20 +AC_SUBST(LT_REVISION)
9.21 +AC_SUBST(LT_AGE)
9.22 +
9.23 +AC_ISC_POSIX
9.24 +AC_PROG_CC
9.25 +AM_PROG_CC_STDC
9.26 +AC_HEADER_STDC
9.27 +AM_PROG_LIBTOOL
9.28 +AC_PROG_MAKE_SET
9.29 +AC_PROG_LN_S
9.30 +AC_SYS_LARGEFILE
9.31 +AM_PROG_CC_C_O
9.32 +
9.33 +# Taken from dbus
9.34 +AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
9.35 +AC_ARG_ENABLE(verbose-mode, [ --enable-verbose-mode support verbose debug mode],enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
9.36 +
9.37 +if test "${enable_verbose_mode}" != no; then
9.38 + # To get -rdynamic you pass -export-dynamic to libtool.
9.39 + AC_DEFINE(BUILT_R_DYNAMIC,1,[whether -export-dynamic was passed to libtool])
9.40 + R_DYNAMIC_LDFLAG=-export-dynamic
9.41 +else
9.42 + R_DYNAMIC_LDFLAG=
9.43 +fi
9.44 +AC_SUBST(R_DYNAMIC_LDFLAG)
9.45 +
9.46 +#### gcc warning flags
9.47 +
9.48 +if test "x$GCC" = "xyes"; then
9.49 + changequote(,)dnl
9.50 + case " $CFLAGS " in
9.51 + *[\ \ ]-Wall[\ \ ]*) ;;
9.52 + *) CFLAGS="$CFLAGS -Wall" ;;
9.53 + esac
9.54 +
9.55 + case " $CFLAGS " in
9.56 + *[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
9.57 + *) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
9.58 + esac
9.59 +
9.60 + case " $CFLAGS " in
9.61 + *[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
9.62 + *) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
9.63 + esac
9.64 +
9.65 + case " $CFLAGS " in
9.66 + *[\ \ ]-Wnested-externs[\ \ ]*) ;;
9.67 + *) CFLAGS="$CFLAGS -Wnested-externs" ;;
9.68 + esac
9.69 +
9.70 + case " $CFLAGS " in
9.71 + *[\ \ ]-Wcast-align[\ \ ]*) ;;
9.72 + *) CFLAGS="$CFLAGS -Wcast-align" ;;
9.73 + esac
9.74 +
9.75 + case " $CFLAGS " in
9.76 + *[\ \ ]-Wformat[\ \ ]*) ;;
9.77 + *) CFLAGS="$CFLAGS -Wformat" ;;
9.78 + esac
9.79 +
9.80 + case " $CFLAGS " in
9.81 + *[\ \ ]-Wformat-security[\ \ ]*) ;;
9.82 + *) CFLAGS="$CFLAGS -Wformat-security" ;;
9.83 + esac
9.84 +
9.85 + if test "x$enable_ansi" = "xyes"; then
9.86 + case " $CFLAGS " in
9.87 + *[\ \ ]-ansi[\ \ ]*) ;;
9.88 + *) CFLAGS="$CFLAGS -ansi" ;;
9.89 + esac
9.90 +
9.91 + case " $CFLAGS " in
9.92 + *[\ \ ]-D_POSIX_C_SOURCE*) ;;
9.93 + *) CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=199309L" ;;
9.94 + esac
9.95 +
9.96 + case " $CFLAGS " in
9.97 + *[\ \ ]-D_BSD_SOURCE[\ \ ]*) ;;
9.98 + *) CFLAGS="$CFLAGS -D_BSD_SOURCE" ;;
9.99 + esac
9.100 +
9.101 + case " $CFLAGS " in
9.102 + *[\ \ ]-pedantic[\ \ ]*) ;;
9.103 + *) CFLAGS="$CFLAGS -pedantic" ;;
9.104 + esac
9.105 + fi
9.106 + changequote([,])dnl
9.107 +fi
9.108 +
9.109 +PKG_CHECK_MODULES(CURL, [libcurl])
9.110 +AC_SUBST(CURL_CFLAGS)
9.111 +AC_SUBST(CURL_LIBS)
9.112 +
9.113 +ZLIB_LIBS=""
9.114 +AC_ARG_WITH(zlib, [ --with-zlib=<dir> Use zlib from here],
9.115 + [
9.116 + zlib=$withval
9.117 + CPPFLAGS="$CPPFLAGS -I$withval/include"
9.118 + LDFLAGS="$LDFLAGS -L$withval/lib"
9.119 + ]
9.120 + )
9.121 +AC_CHECK_HEADERS(zlib.h, [AC_DEFINE(HAVE_ZLIB_H)],
9.122 + [AC_MSG_ERROR([Can't find zlib.h. Please install zlib.])])
9.123 +AC_CHECK_LIB(z, inflate, [ZLIB_LIBS="-lz"],
9.124 + [AC_MSG_ERROR([Can't find zlib library. Please install zlib.])])
9.125 +AC_SUBST(ZLIB_LIBS)
9.126 +
9.127 +EXPAT_LIB=""
9.128 +AC_ARG_WITH(expat, [ --with-expat=<dir> Use expat from here],
9.129 + [
9.130 + expat=$withval
9.131 + CPPFLAGS="$CPPFLAGS -I$withval/include"
9.132 + LDFLAGS="$LDFLAGS -L$withval/lib"
9.133 + ]
9.134 + )
9.135 +AC_CHECK_HEADERS(expat.h, [AC_DEFINE(HAVE_EXPAT_H)],
9.136 + [AC_MSG_ERROR([Can't find expat.h. Please install expat.])])
9.137 +AC_CHECK_LIB(expat, XML_ParserCreate, [EXPAT_LIBS="-lexpat"],
9.138 + [AC_MSG_ERROR([Can't find expat library. Please install expat.])])
9.139 +AC_SUBST(EXPAT_LIBS)
9.140 +
9.141 +RPM_LIB=""
9.142 +AC_ARG_WITH(rpm, [ --with-rpm=<dir> Use rpm from here],
9.143 + [
9.144 + rpm=$withval
9.145 + CPPFLAGS="$CPPFLAGS -I$withval/include"
9.146 + LDFLAGS="$LDFLAGS -L$withval/lib"
9.147 + ]
9.148 + )
9.149 +AC_CHECK_HEADERS(rpm/rpmlib.h, [],
9.150 + [AC_MSG_ERROR([Can't find rpm/rpmlib.h. Please install rpm-devel.])])
9.151 +AC_CHECK_LIB(rpm,rpmdbOpen,[RPM_LIBS="-lrpm"],
9.152 + [AC_MSG_ERROR([Can't find rpm library. Please install rpm-devel.])])
9.153 +AC_SUBST(RPM_LIBS)
9.154 +
9.155 +if test "x$GCC" = "xyes"; then
9.156 + LDFLAGS="-Wl,--as-needed $LDFLAGS"
9.157 +fi
9.158 +
9.159 +# *****************************
9.160 +# Make available to Makefile.am
9.161 +# *****************************
9.162 +AC_SUBST(SYSCONFDIR, $sysconfdir)
9.163 +
9.164 +# ********************
9.165 +# Internationalisation
9.166 +# ********************
9.167 +
9.168 +IT_PROG_INTLTOOL([0.36.0])
9.169 +GETTEXT_PACKAGE=razor
9.170 +AC_SUBST([GETTEXT_PACKAGE])
9.171 +AM_GLIB_GNU_GETTEXT
9.172 +AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"],[gettext domain])
9.173 +
9.174 +AC_OUTPUT([
9.175 +Makefile
9.176 +data/razor.pc
9.177 +data/Makefile
9.178 +librazor/Makefile
9.179 +src/Makefile
9.180 +docs/Makefile
9.181 +po/Makefile.in
9.182 +])
9.183 +
9.184 +dnl ==========================================================================
9.185 +echo "
9.186 + razor $VERSION
9.187 + =================
9.188 +
9.189 + prefix: ${prefix}
9.190 + libdir: ${libdir}
9.191 + libexecdir: ${libexecdir}
9.192 + bindir: ${bindir}
9.193 + sbindir: ${sbindir}
9.194 + datadir: ${datadir}
9.195 + sysconfdir: ${sysconfdir}
9.196 + localstatedir: ${localstatedir}
9.197 + docdir: ${docdir}
9.198 +
9.199 + compiler: ${CC}
9.200 + cflags: ${CFLAGS}
9.201 + Maintainer mode: ${USE_MAINTAINER_MODE}
9.202 + Building verbose mode: ${enable_verbose_mode}
9.203 +"
9.204 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/data/.gitignore Mon Jun 16 15:40:30 2008 -0400
10.3 @@ -0,0 +1,2 @@
10.4 +razor.pc
10.5 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/data/Makefile.am Mon Jun 16 15:40:30 2008 -0400
11.3 @@ -0,0 +1,11 @@
11.4 +## Process this file with automake to produce Makefile.in
11.5 +
11.6 +pkgconfigdir = $(libdir)/pkgconfig
11.7 +pkgconfig_DATA = razor.pc
11.8 +
11.9 +bashcompletiondir = ${SYSCONFDIR}/bash_completion.d
11.10 +dist_bashcompletion_DATA = bash-completion.sh
11.11 +
11.12 +clean-local :
11.13 + rm -f *~
11.14 +
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/data/bash-completion.sh Mon Jun 16 15:40:30 2008 -0400
12.3 @@ -0,0 +1,47 @@
12.4 +__razor_commands () {
12.5 + local IFS=$'\n'
12.6 + COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:list-package-files:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff:install:init:download" -- $1))
12.7 +}
12.8 +
12.9 +__razor_packages () {
12.10 + local IFS=$'\n'
12.11 +
12.12 + COMPREPLY=($(./razor list --only-names "$1*" | while read p; do echo "$p "; done))
12.13 +}
12.14 +
12.15 +__razor_upstream_packages () {
12.16 + local IFS=$'\n'
12.17 +
12.18 + COMPREPLY=($(RAZOR_REPO=rawhide.repo ./razor list --only-names "$1*" | while read p; do echo "$p "; done))
12.19 +}
12.20 +
12.21 +__razor_files() {
12.22 + COMPREPLY=($(./razor list-files "$1*"))
12.23 +}
12.24 +
12.25 +__razor_requires() {
12.26 + COMPREPLY=($(compgen -W "$(./razor list-requires)" -- $1))
12.27 +}
12.28 +
12.29 +__razor_provides() {
12.30 + COMPREPLY=($(compgen -W "$(./razor list-provides)" -- $1))
12.31 +}
12.32 +
12.33 +__razor() {
12.34 + local cur="${COMP_WORDS[COMP_CWORD]}"
12.35 +
12.36 + if [ $COMP_CWORD = 1 ]; then
12.37 + __razor_commands $cur
12.38 + else
12.39 + case "${COMP_WORDS[1]}" in
12.40 + list-requires|list-provides|list-package-files)
12.41 + __razor_packages $cur ;;
12.42 + list-files|list-file-packages) __razor_files $cur ;;
12.43 + what-requires) __razor_requires $cur ;;
12.44 + what-provides) __razor_provides $cur ;;
12.45 + install|download) __razor_upstream_packages $cur ;;
12.46 + esac
12.47 + fi
12.48 +}
12.49 +
12.50 +complete -o nospace -F __razor razor
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/data/razor.pc.in Mon Jun 16 15:40:30 2008 -0400
13.3 @@ -0,0 +1,12 @@
13.4 +prefix=@prefix@
13.5 +exec_prefix=@exec_prefix@
13.6 +libdir=@libdir@
13.7 +includedir=@includedir@
13.8 +
13.9 +Name: razor
13.10 +Description: library for depsolving, installing and removing packages
13.11 +Version: @VERSION@
13.12 +Requires: expat curl
13.13 +Libs: -L${libdir} -lexpat -lz -lcurl
13.14 +Cflags: -I${includedir}/razor
13.15 +
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/docs/DEPSOLVE.txt Mon Jun 16 15:40:30 2008 -0400
14.3 @@ -0,0 +1,364 @@
14.4 +YUM vs RAZOR
14.5 +------------
14.6 +
14.7 +At a very high level, yum's depsolver does something roughly
14.8 +equivalent to:
14.9 +
14.10 + - For each package being installed or removed
14.11 +
14.12 + - For each relevant property (provides, requires, conflicts,
14.13 + obsoletes):
14.14 +
14.15 + - Figure out what additional packages need to be added to
14.16 + or removed from the system to satisfy this property
14.17 +
14.18 +which ends up being roughly O(N^2 * M) where N is the total number of
14.19 +properties and M is the number of packages being acted on.
14.20 +
14.21 +(I just figured that out off the top of my head, and I'm not totally
14.22 +familiar with the yum code, so it may be wrong.)
14.23 +
14.24 +Razor's depsolver is something like:
14.25 +
14.26 + - do {
14.27 +
14.28 + - For each property to be added to or removed from the system:
14.29 +
14.30 + - Figure out what packages need to be added to or removed
14.31 + from the system to satisfy this property
14.32 +
14.33 + - } until we stop adding/remove more packages
14.34 +
14.35 +with the key being that it's very easy to find the PROVIDES
14.36 +corresponding to a REQUIRES and vice versa, because the property
14.37 +arrays are sorted, and so all properties with the same "name" will be
14.38 +adjacent to one another in the array, allowing many dependencies to be
14.39 +satisified in essentially constant time. (Actually... we've been
14.40 +calling it constant, but it's really O(log N) for heavily-depended-on
14.41 +packages, because the more packages you have, the more variations on
14.42 +"requires foo", "requires foo = 1.1", "requires foo > 1.0", etc you're
14.43 +going to have to scan through.)
14.44 +
14.45 +Ideally though, each iteration of the inner loop body happens in
14.46 +constant time, and thus the inner loop as a whole is O(N), and thus
14.47 +the depsolver as a whole is O(N * M) (or at least, less than
14.48 +O(N * M * log N).
14.49 +
14.50 +
14.51 +FILE DEPENDENCIES
14.52 +-----------------
14.53 +
14.54 +Whenever we add a package with a file REQUIRES to a razor_set, we also
14.55 +add a PROVIDES for that file to the package or packages which provide
14.56 +that file. This means that if we later add another package that
14.57 +requires the same file (eg, /bin/sh or /usr/bin/perl), we can resolve
14.58 +its file requirement exactly like we would resolve a property
14.59 +requirement, in nearly constant time.
14.60 +
14.61 +When adding a *new* file requirement (ie, a requirement on a file that
14.62 +no existing package depends on), we still have to scan through the
14.63 +file tree, which is O(log N) in the number of files.
14.64 +
14.65 +(AFAICT, there's no reason yum couldn't do the same optimization.
14.66 +Also, AFAICT, yum currently sticks property dependencies and file
14.67 +dependencies into the same hash table, so that if any package in the
14.68 +transaction has a file dependency, it causes *property* dependencies
14.69 +to become slower to resolve as well...)
14.70 +
14.71 +
14.72 +THE RULES
14.73 +---------
14.74 +
14.75 +This is what we have figured out for transaction-solving rules;
14.76 +neither yum nor rpm's algorithm seems to be explained in full
14.77 +anywhere...
14.78 +
14.79 + 1. Every requested install in the initial package set must be
14.80 + satisfied as either a new install or an update:
14.81 +
14.82 + - if the requested package name is the name of an upstream
14.83 + package:
14.84 +
14.85 + - if there is not a corresponding already-installed
14.86 + package, then install the upstream package
14.87 +
14.88 + - else if the upstream package is newer than the
14.89 + already-installed package, then update the package
14.90 +
14.91 + - else it's an error (UP_TO_DATE)
14.92 +
14.93 + - else if the requested package name is the name of an
14.94 + already-installed package:
14.95 +
14.96 + - if there is an upstream package that obsoletes the
14.97 + already-installed package, then behave as though the
14.98 + user had requested that that package be installed
14.99 + instead.
14.100 +
14.101 + - else it's an error (UP_TO_DATE or INSTALL_UNAVAILABLE?)
14.102 +
14.103 + - else it's an error (INSTALL_UNAVAILABLE)
14.104 +
14.105 + 2. Every requested removal in the initial package set must be
14.106 + satisfied as a removal. If any requested package name is not
14.107 + the name of an installed package, it's an error
14.108 + (REMOVE_NOT_INSTALLED)
14.109 +
14.110 + REQUIRES processing:
14.111 +
14.112 + 3. If a package being installed or updated-to REQUIRES a property
14.113 + that is not provided by any installed or to-be-installed
14.114 + package, we need to find an installable package that provides
14.115 + that property. If we find one, install/update it. If not, it's
14.116 + an error (UNSATISFIABLE). (If we find an upstream package
14.117 + providing the property that corresponds to a system package
14.118 + that's being removed, then it's a CONTRADICTION.)
14.119 +
14.120 + 4. If an already-installed package REQUIRES a property which is
14.121 + only provided by a package that is being removed, then that
14.122 + package needs to be removed as well.
14.123 +
14.124 + 5. If an already-installed package REQUIRES a property which is
14.125 + only provided by a package that is being upgraded or obsoleted
14.126 + (to a new package which does not provide that property), then:
14.127 +
14.128 + - if there is an update for the installed package, then update
14.129 + the installed package
14.130 +
14.131 + - else if there is another installable package that provides
14.132 + the required property, then install that.
14.133 +
14.134 + - else it's an error (UNSATISFIABLE?)
14.135 +
14.136 + CONFLICTS processing
14.137 +
14.138 + 6. If a package being installed or updated-to CONFLICTS with a
14.139 + property provided by an installed package:
14.140 +
14.141 + - if there is an update for the installed package, which the
14.142 + new package does not conflict with, then update the
14.143 + installed package.
14.144 +
14.145 + - else it's an error (NEW_CONFLICT)
14.146 +
14.147 + 7. If an already-installed package CONFLICTS with a property
14.148 + provided by a to-be-installed package:
14.149 +
14.150 + - if there is an update for the installed package, which does
14.151 + not conflict with the new package, then update the installed
14.152 + package.
14.153 +
14.154 + - else it's an error (NEW_CONFLICT)
14.155 +
14.156 + 8. If a package being installed or updated-to CONFLICTS with a
14.157 + property provided by a to-be-installed package, then it's an
14.158 + error (CONTRADICTION).
14.159 +
14.160 + OBSOLETES processing. NOTE: OBSOLETES are only matched against
14.161 + package names, not against arbitrary provided properties
14.162 +
14.163 + 9. If a package being installed or updated-to OBSOLETES an
14.164 + installed package, then obsolete that package. (ie, remove it,
14.165 + but treat it as updated for purposes of dangling REQUIRES).
14.166 +
14.167 + 10. If an already-installed package OBSOLETES a to-be-installed
14.168 + package, then it's an error. (ALREADY_OBSOLETE)
14.169 +
14.170 + 11. If a package being installed or updated-to OBSOLETES another
14.171 + package being installed or updated-to, then it's an error
14.172 + (CONTRADICTION).
14.173 +
14.174 +
14.175 +
14.176 +THE DEPSOLVER
14.177 +-------------
14.178 +
14.179 +We start with two razor_sets, system and upstream, and a list of
14.180 +requested installations and removals.
14.181 +
14.182 + FIXME: what about multiple upstream repos? Having to deal with
14.183 + arbitrary numbers of razor_sets is possible, but will probably be
14.184 + messy... It might be easier to either store all upstream repo data
14.185 + in a single .repo file, or else merge all upstream .repo files
14.186 + together into a single razor_set at startup. (Or some combination
14.187 + of those.)
14.188 +
14.189 +We create a bit array of the packages in each set, indicating which
14.190 +ones are installed; the system bitarray starts out all 1s, and the
14.191 +upstream bitarray all 0s. Each bit is only allowed to change state
14.192 +once during the transaction; an installed package can be removed, or
14.193 +an uninstalled package installed, but trying to reinstall a removed
14.194 +package, or uninstall a newly-installed package is an error. This
14.195 +means the packages break down into four categories:
14.196 +
14.197 + - installed (1 bit in the system bit array)
14.198 + - to-be-removed (0 bit in the system bit array)
14.199 + - to-be-installed (1 bit in the upstream bit array)
14.200 + - installable (0 bit in the upstream bit array)
14.201 +
14.202 +
14.203 +Depsolver algorithm:
14.204 +
14.205 + - Create new razor_transaction_packages ("rtp"s) for each
14.206 + requested install or remove. These will be "unresolved", because
14.207 + we haven't yet found the razor_packages that correspond to them.
14.208 +
14.209 + - while there are new rtps:
14.210 +
14.211 + - sort the new rtps
14.212 +
14.213 + - Walk the system property list, upstream property list, and
14.214 + new rtp list in parallel, and:
14.215 +
14.216 + - For each uninstalled PROVIDES:
14.217 +
14.218 + - If the property is a valid package name (that is,
14.219 + either it's a package providing its own name, or it
14.220 + has a matching OBSOLETES), and it matches the name
14.221 + of a new rtp of type INSTALL or FORCED_UPDATE with
14.222 + an unresolved new_package:
14.223 +
14.224 + - If the upstream package has the same version as
14.225 + the system package, we have an UP_TO_DATE error
14.226 + (FIXME: not quite right. This doesn't deal with
14.227 + the case where we try to update an application
14.228 + because of a library update, and it turns out
14.229 + there's no new version of the application, but
14.230 + there IS a compat package containing the old
14.231 + version of the library.)
14.232 +
14.233 + - Otherwise, set the rtp's new_package to point to
14.234 + the package providing this property and set the
14.235 + appropriate bit in the upstream bit array.
14.236 +
14.237 + - For each to-be-installed non-file REQUIRES:
14.238 +
14.239 + - See if there's an installed or to-be-installed
14.240 + package that PROVIDES that property.
14.241 +
14.242 + - If not, see if there's an installable package that
14.243 + PROVIDES that property, and create a new INSTALL rtp
14.244 + for it if so.
14.245 +
14.246 + - If not, see if there's a to-be-removed package that
14.247 + PROVIDES that property. (If we find such a package,
14.248 + we have a CONTRADICTION error.)
14.249 +
14.250 + - If none of the above, then we have an UNSATISFIABLE
14.251 + error
14.252 +
14.253 + - For each to-be-installed file REQUIRES:
14.254 +
14.255 + - (We create fake file PROVIDES to match file REQUIRES
14.256 + when importing/merging razor sets, so if there is
14.257 + already another installed package that REQUIRES this
14.258 + file, there will be a PROVIDES listed for it as well.)
14.259 +
14.260 + - See if there's an installed package that PROVIDES
14.261 + that file.
14.262 +
14.263 + - If not, do a binary search of the system file tree
14.264 + looking to see if some installed package provides
14.265 + that file but does not have a PROVIDES for it.
14.266 +
14.267 + - If not, see if there's an installable package that
14.268 + PROVIDES that property, and create a new INSTALL rtp
14.269 + for it if so.
14.270 +
14.271 + - (If we actually work with multiple upstream
14.272 + razor_sets, then we will need to search the upstream
14.273 + file trees at this point, because it's possible that
14.274 + a package in one upstream repo would require a file
14.275 + in another upstream repo. But if we merge the
14.276 + multiple upstream repos into a single razor_set at
14.277 + some point, then we would not need to do that,
14.278 + because it would be guaranteed that we would have
14.279 + already created a fake PROVIDES if any package
14.280 + provides the file.)
14.281 +
14.282 + - If no installed or installable package provides the
14.283 + file, see if there's a to-be-removed package that
14.284 + provides the file. (If we find such a package, we
14.285 + have a CONTRADICTION error.)
14.286 +
14.287 + - If none of the above, then we have an UNSATISFIABLE
14.288 + error
14.289 +
14.290 + - For each to-be-installed PROVIDES:
14.291 +
14.292 + - Check if the new PROVIDES conflicts with an
14.293 + installed CONFLICTS. If so, create a new
14.294 + FORCED_UPDATE rtp for the installed package, so we
14.295 + can try to upgrade it to a non-conflicting version.
14.296 + (If we can't, we'll have an OLD_CONFLICT error.)
14.297 +
14.298 + - Check if the new PROVIDES conflicts with an
14.299 + installed OBSOLETES *and* the PROVIDES property
14.300 + corresponds to the name of its package. (That is,
14.301 + OBSOLETES are only matched against package names,
14.302 + not arbitrary provided properties.) If so, we have
14.303 + an ALREADY_OBSOLETE error.
14.304 +
14.305 + - Check if the new PROVIDES conflicts with a
14.306 + to-be-installed CONFLICTS. If so, we have a
14.307 + CONTRADICTION error.
14.308 +
14.309 + - For each to-be-installed CONFLICTS:
14.310 +
14.311 + - Basically the reverse of the previous case: check if
14.312 + the new CONFLICTS conflicts with an installed
14.313 + PROVIDES. If so, create a new FORCED_UPDATE rtp for
14.314 + the installed package, so we can try to upgrade it
14.315 + to a non-conflicting version. (If we can't, we'll
14.316 + have an NEW_CONFLICT error.)
14.317 +
14.318 + - Check if the new CONFLICTS conflicts with a
14.319 + to-be-installed PROVIDES. If so, we have a
14.320 + CONTRADICTION error.
14.321 +
14.322 + - For each to-be-installed OBSOLETES:
14.323 +
14.324 + - Check if there's an installed package that PROVIDES
14.325 + that property. If so, create an OBSOLETED rtp for
14.326 + the installed package.
14.327 +
14.328 + - If not, check if there's a to-be-installed package
14.329 + that PROVIDES that property. If so, we have a
14.330 + CONTRADICTION error.
14.331 +
14.332 +
14.333 + - For each installed PROVIDES:
14.334 +
14.335 + - If the property is a valid package name (that is,
14.336 + it's a package providing its own name), and it
14.337 + matches the name of a new rtp with an unresolved
14.338 + old_package, then set the rtp's old_package to point
14.339 + to the package providing this property and clear the
14.340 + appropriate bit in the system bit array.
14.341 +
14.342 + - For each to-be-removed PROVIDES:
14.343 +
14.344 + - If there's also an identical to-be-installed
14.345 + PROVIDES, we're ok and can skip this
14.346 +
14.347 + - Otherwise, for each installed REQUIRES of this
14.348 + property:
14.349 +
14.350 + - Look for some other installed or to-be-installed
14.351 + property that satisfies the REQUIRES.
14.352 +
14.353 + - If there isn't one, then for each installed
14.354 + package in this REQUIRES's package list:
14.355 +
14.356 + - If the PROVIDES was lost because the old
14.357 + package was REMOVEd (not FORCED_UPDATE or
14.358 + OBSOLETED), then create a new REMOVE rtp for
14.359 + this package.
14.360 +
14.361 + - Otherwise, create a new FORCED_UPDATE rtp
14.362 + for this package.
14.363 +
14.364 + - (We don't need to look at to-be-installed REQUIRES
14.365 + of this property, because if there are any, they
14.366 + will cause a CONTRADICTION error when we try to
14.367 + re-satisfy them the next time through.)
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/docs/Makefile.am Mon Jun 16 15:40:30 2008 -0400
15.3 @@ -0,0 +1,5 @@
15.4 +
15.5 +EXTRA_DIST = \
15.6 + DEPSOLVE.txt \
15.7 + REPO.txt
15.8 +
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/docs/REPO.txt Mon Jun 16 15:40:30 2008 -0400
16.3 @@ -0,0 +1,172 @@
16.4 +The repo file format / razor_set data structure
16.5 +-----------------------------------------------
16.6 +
16.7 +The repo starts with a header, containing some number of sections,
16.8 +terminated by a section with type 0:
16.9 +
16.10 + struct razor_set_header {
16.11 + uint32_t magic;
16.12 + uint32_t version;
16.13 + struct razor_set_section sections[0];
16.14 + };
16.15 +
16.16 + struct razor_set_section {
16.17 + uint32_t type;
16.18 + uint32_t offset;
16.19 + uint32_t size;
16.20 + };
16.21 +
16.22 +razor_set_open() mmaps the repo file, and creates a struct razor_set:
16.23 +
16.24 + struct razor_set {
16.25 + struct array string_pool;
16.26 + struct array packages;
16.27 + struct array properties;
16.28 + struct array files;
16.29 + struct array package_pool;
16.30 + struct array property_pool;
16.31 + struct array file_pool;
16.32 + struct razor_set_header *header;
16.33 + };
16.34 +
16.35 +by finding the sections with those IDs and creating "struct array"s
16.36 +pointing to the right places in the mmapped data. (This is the only
16.37 +processing needed when reading in the file; everything else is used
16.38 +exactly as-is.)
16.39 +
16.40 +
16.41 +The sections
16.42 +------------
16.43 +
16.44 +RAZOR_STRING_POOL
16.45 +
16.46 + Stores one copy of each string that appears in the repo. (At
16.47 + the moment, this is: package names, package versions, property
16.48 + names, property versions, and (basenames of) filenames.) The
16.49 + strings are arbitrarily-sized, 0-terminated, and not in any
16.50 + particular order (although the empty string always ends up
16.51 + being at offset 0).
16.52 +
16.53 +RAZOR_PACKAGES
16.54 +
16.55 + Array of struct razor_package; one for each package in the
16.56 + set, sorted by name.
16.57 +
16.58 +RAZOR_PROPERTIES
16.59 +
16.60 + Array of struct razor_property; one for each unique property
16.61 + in the set, sorted by type, then name, then relation type (eg,
16.62 + "<" or ">="), then version. (Properties with no version have
16.63 + relation type RAZOR_VERSION_EQUAL, and version "".)
16.64 +
16.65 +RAZOR_FILES
16.66 +
16.67 + Array of struct razor_entry; one for each file owned by any
16.68 + package in the set. The current sort order (which is subject
16.69 + to change) is breadth-first, sorted by basename. So eg: /, /bin,
16.70 + /dev, /etc, /bin/false, /bin/true, /dev/null, /etc/passwd.
16.71 +
16.72 +RAZOR_PACKAGE_POOL
16.73 +
16.74 + Array of struct list, with each list item containing the index
16.75 + of a struct razor_package in the packages section. See the
16.76 + discussion of lists below.
16.77 +
16.78 +RAZOR_PROPERTY_POOL
16.79 +
16.80 + Array of struct list, with each list item containing the index
16.81 + of a struct razor_property in the properties section. See the
16.82 + discussion of lists below.
16.83 +
16.84 +RAZOR_FILE_POOL
16.85 +
16.86 + Array of struct list, with each list item containing the index
16.87 + of a struct razor_entry in the files section. See the
16.88 + discussion of lists below.
16.89 +
16.90 +
16.91 +Data types
16.92 +----------
16.93 +Note that the exact layout of bits involves some historical accidents.
16.94 +(Particularly the fact that the "name" field in most structs loses its
16.95 +high bits to a flags field.)
16.96 +
16.97 +struct list_head
16.98 + uint list_ptr : 24;
16.99 + uint flags : 8;
16.100 +
16.101 +struct list
16.102 + uint data : 24;
16.103 + uint flags : 8;
16.104 +
16.105 + Used to store lists of package, property, or file IDs. "struct
16.106 + list_head" stores the head of the list, which points to one or
16.107 + more "struct list"s in the appropriate "pool" section.
16.108 + ("struct list" should probably be called "struct list_item".)
16.109 +
16.110 + "list_first(&head, &pool)" returns a "struct list *" pointing
16.111 + to the first element of the list (or NULL for an empty list),
16.112 + and "list_next(list)" will return successive elements, until
16.113 + NULL is returned. Each "list->data" contains the index of a
16.114 + package, property, or file in the corresponding section of the
16.115 + set.
16.116 +
16.117 + Peeking underneath the abstraction, a list_head's "flags" is
16.118 + 0xff if the list is empty, 0x80 if it contains a single
16.119 + element, or 0x00 if it contains more than one element. In the
16.120 + single-element case, that element is actually stored in the
16.121 + list_head directly rather than being stored in a pool (and so
16.122 + list_first() just casts the list_head* to a list* and returns
16.123 + it). For multi-element lists, list_ptr is the index in the
16.124 + pool of the first element of this list; the list continues
16.125 + through successive elements of the pool until one with
16.126 + non-zero flags is reached, indicating the end of the list.
16.127 +
16.128 +struct razor_package
16.129 + uint name : 24;
16.130 + uint flags : 8;
16.131 + uint version : 32;
16.132 + struct list_head properties;
16.133 + struct list_head files;
16.134 +
16.135 + name and version are indexes into string_pool. properties is a
16.136 + list of all of the package's properties, and files is a list
16.137 + of its files. flags is currently only used during razor_set
16.138 + merging, to keep track of which set a package came from.
16.139 +
16.140 +struct razor_property
16.141 + uint name : 24;
16.142 + uint flags : 6;
16.143 + uint type : 2;
16.144 + uint relation : 32;
16.145 + uint version : 32;
16.146 + struct list_head packages;
16.147 +
16.148 + name and version are indexes into string_pool. type is an enum
16.149 + razor_property_type (eg, RAZOR_PROPERTY_REQUIRES), and
16.150 + relation is an enum razor_version_relation (eg,
16.151 + RAZOR_VERSION_GREATER_OR_EQUAL). packages is a list of the
16.152 + packages that have this property. flags is currently unused.
16.153 +
16.154 +struct razor_entry
16.155 + uint name : 24;
16.156 + uint flags : 8;
16.157 + uint start : 32;
16.158 + struct list_head packages;
16.159 +
16.160 + name is an index into string_pool, giving the basename of the
16.161 + file. start is either 0, or an index pointing to another
16.162 + razor_entry that is the first child of this entry (for a
16.163 + non-empty directory). (Entry 0 is always the root of the tree,
16.164 + so no entry could have entry 0 as a child.) flags is 0x80
16.165 + (RAZOR_ENTRY_LAST) if an entry is the last entry in its
16.166 + directory. Otherwise it is 0.
16.167 +
16.168 + Note that given a pointer to a struct_razor_entry (eg, from a
16.169 + package's "files" list), there is no way to reconstruct its
16.170 + full name without walking the entire files array up to that
16.171 + point. Because of this and other problems (fix_file_map()), it
16.172 + seems like razor_entry should be modified to include a pointer
16.173 + to its parent. (Storing full paths instead of just basenames
16.174 + would also fix this problem, but that would use much more
16.175 + memory.)
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/librazor/.gitignore Mon Jun 16 15:40:30 2008 -0400
17.3 @@ -0,0 +1,5 @@
17.4 +.deps
17.5 +.libs
17.6 +*.lo
17.7 +*.la
17.8 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/librazor/Makefile.am Mon Jun 16 15:40:30 2008 -0400
18.3 @@ -0,0 +1,34 @@
18.4 +## Process this file with automake to produce Makefile.in
18.5 +
18.6 +INCLUDES = \
18.7 + -I$(top_builddir)/src -I$(top_srcdir)/src \
18.8 + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
18.9 + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
18.10 + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
18.11 + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \
18.12 + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \
18.13 + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
18.14 + -DPACKAGE_LIB_DIR=\""$(libdir)"\"
18.15 +
18.16 +lib_LTLIBRARIES = librazor.la
18.17 +
18.18 +librazorincludedir = $(includedir)/razor
18.19 +
18.20 +librazorinclude_HEADERS = \
18.21 + razor.h
18.22 +
18.23 +librazor_la_SOURCES = \
18.24 + razor-internal.h \
18.25 + razor.h \
18.26 + razor.c \
18.27 + razor-root.c \
18.28 + types.h \
18.29 + types.c \
18.30 + util.c \
18.31 + rpm.c
18.32 +
18.33 +librazor_la_LIBADD = $(ZLIB_LIBS)
18.34 +
18.35 +clean-local :
18.36 + rm -f *~
18.37 +
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/librazor/razor-internal.h Mon Jun 16 15:40:30 2008 -0400
19.3 @@ -0,0 +1,19 @@
19.4 +#ifndef _RAZOR_INTERNAL_H_
19.5 +#define _RAZOR_INTERNAL_H_
19.6 +
19.7 +#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
19.8 +
19.9 +/* Utility functions */
19.10 +
19.11 +int razor_create_dir(const char *root, const char *path);
19.12 +int razor_write(int fd, const void *data, size_t size);
19.13 +
19.14 +
19.15 +typedef int (*razor_compare_with_data_func_t)(const void *p1,
19.16 + const void *p,
19.17 + void *data);
19.18 +uint32_t *
19.19 +razor_qsort_with_data(void *base, size_t nelem, size_t size,
19.20 + razor_compare_with_data_func_t compare, void *data);
19.21 +
19.22 +#endif /* _RAZOR_INTERNAL_H_ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/librazor/razor-root.c Mon Jun 16 15:40:30 2008 -0400
20.3 @@ -0,0 +1,168 @@
20.4 +#include <stdlib.h>
20.5 +#include <stdint.h>
20.6 +#include <stdio.h>
20.7 +#include <sys/stat.h>
20.8 +#include <dirent.h>
20.9 +#include <unistd.h>
20.10 +#include <fcntl.h>
20.11 +#include "razor.h"
20.12 +#include "razor-internal.h"
20.13 +
20.14 +static const char system_repo_filename[] = "system.repo";
20.15 +static const char next_repo_filename[] = "system-next.repo";
20.16 +static const char razor_root_path[] = "/var/lib/razor";
20.17 +
20.18 +struct razor_root {
20.19 + struct razor_set *system;
20.20 + struct razor_set *next;
20.21 + int fd;
20.22 + char path[PATH_MAX];
20.23 + char new_path[PATH_MAX];
20.24 +};
20.25 +
20.26 +int
20.27 +razor_root_create(const char *root)
20.28 +{
20.29 + struct stat buf;
20.30 + struct razor_set *set;
20.31 + char path[PATH_MAX];
20.32 +
20.33 + if (stat(root, &buf) < 0) {
20.34 + if (mkdir(root, 0777) < 0) {
20.35 + fprintf(stderr,
20.36 + "could not create install root \"%s\"\n",
20.37 + root);
20.38 + return -1;
20.39 + }
20.40 + fprintf(stderr, "created install root \"%s\"\n", root);
20.41 + } else if (!S_ISDIR(buf.st_mode)) {
20.42 + fprintf(stderr,
20.43 + "install root \"%s\" exists, but is not a directory\n",
20.44 + root);
20.45 + return -1;
20.46 + }
20.47 +
20.48 + snprintf(path, sizeof path, "%s/%s",
20.49 + razor_root_path, system_repo_filename);
20.50 + if (razor_create_dir(root, path) < 0) {
20.51 + fprintf(stderr, "could not create %s%s\n",
20.52 + root, razor_root_path);
20.53 + return -1;
20.54 + }
20.55 +
20.56 + set = razor_set_create();
20.57 + snprintf(path, sizeof path, "%s%s/%s",
20.58 + root, razor_root_path, system_repo_filename);
20.59 + if (stat(path, &buf) == 0) {
20.60 + fprintf(stderr,
20.61 + "a razor install root is already initialized\n");
20.62 + return -1;
20.63 + }
20.64 + if (razor_set_write(set, path) < 0) {
20.65 + fprintf(stderr, "could not write initial package set\n");
20.66 + return -1;
20.67 + }
20.68 + razor_set_destroy(set);
20.69 +
20.70 + return 0;
20.71 +}
20.72 +
20.73 +struct razor_root *
20.74 +razor_root_open(const char *root, int flags)
20.75 +{
20.76 + struct razor_root *image;
20.77 +
20.78 + image = malloc(sizeof *image);
20.79 + if (image == NULL)
20.80 + return NULL;
20.81 +
20.82 + /* Create the new next repo file up front to ensure exclusive
20.83 + * access. */
20.84 + snprintf(image->new_path, sizeof image->new_path,
20.85 + "%s%s/%s", root, root, next_repo_filename);
20.86 + image->fd = open(image->new_path,
20.87 + O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
20.88 + if (image->fd < 0) {
20.89 + fprintf(stderr, "failed to get lock file, "
20.90 + "maybe previous operation crashed?\n");
20.91 +
20.92 + /* FIXME: Use fcntl advisory locking on the system
20.93 + * package set file to figure out whether previous
20.94 + * operation crashed or is still in progress. */
20.95 +
20.96 + free(image);
20.97 + return NULL;
20.98 + }
20.99 +
20.100 + snprintf(image->path, sizeof image->path,
20.101 + "%s%s/%s", root, razor_root_path, system_repo_filename);
20.102 + image->system = razor_set_open(image->path);
20.103 + if (image->system == NULL) {
20.104 + unlink(image->new_path);
20.105 + close(image->fd);
20.106 + free(image);
20.107 + return NULL;
20.108 + }
20.109 +
20.110 + return image;
20.111 +}
20.112 +
20.113 +struct razor_set *
20.114 +razor_root_open_read_only(const char *root)
20.115 +{
20.116 + char path[PATH_MAX];
20.117 +
20.118 + snprintf(path, sizeof path, "%s%s/%s",
20.119 + root, razor_root_path, system_repo_filename);
20.120 +
20.121 + return razor_set_open(path);
20.122 +}
20.123 +
20.124 +struct razor_transaction *
20.125 +razor_root_create_transaction(struct razor_root *image,
20.126 + struct razor_set *upstream)
20.127 +{
20.128 + /* FIXME: This should take a number of upstream repos. */
20.129 + return razor_transaction_create(image->system, upstream);
20.130 +}
20.131 +
20.132 +int
20.133 +razor_root_close(struct razor_root *image)
20.134 +{
20.135 + unlink(image->new_path);
20.136 + close(image->fd);
20.137 + free(image);
20.138 +
20.139 + return 0;
20.140 +}
20.141 +
20.142 +void
20.143 +razor_root_update(struct razor_root *root, struct razor_set *next)
20.144 +{
20.145 + razor_set_write_to_fd(next, root->fd);
20.146 + root->next = next;
20.147 +
20.148 + /* Sync the new repo file so the new package set is on disk
20.149 + * before we start upgrading. */
20.150 + fsync(root->fd);
20.151 + printf("wrote %s\n", root->new_path);
20.152 +}
20.153 +
20.154 +int
20.155 +razor_root_commit(struct razor_root *image)
20.156 +{
20.157 + /* Make it so. */
20.158 + rename(image->new_path, image->path);
20.159 + printf("renamed %s to %s\n", image->new_path, image->path);
20.160 + close(image->fd);
20.161 + free(image);
20.162 +
20.163 + return 0;
20.164 +}
20.165 +
20.166 +void
20.167 +razor_root_diff(struct razor_root *root,
20.168 + razor_package_callback_t callback, void *data)
20.169 +{
20.170 + return razor_set_diff(root->system, root->next, callback, data);
20.171 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/librazor/razor.c Mon Jun 16 15:40:30 2008 -0400
21.3 @@ -0,0 +1,2611 @@
21.4 +/*
21.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
21.6 + * Copyright (C) 2008 Red Hat, Inc
21.7 + *
21.8 + * This program is free software; you can redistribute it and/or modify
21.9 + * it under the terms of the GNU General Public License as published by
21.10 + * the Free Software Foundation; either version 2 of the License, or
21.11 + * (at your option) any later version.
21.12 + *
21.13 + * This program is distributed in the hope that it will be useful,
21.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.16 + * GNU General Public License for more details.
21.17 + *
21.18 + * You should have received a copy of the GNU General Public License along
21.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
21.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21.21 + */
21.22 +
21.23 +#define _GNU_SOURCE
21.24 +
21.25 +#include <stdlib.h>
21.26 +#include <stddef.h>
21.27 +#include <stdint.h>
21.28 +#include <stdio.h>
21.29 +#include <string.h>
21.30 +#include <sys/types.h>
21.31 +#include <sys/stat.h>
21.32 +#include <sys/mman.h>
21.33 +#include <unistd.h>
21.34 +#include <fcntl.h>
21.35 +#include <errno.h>
21.36 +#include <ctype.h>
21.37 +#include <fnmatch.h>
21.38 +
21.39 +#include "razor.h"
21.40 +#include "razor-internal.h"
21.41 +#include "types.h"
21.42 +
21.43 +struct razor_set_section {
21.44 + uint32_t type;
21.45 + uint32_t offset;
21.46 + uint32_t size;
21.47 +};
21.48 +
21.49 +struct razor_set_header {
21.50 + uint32_t magic;
21.51 + uint32_t version;
21.52 + struct razor_set_section sections[0];
21.53 +};
21.54 +
21.55 +#define RAZOR_MAGIC 0x7a7a7a7a
21.56 +#define RAZOR_VERSION 1
21.57 +
21.58 +#define RAZOR_STRING_POOL 0
21.59 +#define RAZOR_PACKAGES 1
21.60 +#define RAZOR_PROPERTIES 2
21.61 +#define RAZOR_FILES 3
21.62 +#define RAZOR_PACKAGE_POOL 4
21.63 +#define RAZOR_PROPERTY_POOL 5
21.64 +#define RAZOR_FILE_POOL 6
21.65 +
21.66 +struct razor_package {
21.67 + uint name : 24;
21.68 + uint flags : 8;
21.69 + uint32_t version;
21.70 + uint32_t arch;
21.71 + struct list_head properties;
21.72 + struct list_head files;
21.73 +};
21.74 +
21.75 +struct razor_property {
21.76 + uint name : 24;
21.77 + uint flags : 6;
21.78 + enum razor_property_type type : 2;
21.79 + enum razor_version_relation relation : 32;
21.80 + uint32_t version;
21.81 + struct list_head packages;
21.82 +};
21.83 +
21.84 +struct razor_entry {
21.85 + uint name : 24;
21.86 + uint flags : 8;
21.87 + uint32_t start;
21.88 + struct list_head packages;
21.89 +};
21.90 +
21.91 +#define RAZOR_ENTRY_LAST 0x80
21.92 +
21.93 +struct razor_set {
21.94 + struct array string_pool;
21.95 + struct array packages;
21.96 + struct array properties;
21.97 + struct array files;
21.98 + struct array package_pool;
21.99 + struct array property_pool;
21.100 + struct array file_pool;
21.101 + struct razor_set_header *header;
21.102 +};
21.103 +
21.104 +struct import_entry {
21.105 + uint32_t package;
21.106 + char *name;
21.107 +};
21.108 +
21.109 +struct import_directory {
21.110 + uint32_t name, count;
21.111 + struct array files;
21.112 + struct array packages;
21.113 + struct import_directory *last;
21.114 +};
21.115 +
21.116 +struct razor_importer {
21.117 + struct razor_set *set;
21.118 + struct hashtable table;
21.119 + struct razor_package *package;
21.120 + struct array properties;
21.121 + struct array files;
21.122 + struct array file_requires;
21.123 +};
21.124 +
21.125 +static void *
21.126 +zalloc(size_t size)
21.127 +{
21.128 + void *p;
21.129 +
21.130 + p = malloc(size);
21.131 + memset(p, 0, size);
21.132 +
21.133 + return p;
21.134 +}
21.135 +
21.136 +struct razor_set_section razor_sections[] = {
21.137 + { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
21.138 + { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
21.139 + { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
21.140 + { RAZOR_FILES, offsetof(struct razor_set, files) },
21.141 + { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
21.142 + { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
21.143 + { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
21.144 +};
21.145 +
21.146 +struct razor_set *
21.147 +razor_set_create(void)
21.148 +{
21.149 + struct razor_set *set;
21.150 + struct razor_entry *e;
21.151 + char *empty;
21.152 +
21.153 + set = zalloc(sizeof *set);
21.154 +
21.155 + e = array_add(&set->files, sizeof *e);
21.156 + empty = array_add(&set->string_pool, 1);
21.157 + *empty = '\0';
21.158 + e->name = 0;
21.159 + e->flags = RAZOR_ENTRY_LAST;
21.160 + e->start = 0;
21.161 + list_set_empty(&e->packages);
21.162 +
21.163 + return set;
21.164 +}
21.165 +
21.166 +struct razor_set *
21.167 +razor_set_open(const char *filename)
21.168 +{
21.169 + struct razor_set *set;
21.170 + struct razor_set_section *s;
21.171 + struct stat stat;
21.172 + struct array *array;
21.173 + int fd;
21.174 +
21.175 + set = zalloc(sizeof *set);
21.176 + fd = open(filename, O_RDONLY);
21.177 + if (fstat(fd, &stat) < 0)
21.178 + return NULL;
21.179 + set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
21.180 + if (set->header == MAP_FAILED) {
21.181 + free(set);
21.182 + return NULL;
21.183 + }
21.184 +
21.185 + for (s = set->header->sections; ~s->type; s++) {
21.186 + if (s->type >= ARRAY_SIZE(razor_sections))
21.187 + continue;
21.188 + if (s->type != razor_sections[s->type].type)
21.189 + continue;
21.190 + array = (void *) set + razor_sections[s->type].offset;
21.191 + array->data = (void *) set->header + s->offset;
21.192 + array->size = s->size;
21.193 + array->alloc = s->size;
21.194 + }
21.195 + close(fd);
21.196 +
21.197 + return set;
21.198 +}
21.199 +
21.200 +void
21.201 +razor_set_destroy(struct razor_set *set)
21.202 +{
21.203 + unsigned int size;
21.204 + struct array *a;
21.205 + int i;
21.206 +
21.207 + if (set->header) {
21.208 + for (i = 0; set->header->sections[i].type; i++)
21.209 + ;
21.210 + size = set->header->sections[i].type;
21.211 + munmap(set->header, size);
21.212 + } else {
21.213 + for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
21.214 + a = (void *) set + razor_sections[i].offset;
21.215 + free(a->data);
21.216 + }
21.217 + }
21.218 +
21.219 + free(set);
21.220 +}
21.221 +
21.222 +int
21.223 +razor_set_write_to_fd(struct razor_set *set, int fd)
21.224 +{
21.225 + char data[4096];
21.226 + struct razor_set_header *header = (struct razor_set_header *) data;
21.227 + struct array *a;
21.228 + uint32_t offset;
21.229 + int i;
21.230 +
21.231 + memset(data, 0, sizeof data);
21.232 + header->magic = RAZOR_MAGIC;
21.233 + header->version = RAZOR_VERSION;
21.234 + offset = sizeof data;
21.235 +
21.236 + for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
21.237 + if (razor_sections[i].type != i)
21.238 + continue;
21.239 + a = (void *) set + razor_sections[i].offset;
21.240 + header->sections[i].type = i;
21.241 + header->sections[i].offset = offset;
21.242 + header->sections[i].size = a->size;
21.243 + offset += ALIGN(a->size, 4096);
21.244 + }
21.245 +
21.246 + header->sections[i].type = ~0;
21.247 + header->sections[i].offset = 0;
21.248 + header->sections[i].size = 0;
21.249 +
21.250 + razor_write(fd, data, sizeof data);
21.251 + memset(data, 0, sizeof data);
21.252 + for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
21.253 + if (razor_sections[i].type != i)
21.254 + continue;
21.255 + a = (void *) set + razor_sections[i].offset;
21.256 + razor_write(fd, a->data, a->size);
21.257 + razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
21.258 + }
21.259 +
21.260 + return 0;
21.261 +}
21.262 +
21.263 +int
21.264 +razor_set_write(struct razor_set *set, const char *filename)
21.265 +{
21.266 + int fd, status;
21.267 +
21.268 + fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
21.269 + if (fd < 0)
21.270 + return -1;
21.271 +
21.272 + status = razor_set_write_to_fd(set, fd);
21.273 + if (status) {
21.274 + close(fd);
21.275 + return status;
21.276 + }
21.277 +
21.278 + return close(fd);
21.279 +}
21.280 +
21.281 +void
21.282 +razor_build_evr(char *evr_buf, int size, const char *epoch,
21.283 + const char *version, const char *release)
21.284 +{
21.285 + int len;
21.286 +
21.287 + if (!version || !*version) {
21.288 + *evr_buf = '\0';
21.289 + return;
21.290 + }
21.291 +
21.292 + if (epoch && *epoch && strcmp(epoch, "0") != 0) {
21.293 + len = snprintf(evr_buf, size, "%s:", epoch);
21.294 + evr_buf += len;
21.295 + size -= len;
21.296 + }
21.297 + len = snprintf(evr_buf, size, "%s", version);
21.298 + evr_buf += len;
21.299 + size -= len;
21.300 + if (release && *release)
21.301 + snprintf(evr_buf, size, "-%s", release);
21.302 +}
21.303 +
21.304 +void
21.305 +razor_importer_begin_package(struct razor_importer *importer,
21.306 + const char *name,
21.307 + const char *version,
21.308 + const char *arch)
21.309 +{
21.310 + struct razor_package *p;
21.311 +
21.312 + p = array_add(&importer->set->packages, sizeof *p);
21.313 + p->name = hashtable_tokenize(&importer->table, name);
21.314 + p->flags = 0;
21.315 + p->version = hashtable_tokenize(&importer->table, version);
21.316 + p->arch = hashtable_tokenize(&importer->table, arch);
21.317 +
21.318 + importer->package = p;
21.319 + array_init(&importer->properties);
21.320 +}
21.321 +
21.322 +void
21.323 +razor_importer_finish_package(struct razor_importer *importer)
21.324 +{
21.325 + list_set_array(&importer->package->properties,
21.326 + &importer->set->property_pool,
21.327 + &importer->properties,
21.328 + 1);
21.329 +
21.330 + array_release(&importer->properties);
21.331 +}
21.332 +
21.333 +void
21.334 +razor_importer_add_property(struct razor_importer *importer,
21.335 + const char *name,
21.336 + enum razor_version_relation relation,
21.337 + const char *version,
21.338 + enum razor_property_type type)
21.339 +{
21.340 + struct razor_property *p;
21.341 + uint32_t *r;
21.342 +
21.343 + p = array_add(&importer->set->properties, sizeof *p);
21.344 + p->name = hashtable_tokenize(&importer->table, name);
21.345 + p->flags = 0;
21.346 + p->type = type;
21.347 + p->relation = relation;
21.348 + p->version = hashtable_tokenize(&importer->table, version);
21.349 + list_set_ptr(&p->packages, importer->package -
21.350 + (struct razor_package *) importer->set->packages.data);
21.351 +
21.352 + r = array_add(&importer->properties, sizeof *r);
21.353 + *r = p - (struct razor_property *) importer->set->properties.data;
21.354 +
21.355 + if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
21.356 + r = array_add(&importer->file_requires, sizeof *r);
21.357 + *r = p->name;
21.358 + }
21.359 +}
21.360 +
21.361 +void
21.362 +razor_importer_add_file(struct razor_importer *importer, const char *name)
21.363 +{
21.364 + struct import_entry *e;
21.365 +
21.366 + e = array_add(&importer->files, sizeof *e);
21.367 +
21.368 + e->package = importer->package -
21.369 + (struct razor_package *) importer->set->packages.data;
21.370 + e->name = strdup(name);
21.371 +}
21.372 +
21.373 +struct razor_importer *
21.374 +razor_importer_new(void)
21.375 +{
21.376 + struct razor_importer *importer;
21.377 +
21.378 + importer = zalloc(sizeof *importer);
21.379 + importer->set = razor_set_create();
21.380 + hashtable_init(&importer->table, &importer->set->string_pool);
21.381 +
21.382 + return importer;
21.383 +}
21.384 +
21.385 +/* Destroy an importer without creating the set. */
21.386 +void
21.387 +razor_importer_destroy(struct razor_importer *importer)
21.388 +{
21.389 + /* FIXME: write this */
21.390 +}
21.391 +
21.392 +static int
21.393 +versioncmp(const char *s1, const char *s2)
21.394 +{
21.395 + const char *p1, *p2;
21.396 + long n1, n2;
21.397 + int res;
21.398 +
21.399 + n1 = strtol(s1, (char **) &p1, 10);
21.400 + n2 = strtol(s2, (char **) &p2, 10);
21.401 +
21.402 + /* Epoch; if one but not the other has an epoch set, default
21.403 + * the epoch-less version to 0. */
21.404 + res = (*p1 == ':') - (*p2 == ':');
21.405 + if (res < 0) {
21.406 + n1 = 0;
21.407 + p1 = s1;
21.408 + p2++;
21.409 + } else if (res > 0) {
21.410 + p1++;
21.411 + n2 = 0;
21.412 + p2 = s2;
21.413 + }
21.414 +
21.415 + if (n1 != n2)
21.416 + return n1 - n2;
21.417 + while (*p1 && *p2) {
21.418 + if (*p1 != *p2)
21.419 + return *p1 - *p2;
21.420 + p1++;
21.421 + p2++;
21.422 + if (isdigit(*p1) && isdigit(*p2))
21.423 + return versioncmp(p1, p2);
21.424 + }
21.425 +
21.426 + return *p1 - *p2;
21.427 +}
21.428 +
21.429 +static int
21.430 +compare_packages(const void *p1, const void *p2, void *data)
21.431 +{
21.432 + const struct razor_package *pkg1 = p1, *pkg2 = p2;
21.433 + struct razor_set *set = data;
21.434 + char *pool = set->string_pool.data;
21.435 +
21.436 + /* FIXME: what if the flags are different? */
21.437 + if (pkg1->name == pkg2->name)
21.438 + return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
21.439 + else
21.440 + return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
21.441 +}
21.442 +
21.443 +static int
21.444 +compare_properties(const void *p1, const void *p2, void *data)
21.445 +{
21.446 + const struct razor_property *prop1 = p1, *prop2 = p2;
21.447 + struct razor_set *set = data;
21.448 + char *pool = set->string_pool.data;
21.449 +
21.450 + if (prop1->name != prop2->name)
21.451 + return strcmp(&pool[prop1->name], &pool[prop2->name]);
21.452 + else if (prop1->type != prop2->type)
21.453 + return prop1->type - prop2->type;
21.454 + else if (prop1->relation != prop2->relation)
21.455 + return prop1->relation - prop2->relation;
21.456 + else
21.457 + return versioncmp(&pool[prop1->version], &pool[prop2->version]);
21.458 +}
21.459 +
21.460 +static uint32_t *
21.461 +uniqueify_properties(struct razor_set *set)
21.462 +{
21.463 + struct razor_property *rp, *up, *rp_end;
21.464 + struct array *pkgs, *p;
21.465 + struct list_head *r;
21.466 + uint32_t *map, *rmap;
21.467 + int i, count, unique;
21.468 +
21.469 + count = set->properties.size / sizeof(struct razor_property);
21.470 + map = razor_qsort_with_data(set->properties.data,
21.471 + count,
21.472 + sizeof(struct razor_property),
21.473 + compare_properties,
21.474 + set);
21.475 +
21.476 + rp_end = set->properties.data + set->properties.size;
21.477 + rmap = malloc(count * sizeof *map);
21.478 + pkgs = zalloc(count * sizeof *pkgs);
21.479 + for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
21.480 + if (rp->name != up->name || rp->type != up->type ||
21.481 + rp->relation != up->relation || rp->version != up->version) {
21.482 + up++;
21.483 + up->name = rp->name;
21.484 + up->flags = 0;
21.485 + up->type = rp->type;
21.486 + up->relation = rp->relation;
21.487 + up->version = rp->version;
21.488 + }
21.489 +
21.490 + unique = up - (struct razor_property *) set->properties.data;
21.491 + rmap[map[i]] = unique;
21.492 + r = array_add(&pkgs[unique], sizeof *r);
21.493 + *r = rp->packages;
21.494 + }
21.495 + free(map);
21.496 +
21.497 + if (up != rp)
21.498 + up++;
21.499 + set->properties.size = (void *) up - set->properties.data;
21.500 + rp_end = up;
21.501 + for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
21.502 + list_set_array(&rp->packages, &set->package_pool, p, 0);
21.503 + array_release(p);
21.504 + }
21.505 +
21.506 + free(pkgs);
21.507 +
21.508 + return rmap;
21.509 +}
21.510 +
21.511 +static int
21.512 +compare_filenames(const void *p1, const void *p2, void *data)
21.513 +{
21.514 + const struct import_entry *e1 = p1;
21.515 + const struct import_entry *e2 = p2;
21.516 + const char *n1 = e1->name;
21.517 + const char *n2 = e2->name;
21.518 +
21.519 + /* Need to make sure that the contents of a directory
21.520 + * are sorted immediately after it. So "foo/bar" has to
21.521 + * sort before "foo.conf"
21.522 + *
21.523 + * FIXME: this is about 60% slower than strcmp
21.524 + */
21.525 + while (*n1 && *n2) {
21.526 + if (*n1 < *n2)
21.527 + return *n2 == '/' ? 1 : -1;
21.528 + else if (*n1 > *n2)
21.529 + return *n1 == '/' ? -1 : 1;
21.530 + n1++;
21.531 + n2++;
21.532 + }
21.533 + if (*n1)
21.534 + return 1;
21.535 + else if (*n2)
21.536 + return -1;
21.537 + else
21.538 + return 0;
21.539 +}
21.540 +
21.541 +static void
21.542 +count_entries(struct import_directory *d)
21.543 +{
21.544 + struct import_directory *p, *end;
21.545 +
21.546 + p = d->files.data;
21.547 + end = d->files.data + d->files.size;
21.548 + d->count = 0;
21.549 + while (p < end) {
21.550 + count_entries(p);
21.551 + d->count += p->count + 1;
21.552 + p++;
21.553 + }
21.554 +}
21.555 +
21.556 +static void
21.557 +serialize_files(struct razor_set *set,
21.558 + struct import_directory *d, struct array *array)
21.559 +{
21.560 + struct import_directory *p, *end;
21.561 + struct razor_entry *e = NULL;
21.562 + uint32_t s;
21.563 +
21.564 + p = d->files.data;
21.565 + end = d->files.data + d->files.size;
21.566 + s = array->size / sizeof *e + d->files.size / sizeof *p;
21.567 + while (p < end) {
21.568 + e = array_add(array, sizeof *e);
21.569 + e->name = p->name;
21.570 + e->flags = 0;
21.571 + e->start = p->count > 0 ? s : 0;
21.572 + s += p->count;
21.573 +
21.574 + list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
21.575 + array_release(&p->packages);
21.576 + p++;
21.577 + }
21.578 + if (e != NULL)
21.579 + e->flags |= RAZOR_ENTRY_LAST;
21.580 +
21.581 + p = d->files.data;
21.582 + end = d->files.data + d->files.size;
21.583 + while (p < end) {
21.584 + serialize_files(set, p, array);
21.585 + p++;
21.586 + }
21.587 +}
21.588 +
21.589 +static void
21.590 +remap_property_package_links(struct array *properties, uint32_t *rmap)
21.591 +{
21.592 + struct razor_property *p, *end;
21.593 +
21.594 + end = properties->data + properties->size;
21.595 + for (p = properties->data; p < end; p++)
21.596 + list_remap_head(&p->packages, rmap);
21.597 +}
21.598 +
21.599 +static void
21.600 +build_file_tree(struct razor_importer *importer)
21.601 +{
21.602 + int count, i, length;
21.603 + struct import_entry *filenames;
21.604 + char *f, *end;
21.605 + uint32_t name, *r;
21.606 + char dirname[256];
21.607 + struct import_directory *d, root;
21.608 + struct razor_entry *e;
21.609 +
21.610 + count = importer->files.size / sizeof (struct import_entry);
21.611 + razor_qsort_with_data(importer->files.data,
21.612 + count,
21.613 + sizeof (struct import_entry),
21.614 + compare_filenames,
21.615 + NULL);
21.616 +
21.617 + root.name = hashtable_tokenize(&importer->table, "");
21.618 + array_init(&root.files);
21.619 + array_init(&root.packages);
21.620 + root.last = NULL;
21.621 +
21.622 + filenames = importer->files.data;
21.623 + for (i = 0; i < count; i++) {
21.624 + f = filenames[i].name;
21.625 + if (*f != '/')
21.626 + continue;
21.627 + f++;
21.628 +
21.629 + d = &root;
21.630 + while (*f) {
21.631 + end = strchr(f, '/');
21.632 + if (end == NULL)
21.633 + end = f + strlen(f);
21.634 + length = end - f;
21.635 + memcpy(dirname, f, length);
21.636 + dirname[length] ='\0';
21.637 + name = hashtable_tokenize(&importer->table, dirname);
21.638 + if (d->last == NULL || d->last->name != name) {
21.639 + d->last = array_add(&d->files, sizeof *d);
21.640 + d->last->name = name;
21.641 + d->last->last = NULL;
21.642 + array_init(&d->last->files);
21.643 + array_init(&d->last->packages);
21.644 + }
21.645 + d = d->last;
21.646 + f = end + 1;
21.647 + if (*end == '\0')
21.648 + break;
21.649 + }
21.650 +
21.651 + r = array_add(&d->packages, sizeof *r);
21.652 + *r = filenames[i].package;
21.653 + free(filenames[i].name);
21.654 + }
21.655 +
21.656 + count_entries(&root);
21.657 + e = importer->set->files.data;
21.658 + e->name = root.name;
21.659 + e->flags = RAZOR_ENTRY_LAST;
21.660 + e->start = importer->files.size ? 1 : 0;
21.661 + list_set_empty(&e->packages);
21.662 +
21.663 + serialize_files(importer->set, &root, &importer->set->files);
21.664 +
21.665 + array_release(&importer->files);
21.666 +}
21.667 +
21.668 +static struct razor_entry *
21.669 +find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
21.670 +
21.671 +static void
21.672 +list_to_array(struct list *list, struct array *array)
21.673 +{
21.674 + uint32_t *item;
21.675 +
21.676 + while (list) {
21.677 + item = array_add(array, sizeof *item);
21.678 + *item = list->data;
21.679 + list = list_next(list);
21.680 + }
21.681 +}
21.682 +
21.683 +static int
21.684 +compare_file_requires(const void *p1, const void *p2, void *data)
21.685 +{
21.686 + uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
21.687 + const char *pool = data;
21.688 +
21.689 + return strcmp(&pool[*f1], &pool[*f2]);
21.690 +}
21.691 +
21.692 +static void
21.693 +find_file_provides(struct razor_importer *importer)
21.694 +{
21.695 + struct razor_property *prop;
21.696 + struct razor_entry *top, *entry;
21.697 + struct razor_package *packages;
21.698 + struct array pkgprops;
21.699 + struct list *pkg;
21.700 + uint32_t *req, *req_start, *req_end;
21.701 + uint32_t *map, *newprop;
21.702 + char *pool;
21.703 +
21.704 + pool = importer->set->string_pool.data;
21.705 + packages = importer->set->packages.data;
21.706 + top = importer->set->files.data;
21.707 +
21.708 + req = req_start = importer->file_requires.data;
21.709 + req_end = importer->file_requires.data + importer->file_requires.size;
21.710 + map = razor_qsort_with_data(req, req_end - req, sizeof *req,
21.711 + compare_file_requires, pool);
21.712 + free(map);
21.713 +
21.714 + for (req = req_start; req < req_end; req++) {
21.715 + if (req > req_start && req[0] == req[-1])
21.716 + continue;
21.717 + entry = find_entry(importer->set, top, &pool[*req]);
21.718 + if (!entry)
21.719 + continue;
21.720 +
21.721 + for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
21.722 + prop = array_add(&importer->set->properties, sizeof *prop);
21.723 + prop->name = *req;
21.724 + prop->type = RAZOR_PROPERTY_PROVIDES;
21.725 + prop->relation = RAZOR_VERSION_EQUAL;
21.726 + prop->version = hashtable_tokenize(&importer->table, "");
21.727 + list_set_ptr(&prop->packages, pkg->data);
21.728 +
21.729 + /* Update property list of pkg */
21.730 + array_init(&pkgprops);
21.731 + list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
21.732 + newprop = array_add(&pkgprops, sizeof *newprop);
21.733 + *newprop = prop - (struct razor_property *)importer->set->properties.data;
21.734 + list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
21.735 + array_release(&pkgprops);
21.736 + }
21.737 + }
21.738 +
21.739 + array_release(&importer->file_requires);
21.740 +}
21.741 +
21.742 +static void
21.743 +build_package_file_lists(struct razor_set *set, uint32_t *rmap)
21.744 +{
21.745 + struct razor_package *p, *packages;
21.746 + struct array *pkgs;
21.747 + struct razor_entry *e, *end;
21.748 + struct list *r;
21.749 + uint32_t *q;
21.750 + int i, count;
21.751 +
21.752 + count = set->packages.size / sizeof *p;
21.753 + pkgs = zalloc(count * sizeof *pkgs);
21.754 +
21.755 + end = set->files.data + set->files.size;
21.756 + for (e = set->files.data; e < end; e++) {
21.757 + list_remap_head(&e->packages, rmap);
21.758 + r = list_first(&e->packages, &set->package_pool);
21.759 + while (r) {
21.760 + q = array_add(&pkgs[r->data], sizeof *q);
21.761 + *q = e - (struct razor_entry *) set->files.data;
21.762 + r = list_next(r);
21.763 + }
21.764 + }
21.765 +
21.766 + packages = set->packages.data;
21.767 + for (i = 0; i < count; i++) {
21.768 + list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
21.769 + array_release(&pkgs[i]);
21.770 + }
21.771 + free(pkgs);
21.772 +}
21.773 +
21.774 +struct razor_set *
21.775 +razor_importer_finish(struct razor_importer *importer)
21.776 +{
21.777 + struct razor_set *set;
21.778 + uint32_t *map, *rmap;
21.779 + int i, count;
21.780 +
21.781 + build_file_tree(importer);
21.782 + find_file_provides(importer);
21.783 +
21.784 + map = uniqueify_properties(importer->set);
21.785 + list_remap_pool(&importer->set->property_pool, map);
21.786 + free(map);
21.787 +
21.788 + count = importer->set->packages.size / sizeof(struct razor_package);
21.789 + map = razor_qsort_with_data(importer->set->packages.data,
21.790 + count,
21.791 + sizeof(struct razor_package),
21.792 + compare_packages,
21.793 + importer->set);
21.794 +
21.795 + rmap = malloc(count * sizeof *rmap);
21.796 + for (i = 0; i < count; i++)
21.797 + rmap[map[i]] = i;
21.798 + free(map);
21.799 +
21.800 + list_remap_pool(&importer->set->package_pool, rmap);
21.801 + build_package_file_lists(importer->set, rmap);
21.802 + remap_property_package_links(&importer->set->properties, rmap);
21.803 + free(rmap);
21.804 +
21.805 + set = importer->set;
21.806 + hashtable_release(&importer->table);
21.807 + free(importer);
21.808 +
21.809 + return set;
21.810 +}
21.811 +
21.812 +struct razor_package_iterator {
21.813 + struct razor_set *set;
21.814 + struct razor_package *package, *end;
21.815 + struct list *index;
21.816 + int free_index;
21.817 +};
21.818 +
21.819 +static struct razor_package_iterator *
21.820 +razor_package_iterator_create_with_index(struct razor_set *set,
21.821 + struct list *index)
21.822 +{
21.823 + struct razor_package_iterator *pi;
21.824 +
21.825 + pi = zalloc(sizeof *pi);
21.826 + pi->set = set;
21.827 + pi->index = index;
21.828 +
21.829 + return pi;
21.830 +}
21.831 +
21.832 +struct razor_package_iterator *
21.833 +razor_package_iterator_create(struct razor_set *set)
21.834 +{
21.835 + struct razor_package_iterator *pi;
21.836 +
21.837 + pi = zalloc(sizeof *pi);
21.838 + pi->set = set;
21.839 + pi->end = set->packages.data + set->packages.size;
21.840 + pi->package = set->packages.data;
21.841 +
21.842 + return pi;
21.843 +}
21.844 +
21.845 +static void
21.846 +razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
21.847 + struct razor_set *set,
21.848 + struct razor_property *property)
21.849 +{
21.850 + memset(pi, 0, sizeof *pi);
21.851 + pi->set = set;
21.852 + pi->index = list_first(&property->packages, &set->package_pool);
21.853 +}
21.854 +
21.855 +struct razor_package_iterator *
21.856 +razor_package_iterator_create_for_property(struct razor_set *set,
21.857 + struct razor_property *property)
21.858 +{
21.859 + struct list *index;
21.860 +
21.861 + index = list_first(&property->packages, &set->package_pool);
21.862 + return razor_package_iterator_create_with_index(set, index);
21.863 +}
21.864 +
21.865 +int
21.866 +razor_package_iterator_next(struct razor_package_iterator *pi,
21.867 + struct razor_package **package,
21.868 + const char **name,
21.869 + const char **version,
21.870 + const char **arch)
21.871 +{
21.872 + char *pool;
21.873 + int valid;
21.874 + struct razor_package *p, *packages;
21.875 +
21.876 + if (pi->package) {
21.877 + p = pi->package++;
21.878 + valid = p < pi->end;
21.879 + } else if (pi->index) {
21.880 + packages = pi->set->packages.data;
21.881 + p = &packages[pi->index->data];
21.882 + pi->index = list_next(pi->index);
21.883 + valid = 1;
21.884 + } else
21.885 + valid = 0;
21.886 +
21.887 + if (valid) {
21.888 + pool = pi->set->string_pool.data;
21.889 + *package = p;
21.890 + *name = &pool[p->name];
21.891 + *version = &pool[p->version];
21.892 + *arch = &pool[p->arch];
21.893 + } else {
21.894 + *package = NULL;
21.895 + }
21.896 +
21.897 + return valid;
21.898 +}
21.899 +
21.900 +void
21.901 +razor_package_iterator_destroy(struct razor_package_iterator *pi)
21.902 +{
21.903 + if (pi->free_index)
21.904 + free(pi->index);
21.905 +
21.906 + free(pi);
21.907 +}
21.908 +
21.909 +struct razor_package *
21.910 +razor_set_get_package(struct razor_set *set, const char *package)
21.911 +{
21.912 + struct razor_package_iterator *pi;
21.913 + struct razor_package *p;
21.914 + const char *name, *version, *arch;
21.915 +
21.916 + pi = razor_package_iterator_create(set);
21.917 + while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
21.918 + if (strcmp(package, name) == 0)
21.919 + break;
21.920 + }
21.921 + razor_package_iterator_destroy(pi);
21.922 +
21.923 + return p;
21.924 +}
21.925 +
21.926 +struct razor_property_iterator {
21.927 + struct razor_set *set;
21.928 + struct razor_property *property, *end;
21.929 + struct list *index;
21.930 +};
21.931 +
21.932 +struct razor_property_iterator *
21.933 +razor_property_iterator_create(struct razor_set *set,
21.934 + struct razor_package *package)
21.935 +{
21.936 + struct razor_property_iterator *pi;
21.937 +
21.938 + pi = zalloc(sizeof *pi);
21.939 + pi->set = set;
21.940 +
21.941 + if (package) {
21.942 + pi->index = list_first(&package->properties,
21.943 + &set->property_pool);
21.944 + } else {
21.945 + pi->property = set->properties.data;
21.946 + pi->end = set->properties.data + set->properties.size;
21.947 + }
21.948 +
21.949 + return pi;
21.950 +}
21.951 +
21.952 +int
21.953 +razor_property_iterator_next(struct razor_property_iterator *pi,
21.954 + struct razor_property **property,
21.955 + const char **name,
21.956 + enum razor_version_relation *relation,
21.957 + const char **version,
21.958 + enum razor_property_type *type)
21.959 +{
21.960 + char *pool;
21.961 + int valid;
21.962 + struct razor_property *p, *properties;
21.963 +
21.964 + if (pi->property) {
21.965 + p = pi->property++;
21.966 + valid = p < pi->end;
21.967 + } else if (pi->index) {
21.968 + properties = pi->set->properties.data;
21.969 + p = &properties[pi->index->data];
21.970 + pi->index = list_next(pi->index);
21.971 + valid = 1;
21.972 + } else
21.973 + valid = 0;
21.974 +
21.975 + if (valid) {
21.976 + pool = pi->set->string_pool.data;
21.977 + *property = p;
21.978 + *name = &pool[p->name];
21.979 + *relation = p->relation;
21.980 + *version = &pool[p->version];
21.981 + *type = p->type;
21.982 + } else {
21.983 + *property = NULL;
21.984 + }
21.985 +
21.986 + return valid;
21.987 +}
21.988 +
21.989 +void
21.990 +razor_property_iterator_destroy(struct razor_property_iterator *pi)
21.991 +{
21.992 + free(pi);
21.993 +}
21.994 +
21.995 +static struct razor_entry *
21.996 +find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
21.997 +{
21.998 + struct razor_entry *e;
21.999 + const char *n, *pool = set->string_pool.data;
21.1000 + int len;
21.1001 +
21.1002 + e = (struct razor_entry *) set->files.data + dir->start;
21.1003 + do {
21.1004 + n = pool + e->name;
21.1005 + if (strcmp(pattern + 1, n) == 0)
21.1006 + return e;
21.1007 + len = strlen(n);
21.1008 + if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
21.1009 + pattern[len + 1] == '/') {
21.1010 + return find_entry(set, e, pattern + len + 1);
21.1011 + }
21.1012 + } while (!((e++)->flags & RAZOR_ENTRY_LAST));
21.1013 +
21.1014 + return NULL;
21.1015 +}
21.1016 +
21.1017 +static void
21.1018 +list_dir(struct razor_set *set, struct razor_entry *dir,
21.1019 + char *prefix, const char *pattern)
21.1020 +{
21.1021 + struct razor_entry *e;
21.1022 + const char *n, *pool = set->string_pool.data;
21.1023 +
21.1024 + e = (struct razor_entry *) set->files.data + dir->start;
21.1025 + do {
21.1026 + n = pool + e->name;
21.1027 + if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
21.1028 + continue;
21.1029 + printf("%s/%s\n", prefix, n);
21.1030 + if (e->start) {
21.1031 + char *sub = prefix + strlen (prefix);
21.1032 + *sub = '/';
21.1033 + strcpy (sub + 1, n);
21.1034 + list_dir(set, e, prefix, pattern);
21.1035 + *sub = '\0';
21.1036 + }
21.1037 + } while (!((e++)->flags & RAZOR_ENTRY_LAST));
21.1038 +}
21.1039 +
21.1040 +void
21.1041 +razor_set_list_files(struct razor_set *set, const char *pattern)
21.1042 +{
21.1043 + struct razor_entry *e;
21.1044 + char buffer[512], *p, *base;
21.1045 +
21.1046 + if (pattern == NULL || !strcmp (pattern, "/")) {
21.1047 + buffer[0] = '\0';
21.1048 + list_dir(set, set->files.data, buffer, NULL);
21.1049 + return;
21.1050 + }
21.1051 +
21.1052 + strcpy(buffer, pattern);
21.1053 + e = find_entry(set, set->files.data, buffer);
21.1054 + if (e && e->start > 0) {
21.1055 + base = NULL;
21.1056 + } else {
21.1057 + p = strrchr(buffer, '/');
21.1058 + if (p) {
21.1059 + *p = '\0';
21.1060 + base = p + 1;
21.1061 + } else {
21.1062 + base = NULL;
21.1063 + }
21.1064 + }
21.1065 + e = find_entry(set, set->files.data, buffer);
21.1066 + if (e->start != 0)
21.1067 + list_dir(set, e, buffer, base);
21.1068 +}
21.1069 +
21.1070 +struct razor_package_iterator *
21.1071 +razor_package_iterator_create_for_file(struct razor_set *set,
21.1072 + const char *filename)
21.1073 +{
21.1074 + struct razor_entry *entry;
21.1075 + struct list *index;
21.1076 +
21.1077 + entry = find_entry(set, set->files.data, filename);
21.1078 + if (entry == NULL)
21.1079 + return NULL;
21.1080 +
21.1081 + index = list_first(&entry->packages, &set->package_pool);
21.1082 + return razor_package_iterator_create_with_index(set, index);
21.1083 +}
21.1084 +
21.1085 +static struct list *
21.1086 +list_package_files(struct razor_set *set, struct list *r,
21.1087 + struct razor_entry *dir, uint32_t end,
21.1088 + char *prefix)
21.1089 +{
21.1090 + struct razor_entry *e, *f, *entries;
21.1091 + uint32_t next, file;
21.1092 + char *pool;
21.1093 + int len;
21.1094 +
21.1095 + entries = (struct razor_entry *) set->files.data;
21.1096 + pool = set->string_pool.data;
21.1097 +
21.1098 + e = entries + dir->start;
21.1099 + do {
21.1100 + if (entries + r->data == e) {
21.1101 + printf("%s/%s\n", prefix, pool + e->name);
21.1102 + r = list_next(r);
21.1103 + if (!r)
21.1104 + return NULL;
21.1105 + if (r->data >= end)
21.1106 + return r;
21.1107 + }
21.1108 + } while (!((e++)->flags & RAZOR_ENTRY_LAST));
21.1109 +
21.1110 + e = entries + dir->start;
21.1111 + do {
21.1112 + if (e->start == 0)
21.1113 + continue;
21.1114 +
21.1115 + if (e->flags & RAZOR_ENTRY_LAST)
21.1116 + next = end;
21.1117 + else {
21.1118 + f = e + 1;
21.1119 + while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
21.1120 + f++;
21.1121 + if (f->start == 0)
21.1122 + next = end;
21.1123 + else
21.1124 + next = f->start;
21.1125 + }
21.1126 +
21.1127 + file = r->data;
21.1128 + if (e->start <= file && file < next) {
21.1129 + len = strlen(prefix);
21.1130 + prefix[len] = '/';
21.1131 + strcpy(prefix + len + 1, pool + e->name);
21.1132 + r = list_package_files(set, r, e, next, prefix);
21.1133 + prefix[len] = '\0';
21.1134 + }
21.1135 + } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
21.1136 +
21.1137 + return r;
21.1138 +}
21.1139 +
21.1140 +void
21.1141 +razor_set_list_package_files(struct razor_set *set, const char *name)
21.1142 +{
21.1143 + struct razor_package *package;
21.1144 + struct list *r;
21.1145 + uint32_t end;
21.1146 + char buffer[512];
21.1147 +
21.1148 + package = razor_set_get_package(set, name);
21.1149 +
21.1150 + r = list_first(&package->files, &set->file_pool);
21.1151 + end = set->files.size / sizeof (struct razor_entry);
21.1152 + buffer[0] = '\0';
21.1153 + list_package_files(set, r, set->files.data, end, buffer);
21.1154 +}
21.1155 +
21.1156 +#define UPSTREAM_SOURCE 0x80
21.1157 +
21.1158 +struct source {
21.1159 + struct razor_set *set;
21.1160 + uint32_t *property_map;
21.1161 + uint32_t *file_map;
21.1162 +};
21.1163 +
21.1164 +struct razor_merger {
21.1165 + struct razor_set *set;
21.1166 + struct hashtable table;
21.1167 + struct source source1;
21.1168 + struct source source2;
21.1169 +};
21.1170 +
21.1171 +static struct razor_merger *
21.1172 +razor_merger_create(struct razor_set *set1, struct razor_set *set2)
21.1173 +{
21.1174 + struct razor_merger *merger;
21.1175 + int count;
21.1176 + size_t size;
21.1177 +
21.1178 + merger = zalloc(sizeof *merger);
21.1179 + merger->set = razor_set_create();
21.1180 + hashtable_init(&merger->table, &merger->set->string_pool);
21.1181 +
21.1182 + merger->source1.set = set1;
21.1183 + count = set1->properties.size / sizeof (struct razor_property);
21.1184 + size = count * sizeof merger->source1.property_map[0];
21.1185 + merger->source1.property_map = zalloc(size);
21.1186 + count = set1->files.size / sizeof (struct razor_entry);
21.1187 + size = count * sizeof merger->source1.file_map[0];
21.1188 + merger->source1.file_map = zalloc(size);
21.1189 +
21.1190 + merger->source2.set = set2;
21.1191 + count = set2->properties.size / sizeof (struct razor_property);
21.1192 + size = count * sizeof merger->source2.property_map[0];
21.1193 + merger->source2.property_map = zalloc(size);
21.1194 + count = set2->files.size / sizeof (struct razor_entry);
21.1195 + size = count * sizeof merger->source2.file_map[0];
21.1196 + merger->source2.file_map = zalloc(size);
21.1197 +
21.1198 + return merger;
21.1199 +}
21.1200 +
21.1201 +static void
21.1202 +razor_merger_add_package(struct razor_merger *merger,
21.1203 + struct razor_package *package)
21.1204 +{
21.1205 + char *pool;
21.1206 + struct list *r;
21.1207 + struct razor_package *p;
21.1208 + struct razor_set *set1;
21.1209 + struct source *source;
21.1210 + uint32_t flags;
21.1211 +
21.1212 + set1 = merger->source1.set;
21.1213 + if (set1->packages.data <= (void *) package &&
21.1214 + (void *) package < set1->packages.data + set1->packages.size) {
21.1215 + source = &merger->source1;
21.1216 + flags = 0;
21.1217 + } else {
21.1218 + source = &merger->source2;
21.1219 + flags = UPSTREAM_SOURCE;
21.1220 + }
21.1221 +
21.1222 + pool = source->set->string_pool.data;
21.1223 + p = array_add(&merger->set->packages, sizeof *p);
21.1224 + p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
21.1225 + p->flags = flags;
21.1226 + p->version = hashtable_tokenize(&merger->table,
21.1227 + &pool[package->version]);
21.1228 + p->arch = hashtable_tokenize(&merger->table,
21.1229 + &pool[package->arch]);
21.1230 +
21.1231 + p->properties = package->properties;
21.1232 + r = list_first(&package->properties, &source->set->property_pool);
21.1233 + while (r) {
21.1234 + source->property_map[r->data] = 1;
21.1235 + r = list_next(r);
21.1236 + }
21.1237 +
21.1238 + p->files = package->files;
21.1239 + r = list_first(&package->files, &source->set->file_pool);
21.1240 + while (r) {
21.1241 + source->file_map[r->data] = 1;
21.1242 + r = list_next(r);
21.1243 + }
21.1244 +}
21.1245 +
21.1246 +static uint32_t
21.1247 +add_property(struct razor_merger *merger,
21.1248 + const char *name, enum razor_version_relation relation,
21.1249 + const char *version, int type)
21.1250 +{
21.1251 + struct razor_property *p;
21.1252 +
21.1253 + p = array_add(&merger->set->properties, sizeof *p);
21.1254 + p->name = hashtable_tokenize(&merger->table, name);
21.1255 + p->flags = 0;
21.1256 + p->type = type;
21.1257 + p->relation = relation;
21.1258 + p->version = hashtable_tokenize(&merger->table, version);
21.1259 +
21.1260 + return p - (struct razor_property *) merger->set->properties.data;
21.1261 +}
21.1262 +
21.1263 +static void
21.1264 +merge_properties(struct razor_merger *merger)
21.1265 +{
21.1266 + struct razor_property *p1, *p2;
21.1267 + struct razor_set *set1, *set2;
21.1268 + uint32_t *map1, *map2;
21.1269 + int i, j, cmp, count1, count2;
21.1270 + char *pool1, *pool2;
21.1271 +
21.1272 + set1 = merger->source1.set;
21.1273 + set2 = merger->source2.set;
21.1274 + map1 = merger->source1.property_map;
21.1275 + map2 = merger->source2.property_map;
21.1276 +
21.1277 + i = 0;
21.1278 + j = 0;
21.1279 + pool1 = set1->string_pool.data;
21.1280 + pool2 = set2->string_pool.data;
21.1281 +
21.1282 + count1 = set1->properties.size / sizeof *p1;
21.1283 + count2 = set2->properties.size / sizeof *p2;
21.1284 + while (i < count1 || j < count2) {
21.1285 + if (i < count1 && map1[i] == 0) {
21.1286 + i++;
21.1287 + continue;
21.1288 + }
21.1289 + if (j < count2 && map2[j] == 0) {
21.1290 + j++;
21.1291 + continue;
21.1292 + }
21.1293 + p1 = (struct razor_property *) set1->properties.data + i;
21.1294 + p2 = (struct razor_property *) set2->properties.data + j;
21.1295 + if (i < count1 && j < count2)
21.1296 + cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
21.1297 + else if (i < count1)
21.1298 + cmp = -1;
21.1299 + else
21.1300 + cmp = 1;
21.1301 + if (cmp == 0)
21.1302 + cmp = p1->type - p2->type;
21.1303 + if (cmp == 0)
21.1304 + cmp = p1->relation - p2->relation;
21.1305 + if (cmp == 0)
21.1306 + cmp = versioncmp(&pool1[p1->version],
21.1307 + &pool2[p2->version]);
21.1308 + if (cmp < 0) {
21.1309 + map1[i++] = add_property(merger,
21.1310 + &pool1[p1->name],
21.1311 + p1->relation,
21.1312 + &pool1[p1->version],
21.1313 + p1->type);
21.1314 + } else if (cmp > 0) {
21.1315 + map2[j++] = add_property(merger,
21.1316 + &pool2[p2->name],
21.1317 + p2->relation,
21.1318 + &pool2[p2->version],
21.1319 + p2->type);
21.1320 + } else {
21.1321 + map1[i++] = map2[j++] = add_property(merger,
21.1322 + &pool1[p1->name],
21.1323 + p1->relation,
21.1324 + &pool1[p1->version],
21.1325 + p1->type);
21.1326 + }
21.1327 + }
21.1328 +}
21.1329 +
21.1330 +static void
21.1331 +emit_properties(struct list_head *properties, struct array *source_pool,
21.1332 + uint32_t *map, struct array *pool)
21.1333 +{
21.1334 + uint32_t r;
21.1335 + struct list *p, *q;
21.1336 +
21.1337 + r = pool->size / sizeof *q;
21.1338 + p = list_first(properties, source_pool);
21.1339 + while (p) {
21.1340 + q = array_add(pool, sizeof *q);
21.1341 + q->data = map[p->data];
21.1342 + q->flags = p->flags;
21.1343 + p = list_next(p);
21.1344 + }
21.1345 +
21.1346 + list_set_ptr(properties, r);
21.1347 +}
21.1348 +
21.1349 +static uint32_t
21.1350 +add_file(struct razor_merger *merger, const char *name)
21.1351 +{
21.1352 + struct razor_entry *e;
21.1353 +
21.1354 + e = array_add(&merger->set->files, sizeof *e);
21.1355 + e->name = hashtable_tokenize(&merger->table, name);
21.1356 + e->flags = 0;
21.1357 + e->start = 0;
21.1358 +
21.1359 + return e - (struct razor_entry *)merger->set->files.data;
21.1360 +}
21.1361 +
21.1362 +/* FIXME. Blah */
21.1363 +static int
21.1364 +fix_file_map(uint32_t *map,
21.1365 + struct razor_entry *files,
21.1366 + struct razor_entry *top)
21.1367 +{
21.1368 + uint32_t e;
21.1369 + int found_file = 0;
21.1370 +
21.1371 + e = top->start;
21.1372 + do {
21.1373 + if (files[e].start)
21.1374 + fix_file_map(map, files, &files[e]);
21.1375 + if (map[e])
21.1376 + found_file = 1;
21.1377 + } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
21.1378 +
21.1379 + if (found_file)
21.1380 + map[top - files] = 1;
21.1381 + return found_file;
21.1382 +}
21.1383 +
21.1384 +struct merge_directory {
21.1385 + uint32_t merged, dir1, dir2;
21.1386 +};
21.1387 +
21.1388 +static void
21.1389 +merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
21.1390 +{
21.1391 + struct razor_entry *root1, *root2, *mroot, *e1, *e2;
21.1392 + struct razor_set *set1, *set2;
21.1393 + struct array merge_stack;
21.1394 + struct merge_directory *child_md, *end_md;
21.1395 + uint32_t *map1, *map2, start, last;
21.1396 + int cmp;
21.1397 + char *pool1, *pool2;
21.1398 +
21.1399 + set1 = merger->source1.set;
21.1400 + set2 = merger->source2.set;
21.1401 + map1 = merger->source1.file_map;
21.1402 + map2 = merger->source2.file_map;
21.1403 + pool1 = set1->string_pool.data;
21.1404 + pool2 = set2->string_pool.data;
21.1405 + root1 = (struct razor_entry *) set1->files.data;
21.1406 + root2 = (struct razor_entry *) set2->files.data;
21.1407 +
21.1408 + array_init(&merge_stack);
21.1409 +
21.1410 + start = merger->set->files.size / sizeof (struct razor_entry);
21.1411 + last = 0;
21.1412 + e1 = md->dir1 ? root1 + md->dir1 : NULL;
21.1413 + e2 = md->dir2 ? root2 + md->dir2 : NULL;
21.1414 + while (e1 || e2) {
21.1415 + if (!e2 && !map1[e1 - root1]) {
21.1416 + if ((e1++)->flags & RAZOR_ENTRY_LAST)
21.1417 + e1 = NULL;
21.1418 + continue;
21.1419 + }
21.1420 + if (!e1 && !map2[e2 - root2]) {
21.1421 + if ((e2++)->flags & RAZOR_ENTRY_LAST)
21.1422 + e2 = NULL;
21.1423 + continue;
21.1424 + }
21.1425 + if (e1 && !map1[e1 - root1] &&
21.1426 + e2 && !map1[e2 - root2]) {
21.1427 + if ((e1++)->flags & RAZOR_ENTRY_LAST)
21.1428 + e1 = NULL;
21.1429 + if ((e2++)->flags & RAZOR_ENTRY_LAST)
21.1430 + e2 = NULL;
21.1431 + continue;
21.1432 + }
21.1433 +
21.1434 + if (!e1)
21.1435 + cmp = 1;
21.1436 + else if (!e2)
21.1437 + cmp = -1;
21.1438 + else {
21.1439 + cmp = strcmp (&pool1[e1->name],
21.1440 + &pool2[e2->name]);
21.1441 + }
21.1442 +
21.1443 + if (cmp < 0) {
21.1444 + if (map1[e1 - root1]) {
21.1445 + map1[e1 - root1] = last =
21.1446 + add_file(merger, &pool1[e1->name]);
21.1447 + if (e1->start) {
21.1448 + child_md = array_add(&merge_stack, sizeof (struct merge_directory));
21.1449 + child_md->merged = last;
21.1450 + child_md->dir1 = e1->start;
21.1451 + child_md->dir2 = 0;
21.1452 + }
21.1453 + }
21.1454 + if ((e1++)->flags & RAZOR_ENTRY_LAST)
21.1455 + e1 = NULL;
21.1456 + } else if (cmp > 0) {
21.1457 + if (map2[e2 - root2]) {
21.1458 + map2[e2 - root2] = last =
21.1459 + add_file(merger, &pool2[e2->name]);
21.1460 + if (e2->start) {
21.1461 + child_md = array_add(&merge_stack, sizeof (struct merge_directory));
21.1462 + child_md->merged = last;
21.1463 + child_md->dir1 = 0;
21.1464 + child_md->dir2 = e2->start;
21.1465 + }
21.1466 + }
21.1467 + if ((e2++)->flags & RAZOR_ENTRY_LAST)
21.1468 + e2 = NULL;
21.1469 + } else {
21.1470 + map1[e1 - root1] = map2[e2- root2] = last =
21.1471 + add_file(merger, &pool1[e1->name]);
21.1472 + if (e1->start || e2->start) {
21.1473 + child_md = array_add(&merge_stack, sizeof (struct merge_directory));
21.1474 + child_md->merged = last;
21.1475 + child_md->dir1 = e1->start;
21.1476 + child_md->dir2 = e2->start;
21.1477 + }
21.1478 + if ((e1++)->flags & RAZOR_ENTRY_LAST)
21.1479 + e1 = NULL;
21.1480 + if ((e2++)->flags & RAZOR_ENTRY_LAST)
21.1481 + e2 = NULL;
21.1482 + }
21.1483 + }
21.1484 +
21.1485 + mroot = (struct razor_entry *)merger->set->files.data;
21.1486 + if (last) {
21.1487 + mroot[last].flags = RAZOR_ENTRY_LAST;
21.1488 + mroot[md->merged].start = start;
21.1489 + } else
21.1490 + mroot[md->merged].start = 0;
21.1491 +
21.1492 + end_md = merge_stack.data + merge_stack.size;
21.1493 + for (child_md = merge_stack.data; child_md < end_md; child_md++)
21.1494 + merge_one_directory(merger, child_md);
21.1495 + array_release(&merge_stack);
21.1496 +}
21.1497 +
21.1498 +static void
21.1499 +merge_files(struct razor_merger *merger)
21.1500 +{
21.1501 + struct razor_entry *root;
21.1502 + struct merge_directory md;
21.1503 + uint32_t *map1, *map2;
21.1504 +
21.1505 + map1 = merger->source1.file_map;
21.1506 + map2 = merger->source2.file_map;
21.1507 +
21.1508 + md.merged = 0;
21.1509 +
21.1510 + if (merger->source1.set->files.size) {
21.1511 + root = (struct razor_entry *) merger->source1.set->files.data;
21.1512 + if (root->start)
21.1513 + fix_file_map(map1, root, root);
21.1514 + md.dir1 = root->start;
21.1515 + } else
21.1516 + md.dir1 = 0;
21.1517 +
21.1518 + if (merger->source2.set->files.size) {
21.1519 + root = (struct razor_entry *) merger->source2.set->files.data;
21.1520 + if (root->start)
21.1521 + fix_file_map(map2, root, root);
21.1522 + md.dir2 = root->start;
21.1523 + } else
21.1524 + md.dir2 = 0;
21.1525 +
21.1526 + merge_one_directory(merger, &md);
21.1527 +}
21.1528 +
21.1529 +static void
21.1530 +emit_files(struct list_head *files, struct array *source_pool,
21.1531 + uint32_t *map, struct array *pool)
21.1532 +{
21.1533 + uint32_t r;
21.1534 + struct list *p, *q;
21.1535 +
21.1536 + r = pool->size / sizeof *q;
21.1537 + p = list_first(files, source_pool);
21.1538 + while (p) {
21.1539 + q = array_add(pool, sizeof *q);
21.1540 + q->data = map[p->data];
21.1541 + q->flags = p->flags;
21.1542 + p = list_next(p);
21.1543 + }
21.1544 +
21.1545 + list_set_ptr(files, r);
21.1546 +}
21.1547 +
21.1548 +/* Rebuild property->packages maps. We can't just remap these, as a
21.1549 + * property may have lost or gained a number of packages. Allocate an
21.1550 + * array per property and loop through the packages and add them to
21.1551 + * the arrays for their properties. */
21.1552 +static void
21.1553 +rebuild_property_package_lists(struct razor_set *set)
21.1554 +{
21.1555 + struct array *pkgs, *a;
21.1556 + struct razor_package *pkg, *pkg_end;
21.1557 + struct razor_property *prop, *prop_end;
21.1558 + struct list *r;
21.1559 + uint32_t *q;
21.1560 + int count;
21.1561 +
21.1562 + count = set->properties.size / sizeof (struct razor_property);
21.1563 + pkgs = zalloc(count * sizeof *pkgs);
21.1564 + pkg_end = set->packages.data + set->packages.size;
21.1565 +
21.1566 + for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
21.1567 + r = list_first(&pkg->properties, &set->property_pool);
21.1568 + while (r) {
21.1569 + q = array_add(&pkgs[r->data], sizeof *q);
21.1570 + *q = pkg - (struct razor_package *) set->packages.data;
21.1571 + r = list_next(r);
21.1572 + }
21.1573 + }
21.1574 +
21.1575 + prop_end = set->properties.data + set->properties.size;
21.1576 + a = pkgs;
21.1577 + for (prop = set->properties.data; prop < prop_end; prop++, a++) {
21.1578 + list_set_array(&prop->packages, &set->package_pool, a, 0);
21.1579 + array_release(a);
21.1580 + }
21.1581 + free(pkgs);
21.1582 +}
21.1583 +
21.1584 +static void
21.1585 +rebuild_file_package_lists(struct razor_set *set)
21.1586 +{
21.1587 + struct array *pkgs, *a;
21.1588 + struct razor_package *pkg, *pkg_end;
21.1589 + struct razor_entry *entry, *entry_end;
21.1590 + struct list *r;
21.1591 + uint32_t *q;
21.1592 + int count;
21.1593 +
21.1594 + count = set->files.size / sizeof (struct razor_entry);
21.1595 + pkgs = zalloc(count * sizeof *pkgs);
21.1596 + pkg_end = set->packages.data + set->packages.size;
21.1597 +
21.1598 + for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
21.1599 + r = list_first(&pkg->files, &set->file_pool);
21.1600 + while (r) {
21.1601 + q = array_add(&pkgs[r->data], sizeof *q);
21.1602 + *q = pkg - (struct razor_package *) set->packages.data;
21.1603 + r = list_next(r);
21.1604 + }
21.1605 + }
21.1606 +
21.1607 + entry_end = set->files.data + set->files.size;
21.1608 + a = pkgs;
21.1609 + for (entry = set->files.data; entry < entry_end; entry++, a++) {
21.1610 + list_set_array(&entry->packages, &set->package_pool, a, 0);
21.1611 + array_release(a);
21.1612 + }
21.1613 + free(pkgs);
21.1614 +}
21.1615 +
21.1616 +static struct razor_set *
21.1617 +razor_merger_finish(struct razor_merger *merger)
21.1618 +{
21.1619 + struct razor_set *result;
21.1620 + struct razor_package *p, *pend;
21.1621 +
21.1622 + /* As we built the package list, we filled out a bitvector of
21.1623 + * the properties that are referenced by the packages in the
21.1624 + * new set. Now we do a parallel loop through the properties
21.1625 + * and emit those marked in the bit vector to the new set. In
21.1626 + * the process, we update the bit vector to actually map from
21.1627 + * indices in the old property list to indices in the new
21.1628 + * property list for both sets. */
21.1629 +
21.1630 + merge_properties(merger);
21.1631 + merge_files(merger);
21.1632 +
21.1633 + /* Now we loop through the packages again and emit the
21.1634 + * property lists, remapped to point to the new properties. */
21.1635 +
21.1636 + pend = merger->set->packages.data + merger->set->packages.size;
21.1637 + for (p = merger->set->packages.data; p < pend; p++) {
21.1638 + struct source *src;
21.1639 +
21.1640 + if (p->flags & UPSTREAM_SOURCE)
21.1641 + src = &merger->source2;
21.1642 + else
21.1643 + src = &merger->source1;
21.1644 +
21.1645 + emit_properties(&p->properties,
21.1646 + &src->set->property_pool,
21.1647 + src->property_map,
21.1648 + &merger->set->property_pool);
21.1649 + emit_files(&p->files,
21.1650 + &src->set->file_pool,
21.1651 + src->file_map,
21.1652 + &merger->set->file_pool);
21.1653 + p->flags &= ~UPSTREAM_SOURCE;
21.1654 + }
21.1655 +
21.1656 + rebuild_property_package_lists(merger->set);
21.1657 + rebuild_file_package_lists(merger->set);
21.1658 +
21.1659 + result = merger->set;
21.1660 + hashtable_release(&merger->table);
21.1661 + free(merger);
21.1662 +
21.1663 + return result;
21.1664 +}
21.1665 +
21.1666 +/* The diff order matters. We should sort the packages so that a
21.1667 + * REMOVE of a package comes before the INSTALL, and so that all
21.1668 + * requires for a package have been installed before the package.
21.1669 + **/
21.1670 +
21.1671 +void
21.1672 +razor_set_diff(struct razor_set *set, struct razor_set *upstream,
21.1673 + razor_package_callback_t callback, void *data)
21.1674 +{
21.1675 + struct razor_package_iterator *pi1, *pi2;
21.1676 + struct razor_package *p1, *p2;
21.1677 + const char *name1, *name2, *version1, *version2, *arch1, *arch2;
21.1678 + int res;
21.1679 +
21.1680 + pi1 = razor_package_iterator_create(set);
21.1681 + pi2 = razor_package_iterator_create(upstream);
21.1682 +
21.1683 + razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
21.1684 + razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
21.1685 +
21.1686 + while (p1 || p2) {
21.1687 + if (p1 && p2) {
21.1688 + res = strcmp(name1, name2);
21.1689 + if (res == 0)
21.1690 + res = versioncmp(version1, version2);
21.1691 + } else {
21.1692 + res = 0;
21.1693 + }
21.1694 +
21.1695 + if (p2 == NULL || res < 0)
21.1696 + callback(name1, version1, NULL, arch1, data);
21.1697 + else if (p1 == NULL || res > 0)
21.1698 + callback(name2, NULL, version2, arch2, data);
21.1699 +
21.1700 + if (p1 != NULL && res <= 0)
21.1701 + razor_package_iterator_next(pi1, &p1,
21.1702 + &name1, &version1, &arch1);
21.1703 + if (p2 != NULL && res >= 0)
21.1704 + razor_package_iterator_next(pi2, &p2,
21.1705 + &name2, &version2, &arch2);
21.1706 + }
21.1707 +
21.1708 + razor_package_iterator_destroy(pi1);
21.1709 + razor_package_iterator_destroy(pi2);
21.1710 +}
21.1711 +
21.1712 +static int
21.1713 +provider_satisfies_requirement(struct razor_property *provider,
21.1714 + const char *provider_strings,
21.1715 + enum razor_version_relation relation,
21.1716 + const char *required)
21.1717 +{
21.1718 + int cmp, len;
21.1719 + const char *provided = &provider_strings[provider->version];
21.1720 +
21.1721 + if (!*required)
21.1722 + return 1;
21.1723 + if (!*provided) {
21.1724 + if (relation >= RAZOR_VERSION_EQUAL)
21.1725 + return 1;
21.1726 + else
21.1727 + return 0;
21.1728 + }
21.1729 +
21.1730 + cmp = versioncmp(provided, required);
21.1731 +
21.1732 + switch (relation) {
21.1733 + case RAZOR_VERSION_LESS:
21.1734 + return cmp < 0;
21.1735 +
21.1736 + case RAZOR_VERSION_LESS_OR_EQUAL:
21.1737 + if (cmp <= 0)
21.1738 + return 1;
21.1739 + /* fall through: FIXME, make sure this is correct */
21.1740 +
21.1741 + case RAZOR_VERSION_EQUAL:
21.1742 + if (cmp == 0)
21.1743 + return 1;
21.1744 +
21.1745 + /* "foo == 1.1" is satisfied by "foo 1.1-2" */
21.1746 + len = strlen(required);
21.1747 + if (!strncmp(required, provided, len) && provided[len] == '-')
21.1748 + return 1;
21.1749 + return 0;
21.1750 +
21.1751 + case RAZOR_VERSION_GREATER_OR_EQUAL:
21.1752 + return cmp >= 0;
21.1753 +
21.1754 + case RAZOR_VERSION_GREATER:
21.1755 + return cmp > 0;
21.1756 + }
21.1757 +
21.1758 + /* shouldn't happen */
21.1759 + return 0;
21.1760 +}
21.1761 +
21.1762 +#define TRANS_PACKAGE_PRESENT 1
21.1763 +#define TRANS_PACKAGE_UPDATE 2
21.1764 +#define TRANS_PROPERTY_SATISFIED 0x80000000
21.1765 +
21.1766 +struct transaction_set {
21.1767 + struct razor_set *set;
21.1768 + uint32_t *packages;
21.1769 + uint32_t *properties;
21.1770 +};
21.1771 +
21.1772 +struct razor_transaction {
21.1773 + int package_count, errors;
21.1774 + struct transaction_set system, upstream;
21.1775 + int changes;
21.1776 +};
21.1777 +
21.1778 +static void
21.1779 +transaction_set_init(struct transaction_set *ts, struct razor_set *set)
21.1780 +{
21.1781 + int count;
21.1782 +
21.1783 + ts->set = set;
21.1784 + count = set->packages.size / sizeof (struct razor_package);
21.1785 + ts->packages = zalloc(count * sizeof *ts->packages);
21.1786 + count = set->properties.size / sizeof (struct razor_property);
21.1787 + ts->properties = zalloc(count * sizeof *ts->properties);
21.1788 +}
21.1789 +
21.1790 +static void
21.1791 +transaction_set_release(struct transaction_set *ts)
21.1792 +{
21.1793 + free(ts->packages);
21.1794 + free(ts->properties);
21.1795 +}
21.1796 +
21.1797 +static void
21.1798 +transaction_set_install_package(struct transaction_set *ts,
21.1799 + struct razor_package *package)
21.1800 +{
21.1801 + struct razor_package *pkgs;
21.1802 + struct list *prop;
21.1803 + int i;
21.1804 +
21.1805 + pkgs = ts->set->packages.data;
21.1806 + i = package - pkgs;
21.1807 + if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
21.1808 + return;
21.1809 +
21.1810 + ts->packages[i] = TRANS_PACKAGE_PRESENT;
21.1811 +
21.1812 + prop = list_first(&package->properties, &ts->set->property_pool);
21.1813 + while (prop) {
21.1814 + ts->properties[prop->data]++;
21.1815 + prop = list_next(prop);
21.1816 + }
21.1817 +}
21.1818 +
21.1819 +static void
21.1820 +transaction_set_remove_package(struct transaction_set *ts,
21.1821 + struct razor_package *package)
21.1822 +{
21.1823 + struct razor_package *pkgs;
21.1824 + struct list *prop;
21.1825 + int i;
21.1826 +
21.1827 + pkgs = ts->set->packages.data;
21.1828 + i = package - pkgs;
21.1829 + if (ts->packages[i] == 0)
21.1830 + return;
21.1831 +
21.1832 + ts->packages[i] = 0;
21.1833 +
21.1834 + prop = list_first(&package->properties, &ts->set->property_pool);
21.1835 + while (prop) {
21.1836 + ts->properties[prop->data]--;
21.1837 + prop = list_next(prop);
21.1838 + }
21.1839 +}
21.1840 +
21.1841 +struct razor_transaction *
21.1842 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
21.1843 +{
21.1844 + struct razor_transaction *trans;
21.1845 + struct razor_package *p, *spkgs, *pend;
21.1846 +
21.1847 + trans = zalloc(sizeof *trans);
21.1848 + transaction_set_init(&trans->system, system);
21.1849 + transaction_set_init(&trans->upstream, upstream);
21.1850 +
21.1851 + spkgs = trans->system.set->packages.data;
21.1852 + pend = trans->system.set->packages.data +
21.1853 + trans->system.set->packages.size;
21.1854 + for (p = spkgs; p < pend; p++)
21.1855 + transaction_set_install_package(&trans->system, p);
21.1856 +
21.1857 + return trans;
21.1858 +}
21.1859 +
21.1860 +void
21.1861 +razor_transaction_install_package(struct razor_transaction *trans,
21.1862 + struct razor_package *package)
21.1863 +{
21.1864 + transaction_set_install_package(&trans->upstream, package);
21.1865 + trans->changes++;
21.1866 +}
21.1867 +
21.1868 +void
21.1869 +razor_transaction_remove_package(struct razor_transaction *trans,
21.1870 + struct razor_package *package)
21.1871 +{
21.1872 + transaction_set_remove_package(&trans->system, package);
21.1873 + trans->changes++;
21.1874 +}
21.1875 +
21.1876 +void
21.1877 +razor_transaction_update_package(struct razor_transaction *trans,
21.1878 + struct razor_package *package)
21.1879 +{
21.1880 + struct razor_package *spkgs, *upkgs, *end;
21.1881 +
21.1882 + spkgs = trans->system.set->packages.data;
21.1883 + upkgs = trans->upstream.set->packages.data;
21.1884 + end = trans->system.set->packages.data +
21.1885 + trans->system.set->packages.size;
21.1886 + if (spkgs <= package && package < end)
21.1887 + trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
21.1888 + else
21.1889 + trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
21.1890 +}
21.1891 +
21.1892 +struct prop_iter {
21.1893 + struct razor_property *p, *start, *end;
21.1894 + const char *pool;
21.1895 + uint32_t *present;
21.1896 +};
21.1897 +
21.1898 +static void
21.1899 +prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
21.1900 +{
21.1901 + pi->p = ts->set->properties.data;
21.1902 + pi->start = ts->set->properties.data;
21.1903 + pi->end = ts->set->properties.data + ts->set->properties.size;
21.1904 + pi->pool = ts->set->string_pool.data;
21.1905 + pi->present = ts->properties;
21.1906 +}
21.1907 +
21.1908 +static int
21.1909 +prop_iter_next(struct prop_iter *pi,
21.1910 + enum razor_property_type type, struct razor_property **p)
21.1911 +{
21.1912 + while (pi->p < pi->end) {
21.1913 + if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
21.1914 + pi->p->type == type) {
21.1915 + *p = pi->p++;
21.1916 + return 1;
21.1917 + }
21.1918 + pi->p++;
21.1919 + }
21.1920 +
21.1921 + return 0;
21.1922 +}
21.1923 +
21.1924 +static struct razor_property *
21.1925 +prop_iter_seek_to(struct prop_iter *pi,
21.1926 + enum razor_property_type type, const char *match)
21.1927 +{
21.1928 + uint32_t name;
21.1929 +
21.1930 + while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
21.1931 + pi->p++;
21.1932 +
21.1933 + if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
21.1934 + return NULL;
21.1935 +
21.1936 + name = pi->p->name;
21.1937 + while (pi->p < pi->end &&
21.1938 + pi->p->name == name &&
21.1939 + pi->p->type != type)
21.1940 + pi->p++;
21.1941 +
21.1942 + if (pi->p == pi->end || pi->p->name != name)
21.1943 + return NULL;
21.1944 +
21.1945 + return pi->p;
21.1946 +}
21.1947 +
21.1948 +/* Remove packages from set that provide any of the matching (same
21.1949 + * name and type) providers from ppi onwards that match the
21.1950 + * requirement that rpi points to. */
21.1951 +static void
21.1952 +remove_matching_providers(struct razor_transaction *trans,
21.1953 + struct prop_iter *ppi,
21.1954 + enum razor_version_relation relation,
21.1955 + const char *version)
21.1956 +{
21.1957 + struct razor_property *p;
21.1958 + struct razor_package *pkg, *pkgs;
21.1959 + struct razor_package_iterator pkg_iter;
21.1960 + struct razor_set *set;
21.1961 + const char *n, *v, *a;
21.1962 +
21.1963 + if (ppi->present == trans->system.properties)
21.1964 + set = trans->system.set;
21.1965 + else
21.1966 + set = trans->upstream.set;
21.1967 +
21.1968 + pkgs = (struct razor_package *) set->packages.data;
21.1969 + for (p = ppi->p;
21.1970 + p < ppi->end &&
21.1971 + p->name == ppi->p->name &&
21.1972 + p->type == ppi->p->type;
21.1973 + p++) {
21.1974 + if (!ppi->present[p - ppi->start])
21.1975 + continue;
21.1976 + if (!provider_satisfies_requirement(p, ppi->pool,
21.1977 + relation, version))
21.1978 + continue;
21.1979 +
21.1980 + razor_package_iterator_init_for_property(&pkg_iter, set, p);
21.1981 + while (razor_package_iterator_next(&pkg_iter,
21.1982 + &pkg, &n, &v, &a)) {
21.1983 + fprintf(stderr, "removing %s-%s\n", n, v);
21.1984 + razor_transaction_remove_package(trans, pkg);
21.1985 + }
21.1986 + }
21.1987 +}
21.1988 +
21.1989 +static void
21.1990 +flag_matching_providers(struct razor_transaction *trans,
21.1991 + struct prop_iter *ppi,
21.1992 + struct razor_property *r,
21.1993 + struct prop_iter *rpi,
21.1994 + unsigned int flag)
21.1995 +{
21.1996 + struct razor_property *p;
21.1997 + struct razor_package *pkg, *pkgs;
21.1998 + struct razor_package_iterator pkg_iter;
21.1999 + struct razor_set *set;
21.2000 + const char *name, *version, *arch;
21.2001 + uint32_t *flags;
21.2002 +
21.2003 + if (ppi->present == trans->system.properties) {
21.2004 + set = trans->system.set;
21.2005 + flags = trans->system.packages;
21.2006 + } else {
21.2007 + set = trans->upstream.set;
21.2008 + flags = trans->upstream.packages;
21.2009 + }
21.2010 +
21.2011 + pkgs = (struct razor_package *) set->packages.data;
21.2012 + for (p = ppi->p;
21.2013 + p < ppi->end &&
21.2014 + p->name == ppi->p->name &&
21.2015 + p->type == ppi->p->type;
21.2016 + p++) {
21.2017 + if (!ppi->present[p - ppi->start])
21.2018 + continue;
21.2019 + if (!provider_satisfies_requirement(p, ppi->pool,
21.2020 + r->relation,
21.2021 + &rpi->pool[r->version]))
21.2022 + continue;
21.2023 +
21.2024 + razor_package_iterator_init_for_property(&pkg_iter, set, p);
21.2025 + while (razor_package_iterator_next(&pkg_iter, &pkg,
21.2026 + &name, &version, &arch)) {
21.2027 +
21.2028 + fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
21.2029 + name, version,
21.2030 + ppi->pool + p->name,
21.2031 + rpi->pool + r->name,
21.2032 + rpi->pool + r->version);
21.2033 + flags[pkg - pkgs] |= flag;
21.2034 + }
21.2035 + }
21.2036 +}
21.2037 +
21.2038 +static struct razor_package *
21.2039 +pick_matching_provider(struct razor_set *set,
21.2040 + struct prop_iter *ppi,
21.2041 + enum razor_version_relation relation,
21.2042 + const char *version)
21.2043 +{
21.2044 + struct razor_property *p;
21.2045 + struct razor_package *pkgs;
21.2046 + struct list *i;
21.2047 +
21.2048 + /* This is where we decide which pkgs to pull in to satisfy a
21.2049 + * requirement. There may be several different providers
21.2050 + * (different versions) and each version of a provider may
21.2051 + * come from a number of packages. We pick the first package
21.2052 + * from the first provider that matches. */
21.2053 +
21.2054 + pkgs = set->packages.data;
21.2055 + for (p = ppi->p;
21.2056 + p < ppi->end &&
21.2057 + p->name == ppi->p->name &&
21.2058 + p->type == ppi->p->type &&
21.2059 + ppi->present[p - ppi->start] == 0;
21.2060 + p++) {
21.2061 + if (!provider_satisfies_requirement(p, ppi->pool,
21.2062 + relation, version))
21.2063 + continue;
21.2064 +
21.2065 + i = list_first(&p->packages, &set->package_pool);
21.2066 +
21.2067 + return &pkgs[i->data];
21.2068 + }
21.2069 +
21.2070 + return NULL;
21.2071 +}
21.2072 +
21.2073 +static void
21.2074 +remove_obsoleted_packages(struct razor_transaction *trans)
21.2075 +{
21.2076 + struct razor_property *up;
21.2077 + struct razor_package *spkgs;
21.2078 + struct prop_iter spi, upi;
21.2079 +
21.2080 + spkgs = trans->system.set->packages.data;
21.2081 + prop_iter_init(&spi, &trans->system);
21.2082 + prop_iter_init(&upi, &trans->upstream);
21.2083 +
21.2084 + while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
21.2085 + if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
21.2086 + &upi.pool[up->name]))
21.2087 + continue;
21.2088 + remove_matching_providers(trans, &spi, up->relation,
21.2089 + &upi.pool[up->version]);
21.2090 + }
21.2091 +}
21.2092 +
21.2093 +static int
21.2094 +any_provider_satisfies_requirement(struct prop_iter *ppi,
21.2095 + enum razor_version_relation relation,
21.2096 + const char *version)
21.2097 +{
21.2098 + struct razor_property *p;
21.2099 +
21.2100 + for (p = ppi->p;
21.2101 + p < ppi->end &&
21.2102 + p->name == ppi->p->name &&
21.2103 + p->type == ppi->p->type;
21.2104 + p++) {
21.2105 + if (ppi->present[p - ppi->start] > 0 &&
21.2106 + provider_satisfies_requirement(p, ppi->pool,
21.2107 + relation, version))
21.2108 + return 1;
21.2109 + }
21.2110 +
21.2111 + return 0;
21.2112 +}
21.2113 +
21.2114 +static void
21.2115 +clear_requires_flags(struct transaction_set *ts)
21.2116 +{
21.2117 + struct razor_property *p;
21.2118 + const char *pool;
21.2119 + int i, count;
21.2120 +
21.2121 + count = ts->set->properties.size / sizeof *p;
21.2122 + p = ts->set->properties.data;
21.2123 + pool = ts->set->string_pool.data;
21.2124 + for (i = 0; i < count; i++) {
21.2125 + ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
21.2126 + if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
21.2127 + ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
21.2128 + }
21.2129 +}
21.2130 +
21.2131 +static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
21.2132 +
21.2133 +static void
21.2134 +mark_satisfied_requires(struct razor_transaction *trans,
21.2135 + struct transaction_set *rts,
21.2136 + struct transaction_set *pts)
21.2137 +{
21.2138 + struct prop_iter rpi, ppi;
21.2139 + struct razor_property *rp;
21.2140 +
21.2141 + prop_iter_init(&rpi, rts);
21.2142 + prop_iter_init(&ppi, pts);
21.2143 +
21.2144 + while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
21.2145 + if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
21.2146 + &rpi.pool[rp->name]))
21.2147 + continue;
21.2148 +
21.2149 + if (any_provider_satisfies_requirement(&ppi, rp->relation,
21.2150 + &rpi.pool[rp->version]))
21.2151 + rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
21.2152 + }
21.2153 +}
21.2154 +
21.2155 +static void
21.2156 +mark_all_satisfied_requires(struct razor_transaction *trans)
21.2157 +{
21.2158 + clear_requires_flags(&trans->system);
21.2159 + clear_requires_flags(&trans->upstream);
21.2160 + mark_satisfied_requires(trans, &trans->system, &trans->system);
21.2161 + mark_satisfied_requires(trans, &trans->system, &trans->upstream);
21.2162 + mark_satisfied_requires(trans, &trans->upstream, &trans->system);
21.2163 + mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
21.2164 +}
21.2165 +
21.2166 +static void
21.2167 +update_unsatisfied_packages(struct razor_transaction *trans)
21.2168 +{
21.2169 + struct razor_package *spkgs, *pkg;
21.2170 + struct razor_property *sp;
21.2171 + struct prop_iter spi;
21.2172 + struct razor_package_iterator pkg_iter;
21.2173 + const char *name, *version, *arch;
21.2174 +
21.2175 + spkgs = trans->system.set->packages.data;
21.2176 + prop_iter_init(&spi, &trans->system);
21.2177 +
21.2178 + while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
21.2179 + if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
21.2180 + continue;
21.2181 +
21.2182 + razor_package_iterator_init_for_property(&pkg_iter,
21.2183 + trans->system.set,
21.2184 + sp);
21.2185 + while (razor_package_iterator_next(&pkg_iter, &pkg,
21.2186 + &name, &version, &arch)) {
21.2187 + fprintf(stderr, "updating %s because %s %s %s "
21.2188 + "isn't satisfied\n",
21.2189 + name, spi.pool + sp->name,
21.2190 + relation_string[sp->relation],
21.2191 + spi.pool + sp->version);
21.2192 + trans->system.packages[pkg - spkgs] |=
21.2193 + TRANS_PACKAGE_UPDATE;
21.2194 + }
21.2195 + }
21.2196 +}
21.2197 +
21.2198 +void
21.2199 +razor_transaction_update_all(struct razor_transaction *trans)
21.2200 +{
21.2201 + struct razor_package *p;
21.2202 + int i, count;
21.2203 +
21.2204 + count = trans->system.set->packages.size / sizeof *p;
21.2205 + for (i = 0; i < count; i++)
21.2206 + trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
21.2207 +}
21.2208 +
21.2209 +static void
21.2210 +update_conflicted_packages(struct razor_transaction *trans)
21.2211 +{
21.2212 + struct razor_package *pkg, *spkgs;
21.2213 + struct razor_property *up, *sp;
21.2214 + struct prop_iter spi, upi;
21.2215 + struct razor_package_iterator pkg_iter;
21.2216 + const char *name, *version, *arch;
21.2217 +
21.2218 + spkgs = trans->system.set->packages.data;
21.2219 + prop_iter_init(&spi, &trans->system);
21.2220 + prop_iter_init(&upi, &trans->upstream);
21.2221 +
21.2222 + while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
21.2223 + if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
21.2224 + &spi.pool[sp->name]))
21.2225 + continue;
21.2226 +
21.2227 + if (!any_provider_satisfies_requirement(&upi, sp->relation,
21.2228 + &spi.pool[sp->version]))
21.2229 + continue;
21.2230 +
21.2231 + razor_package_iterator_init_for_property(&pkg_iter,
21.2232 + trans->system.set,
21.2233 + sp);
21.2234 + while (razor_package_iterator_next(&pkg_iter, &pkg,
21.2235 + &name, &version, &arch)) {
21.2236 + fprintf(stderr, "updating %s %s because it conflicts with %s",
21.2237 + name, version, spi.pool + sp->name);
21.2238 + trans->system.packages[pkg - spkgs] |=
21.2239 + TRANS_PACKAGE_UPDATE;
21.2240 + }
21.2241 + }
21.2242 +
21.2243 + prop_iter_init(&spi, &trans->system);
21.2244 + prop_iter_init(&upi, &trans->upstream);
21.2245 +
21.2246 + while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
21.2247 + sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
21.2248 + &upi.pool[upi.p->name]);
21.2249 +
21.2250 + if (sp)
21.2251 + flag_matching_providers(trans, &spi, up, &upi,
21.2252 + TRANS_PACKAGE_UPDATE);
21.2253 + }
21.2254 +}
21.2255 +
21.2256 +static void
21.2257 +pull_in_requirements(struct razor_transaction *trans,
21.2258 + struct prop_iter *rpi, struct prop_iter *ppi)
21.2259 +{
21.2260 + struct razor_property *rp, *pp;
21.2261 + struct razor_package *pkg, *upkgs;
21.2262 +
21.2263 + upkgs = trans->upstream.set->packages.data;
21.2264 + while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
21.2265 + if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
21.2266 + continue;
21.2267 +
21.2268 + pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
21.2269 + &rpi->pool[rp->name]);
21.2270 + if (pp == NULL)
21.2271 + continue;
21.2272 + pkg = pick_matching_provider(trans->upstream.set,
21.2273 + ppi, rp->relation,
21.2274 + &rpi->pool[rp->version]);
21.2275 + if (pkg == NULL)
21.2276 + continue;
21.2277 +
21.2278 + rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
21.2279 +
21.2280 + fprintf(stderr, "pulling in %s which provides %s %s %s "
21.2281 + "to satisfy %s %s %s\n",
21.2282 + ppi->pool + pkg->name,
21.2283 + ppi->pool + pp->name,
21.2284 + relation_string[pp->relation],
21.2285 + ppi->pool + pp->version,
21.2286 + &rpi->pool[rp->name],
21.2287 + relation_string[rp->relation],
21.2288 + &rpi->pool[rp->version]);
21.2289 +
21.2290 + trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
21.2291 + }
21.2292 +}
21.2293 +
21.2294 +static void
21.2295 +pull_in_all_requirements(struct razor_transaction *trans)
21.2296 +{
21.2297 + struct prop_iter rpi, ppi;
21.2298 +
21.2299 + prop_iter_init(&rpi, &trans->system);
21.2300 + prop_iter_init(&ppi, &trans->upstream);
21.2301 + pull_in_requirements(trans, &rpi, &ppi);
21.2302 +
21.2303 + prop_iter_init(&rpi, &trans->upstream);
21.2304 + prop_iter_init(&ppi, &trans->upstream);
21.2305 + pull_in_requirements(trans, &rpi, &ppi);
21.2306 +}
21.2307 +
21.2308 +static void
21.2309 +flush_scheduled_system_updates(struct razor_transaction *trans)
21.2310 +{
21.2311 + struct razor_package_iterator *pi;
21.2312 + struct razor_package *p, *pkg, *spkgs;
21.2313 + struct prop_iter ppi;
21.2314 + const char *name, *version, *arch;
21.2315 +
21.2316 + spkgs = trans->system.set->packages.data;
21.2317 + pi = razor_package_iterator_create(trans->system.set);
21.2318 + prop_iter_init(&ppi, &trans->upstream);
21.2319 +
21.2320 + while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
21.2321 + if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
21.2322 + continue;
21.2323 +
21.2324 + if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
21.2325 + continue;
21.2326 +
21.2327 + pkg = pick_matching_provider(trans->upstream.set, &ppi,
21.2328 + RAZOR_VERSION_GREATER, version);
21.2329 + if (pkg == NULL)
21.2330 + continue;
21.2331 +
21.2332 + fprintf(stderr, "updating %s-%s to %s-%s\n",
21.2333 + name, version,
21.2334 + &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
21.2335 +
21.2336 + razor_transaction_remove_package(trans, p);
21.2337 + razor_transaction_install_package(trans, pkg);
21.2338 + }
21.2339 +
21.2340 + razor_package_iterator_destroy(pi);
21.2341 +}
21.2342 +
21.2343 +static void
21.2344 +flush_scheduled_upstream_updates(struct razor_transaction *trans)
21.2345 +{
21.2346 + struct razor_package_iterator *pi;
21.2347 + struct razor_package *p, *upkgs;
21.2348 + struct prop_iter spi;
21.2349 + const char *name, *version, *arch;
21.2350 +
21.2351 + upkgs = trans->upstream.set->packages.data;
21.2352 + pi = razor_package_iterator_create(trans->upstream.set);
21.2353 + prop_iter_init(&spi, &trans->system);
21.2354 +
21.2355 + while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
21.2356 + if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
21.2357 + continue;
21.2358 +
21.2359 + if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
21.2360 + continue;
21.2361 + remove_matching_providers(trans, &spi,
21.2362 + RAZOR_VERSION_LESS, version);
21.2363 + razor_transaction_install_package(trans, p);
21.2364 + fprintf(stderr, "installing %s-%s\n", name, version);
21.2365 + }
21.2366 +}
21.2367 +
21.2368 +int
21.2369 +razor_transaction_resolve(struct razor_transaction *trans)
21.2370 +{
21.2371 + int last = 0;
21.2372 +
21.2373 + flush_scheduled_system_updates(trans);
21.2374 +
21.2375 + while (last < trans->changes) {
21.2376 + last = trans->changes;
21.2377 + remove_obsoleted_packages(trans);
21.2378 + mark_all_satisfied_requires(trans);
21.2379 + update_unsatisfied_packages(trans);
21.2380 + update_conflicted_packages(trans);
21.2381 + pull_in_all_requirements(trans);
21.2382 + flush_scheduled_system_updates(trans);
21.2383 + flush_scheduled_upstream_updates(trans);
21.2384 + }
21.2385 +
21.2386 + return trans->changes;
21.2387 +}
21.2388 +
21.2389 +static void
21.2390 +describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
21.2391 +{
21.2392 + struct razor_package_iterator pi;
21.2393 + struct razor_package *pkg;
21.2394 + const char *name, *version, *arch, *pool;
21.2395 +
21.2396 + pool = set->string_pool.data;
21.2397 + if (pool[rp->version] == '\0') {
21.2398 + razor_package_iterator_init_for_property(&pi, set, rp);
21.2399 + while (razor_package_iterator_next(&pi, &pkg,
21.2400 + &name, &version, &arch))
21.2401 + fprintf(stderr, "%s is needed by %s-%s.%s\n",
21.2402 + &pool[rp->name],
21.2403 + name, version, arch);
21.2404 + } else {
21.2405 + razor_package_iterator_init_for_property(&pi, set, rp);
21.2406 + while (razor_package_iterator_next(&pi, &pkg,
21.2407 + &name, &version, &arch))
21.2408 + fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
21.2409 + &pool[rp->name],
21.2410 + relation_string[rp->relation],
21.2411 + &pool[rp->version],
21.2412 + name, version, arch);
21.2413 + }
21.2414 +}
21.2415 +
21.2416 +int
21.2417 +razor_transaction_describe(struct razor_transaction *trans)
21.2418 +{
21.2419 + struct prop_iter rpi;
21.2420 + struct razor_property *rp;
21.2421 + int unsatisfied;
21.2422 +
21.2423 + flush_scheduled_system_updates(trans);
21.2424 + flush_scheduled_upstream_updates(trans);
21.2425 + mark_all_satisfied_requires(trans);
21.2426 +
21.2427 + unsatisfied = 0;
21.2428 + prop_iter_init(&rpi, &trans->system);
21.2429 + while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
21.2430 + if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
21.2431 + describe_unsatisfied(trans->system.set, rp);
21.2432 + unsatisfied++;
21.2433 + }
21.2434 + }
21.2435 +
21.2436 + prop_iter_init(&rpi, &trans->upstream);
21.2437 + while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
21.2438 + if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
21.2439 + describe_unsatisfied(trans->upstream.set, rp);
21.2440 + unsatisfied++;
21.2441 + }
21.2442 + }
21.2443 +
21.2444 + return unsatisfied;
21.2445 +}
21.2446 +
21.2447 +int
21.2448 +razor_transaction_unsatisfied_property(struct razor_transaction *trans,
21.2449 + const char *name,
21.2450 + enum razor_version_relation rel,
21.2451 + const char *version,
21.2452 + enum razor_property_type type)
21.2453 +{
21.2454 + struct prop_iter pi;
21.2455 + struct razor_property *p;
21.2456 +
21.2457 + prop_iter_init(&pi, &trans->system);
21.2458 + while (prop_iter_next(&pi, type, &p)) {
21.2459 + if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
21.2460 + p->relation == rel &&
21.2461 + strcmp(&pi.pool[p->name], name) == 0 &&
21.2462 + strcmp(&pi.pool[p->version], version) == 0)
21.2463 +
21.2464 + return 1;
21.2465 + }
21.2466 +
21.2467 + prop_iter_init(&pi, &trans->upstream);
21.2468 + while (prop_iter_next(&pi, type, &p)) {
21.2469 + if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
21.2470 + p->relation == rel &&
21.2471 + strcmp(&pi.pool[p->name], name) == 0 &&
21.2472 + strcmp(&pi.pool[p->version], version) == 0)
21.2473 +
21.2474 + return 1;
21.2475 + }
21.2476 +
21.2477 + return 0;
21.2478 +}
21.2479 +
21.2480 +struct razor_set *
21.2481 +razor_transaction_finish(struct razor_transaction *trans)
21.2482 +{
21.2483 + struct razor_merger *merger;
21.2484 + struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
21.2485 + char *upool, *spool;
21.2486 + int cmp;
21.2487 +
21.2488 + s = trans->system.set->packages.data;
21.2489 + spkgs = trans->system.set->packages.data;
21.2490 + send = trans->system.set->packages.data +
21.2491 + trans->system.set->packages.size;
21.2492 + spool = trans->system.set->string_pool.data;
21.2493 +
21.2494 + u = trans->upstream.set->packages.data;
21.2495 + upkgs = trans->upstream.set->packages.data;
21.2496 + uend = trans->upstream.set->packages.data +
21.2497 + trans->upstream.set->packages.size;
21.2498 + upool = trans->upstream.set->string_pool.data;
21.2499 +
21.2500 + merger = razor_merger_create(trans->system.set, trans->upstream.set);
21.2501 + while (s < send || u < uend) {
21.2502 + if (s < send && u < uend)
21.2503 + cmp = strcmp(&spool[s->name], &upool[u->name]);
21.2504 + else if (s < send)
21.2505 + cmp = -1;
21.2506 + else
21.2507 + cmp = 1;
21.2508 +
21.2509 + if (cmp < 0) {
21.2510 + if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
21.2511 + razor_merger_add_package(merger, s);
21.2512 + s++;
21.2513 + } else if (cmp == 0) {
21.2514 + if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
21.2515 + razor_merger_add_package(merger, s);
21.2516 + if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
21.2517 + razor_merger_add_package(merger, u);
21.2518 +
21.2519 + s++;
21.2520 + u++;
21.2521 + } else {
21.2522 + if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
21.2523 + razor_merger_add_package(merger, u);
21.2524 + u++;
21.2525 + }
21.2526 + }
21.2527 +
21.2528 + razor_transaction_destroy(trans);
21.2529 +
21.2530 + return razor_merger_finish(merger);
21.2531 +}
21.2532 +
21.2533 +void
21.2534 +razor_transaction_destroy(struct razor_transaction *trans)
21.2535 +{
21.2536 + transaction_set_release(&trans->system);
21.2537 + transaction_set_release(&trans->upstream);
21.2538 + free(trans);
21.2539 +}
21.2540 +
21.2541 +struct razor_package_query {
21.2542 + struct razor_set *set;
21.2543 + char *vector;
21.2544 + int count;
21.2545 +};
21.2546 +
21.2547 +struct razor_package_query *
21.2548 +razor_package_query_create(struct razor_set *set)
21.2549 +{
21.2550 + struct razor_package_query *pq;
21.2551 + int count;
21.2552 +
21.2553 + pq = zalloc(sizeof *pq);
21.2554 + pq->set = set;
21.2555 + count = set->packages.size / sizeof(struct razor_package);
21.2556 + pq->vector = zalloc(count * sizeof(char));
21.2557 +
21.2558 + return pq;
21.2559 +}
21.2560 +
21.2561 +void
21.2562 +razor_package_query_add_package(struct razor_package_query *pq,
21.2563 + struct razor_package *p)
21.2564 +{
21.2565 + struct razor_package *packages;
21.2566 +
21.2567 + packages = pq->set->packages.data;
21.2568 + pq->count += pq->vector[p - packages] ^ 1;
21.2569 + pq->vector[p - packages] = 1;
21.2570 +}
21.2571 +
21.2572 +void
21.2573 +razor_package_query_add_iterator(struct razor_package_query *pq,
21.2574 + struct razor_package_iterator *pi)
21.2575 +{
21.2576 + struct razor_package *packages, *p;
21.2577 + const char *name, *version, *arch;
21.2578 +
21.2579 + packages = pq->set->packages.data;
21.2580 + while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
21.2581 + pq->count += pq->vector[p - packages] ^ 1;
21.2582 + pq->vector[p - packages] = 1;
21.2583 + }
21.2584 +}
21.2585 +
21.2586 +struct razor_package_iterator *
21.2587 +razor_package_query_finish(struct razor_package_query *pq)
21.2588 +{
21.2589 + struct razor_package_iterator *pi;
21.2590 + struct razor_set *set;
21.2591 + struct list *index;
21.2592 + int i, j, count;
21.2593 +
21.2594 + set = pq->set;
21.2595 + count = set->packages.size / sizeof(struct razor_package);
21.2596 + index = zalloc(pq->count * sizeof *index);
21.2597 +
21.2598 + for (i = 0, j = 0; i < count; i++) {
21.2599 + if (!pq->vector[i])
21.2600 + continue;
21.2601 +
21.2602 + index[j].data = i;
21.2603 + if (j == pq->count - 1)
21.2604 + index[j].flags = 0x80;
21.2605 + j++;
21.2606 + }
21.2607 +
21.2608 + free(pq);
21.2609 +
21.2610 + pi = razor_package_iterator_create_with_index(set, index);
21.2611 + pi->free_index = 1;
21.2612 +
21.2613 + return pi;
21.2614 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/librazor/razor.h Mon Jun 16 15:40:30 2008 -0400
22.3 @@ -0,0 +1,189 @@
22.4 +/*
22.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
22.6 + * Copyright (C) 2008 Red Hat, Inc
22.7 + *
22.8 + * This program is free software; you can redistribute it and/or modify
22.9 + * it under the terms of the GNU General Public License as published by
22.10 + * the Free Software Foundation; either version 2 of the License, or
22.11 + * (at your option) any later version.
22.12 + *
22.13 + * This program is distributed in the hope that it will be useful,
22.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22.16 + * GNU General Public License for more details.
22.17 + *
22.18 + * You should have received a copy of the GNU General Public License along
22.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
22.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22.21 + */
22.22 +
22.23 +#ifndef _RAZOR_H_
22.24 +#define _RAZOR_H_
22.25 +
22.26 +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
22.27 +
22.28 +struct razor_set;
22.29 +struct razor_package;
22.30 +struct razor_property;
22.31 +
22.32 +enum razor_property_type {
22.33 + RAZOR_PROPERTY_REQUIRES,
22.34 + RAZOR_PROPERTY_PROVIDES,
22.35 + RAZOR_PROPERTY_CONFLICTS,
22.36 + RAZOR_PROPERTY_OBSOLETES
22.37 +};
22.38 +
22.39 +enum razor_version_relation {
22.40 + RAZOR_VERSION_LESS,
22.41 + RAZOR_VERSION_LESS_OR_EQUAL,
22.42 + RAZOR_VERSION_EQUAL,
22.43 + RAZOR_VERSION_GREATER_OR_EQUAL,
22.44 + RAZOR_VERSION_GREATER
22.45 +};
22.46 +extern const char * const razor_version_relations[];
22.47 +
22.48 +struct razor_set *razor_set_create(void);
22.49 +struct razor_set *razor_set_open(const char *filename);
22.50 +void razor_set_destroy(struct razor_set *set);
22.51 +int razor_set_write_to_fd(struct razor_set *set, int fd);
22.52 +int razor_set_write(struct razor_set *set, const char *filename);
22.53 +
22.54 +struct razor_package *
22.55 +razor_set_get_package(struct razor_set *set, const char *package);
22.56 +
22.57 +struct razor_package_iterator;
22.58 +struct razor_package_iterator *
22.59 +razor_package_iterator_create(struct razor_set *set);
22.60 +struct razor_package_iterator *
22.61 +razor_package_iterator_create_for_property(struct razor_set *set,
22.62 + struct razor_property *property);
22.63 +struct razor_package_iterator *
22.64 +razor_package_iterator_create_for_file(struct razor_set *set,
22.65 + const char *filename);
22.66 +
22.67 +int razor_package_iterator_next(struct razor_package_iterator *pi,
22.68 + struct razor_package **package,
22.69 + const char **name,
22.70 + const char **version,
22.71 + const char **arch);
22.72 +void razor_package_iterator_destroy(struct razor_package_iterator *pi);
22.73 +
22.74 +struct razor_package_query *
22.75 +razor_package_query_create(struct razor_set *set);
22.76 +void
22.77 +razor_package_query_add_package(struct razor_package_query *pq,
22.78 + struct razor_package *p);
22.79 +void
22.80 +razor_package_query_add_iterator(struct razor_package_query *pq,
22.81 + struct razor_package_iterator *pi);
22.82 +struct razor_package_iterator *
22.83 +razor_package_query_finish(struct razor_package_query *pq);
22.84 +
22.85 +struct razor_property_iterator;
22.86 +struct razor_property_iterator *
22.87 +razor_property_iterator_create(struct razor_set *set,
22.88 + struct razor_package *package);
22.89 +int razor_property_iterator_next(struct razor_property_iterator *pi,
22.90 + struct razor_property **property,
22.91 + const char **name,
22.92 + enum razor_version_relation *relation,
22.93 + const char **version,
22.94 + enum razor_property_type *type);
22.95 +void
22.96 +razor_property_iterator_destroy(struct razor_property_iterator *pi);
22.97 +
22.98 +void razor_set_list_files(struct razor_set *set, const char *prefix);
22.99 +void razor_set_list_package_files(struct razor_set *set, const char *name);
22.100 +
22.101 +void razor_set_list_unsatisfied(struct razor_set *set);
22.102 +
22.103 +typedef void (*razor_package_callback_t)(const char *name,
22.104 + const char *old_version,
22.105 + const char *new_version,
22.106 + const char *arch,
22.107 + void *data);
22.108 +void
22.109 +razor_set_diff(struct razor_set *set, struct razor_set *upstream,
22.110 + razor_package_callback_t callback, void *data);
22.111 +
22.112 +/* Package transactions */
22.113 +
22.114 +struct razor_transaction *
22.115 +razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
22.116 +void razor_transaction_install_package(struct razor_transaction *transaction,
22.117 + struct razor_package *package);
22.118 +void razor_transaction_remove_package(struct razor_transaction *transaction,
22.119 + struct razor_package *package);
22.120 +void razor_transaction_update_package(struct razor_transaction *trans,
22.121 + struct razor_package *package);
22.122 +void razor_transaction_update_all(struct razor_transaction *transaction);
22.123 +int razor_transaction_resolve(struct razor_transaction *trans);
22.124 +int razor_transaction_describe(struct razor_transaction *trans);
22.125 +struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
22.126 +void razor_transaction_destroy(struct razor_transaction *trans);
22.127 +
22.128 +/* Temporary helper for test suite. */
22.129 +int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
22.130 + const char *name,
22.131 + enum razor_version_relation rel,
22.132 + const char *version,
22.133 + enum razor_property_type type);
22.134 +
22.135 +/* Importer interface; for building a razor set from external sources,
22.136 + * like yum, rpmdb or razor package files. */
22.137 +
22.138 +struct razor_importer;
22.139 +struct razor_rpm;
22.140 +
22.141 +struct razor_importer *razor_importer_new(void);
22.142 +void razor_importer_destroy(struct razor_importer *importer);
22.143 +void razor_importer_begin_package(struct razor_importer *importer,
22.144 + const char *name,
22.145 + const char *version,
22.146 + const char *arch);
22.147 +void razor_importer_add_property(struct razor_importer *importer,
22.148 + const char *name,
22.149 + enum razor_version_relation relation,
22.150 + const char *version,
22.151 + enum razor_property_type type);
22.152 +void razor_importer_add_file(struct razor_importer *importer,
22.153 + const char *name);
22.154 +void razor_importer_finish_package(struct razor_importer *importer);
22.155 +
22.156 +int razor_importer_add_rpm(struct razor_importer *importer,
22.157 + struct razor_rpm *rpm);
22.158 +
22.159 +struct razor_set *razor_importer_finish(struct razor_importer *importer);
22.160 +
22.161 +void razor_build_evr(char *evr_buf, int size, const char *epoch,
22.162 + const char *version, const char *release);
22.163 +
22.164 +struct razor_set *razor_set_create_from_yum(void);
22.165 +struct razor_set *razor_set_create_from_rpmdb(void);
22.166 +
22.167 +/* RPM functions */
22.168 +
22.169 +struct razor_rpm *razor_rpm_open(const char *filename);
22.170 +int razor_rpm_install(struct razor_rpm *rpm, const char *root);
22.171 +int razor_rpm_close(struct razor_rpm *rpm);
22.172 +
22.173 +
22.174 +/* Razor root functions. The root data struct encapsulates filesystem
22.175 + * conventions and the locking protocol. */
22.176 +
22.177 +struct razor_root;
22.178 +#define RAZOR_ROOT_OPEN_WRITE 0x01
22.179 +
22.180 +int razor_root_create(const char *root);
22.181 +struct razor_root *razor_root_open(const char *root, int flags);
22.182 +struct razor_set *razor_root_open_read_only(const char *root);
22.183 +struct razor_transaction *
22.184 +razor_root_create_transaction(struct razor_root *image,
22.185 + struct razor_set *upstream);
22.186 +int razor_root_close(struct razor_root *image);
22.187 +void razor_root_update(struct razor_root *image, struct razor_set *next);
22.188 +int razor_root_commit(struct razor_root *image);
22.189 +void razor_root_diff(struct razor_root *root,
22.190 + razor_package_callback_t callback, void *data);
22.191 +
22.192 +#endif /* _RAZOR_H_ */
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/librazor/rpm.c Mon Jun 16 15:40:30 2008 -0400
23.3 @@ -0,0 +1,813 @@
23.4 +/*
23.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
23.6 + * Copyright (C) 2008 Red Hat, Inc
23.7 + *
23.8 + * This program is free software; you can redistribute it and/or modify
23.9 + * it under the terms of the GNU General Public License as published by
23.10 + * the Free Software Foundation; either version 2 of the License, or
23.11 + * (at your option) any later version.
23.12 + *
23.13 + * This program is distributed in the hope that it will be useful,
23.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.16 + * GNU General Public License for more details.
23.17 + *
23.18 + * You should have received a copy of the GNU General Public License along
23.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
23.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23.21 + */
23.22 +
23.23 +#include <stdio.h>
23.24 +#include <stddef.h>
23.25 +#include <stdlib.h>
23.26 +#include <string.h>
23.27 +#include <errno.h>
23.28 +#include <sys/stat.h>
23.29 +#include <sys/mman.h>
23.30 +#include <sys/types.h>
23.31 +#include <sys/wait.h>
23.32 +#include <fcntl.h>
23.33 +#include <dirent.h>
23.34 +#include <unistd.h>
23.35 +#include <arpa/inet.h>
23.36 +#include <zlib.h>
23.37 +
23.38 +#include "razor.h"
23.39 +#include "razor-internal.h"
23.40 +
23.41 +#define RPM_LEAD_SIZE 96
23.42 +
23.43 +enum {
23.44 + PIPE = 1, /*!< pipe/fifo */
23.45 + CDEV = 2, /*!< character device */
23.46 + XDIR = 4, /*!< directory */
23.47 + BDEV = 6, /*!< block device */
23.48 + REG = 8, /*!< regular file */
23.49 + LINK = 10, /*!< hard link */
23.50 + SOCK = 12 /*!< socket */
23.51 +};
23.52 +
23.53 +enum {
23.54 + RPMSENSE_LESS = (1 << 1),
23.55 + RPMSENSE_GREATER = (1 << 2),
23.56 + RPMSENSE_EQUAL = (1 << 3),
23.57 +};
23.58 +
23.59 +enum {
23.60 + RPMTAG_NAME = 1000, /* s */
23.61 + RPMTAG_VERSION = 1001, /* s */
23.62 + RPMTAG_RELEASE = 1002, /* s */
23.63 + RPMTAG_EPOCH = 1003, /* i */
23.64 + RPMTAG_SUMMARY = 1004, /* s{} */
23.65 + RPMTAG_DESCRIPTION = 1005, /* s{} */
23.66 + RPMTAG_BUILDTIME = 1006, /* i */
23.67 + RPMTAG_BUILDHOST = 1007, /* s */
23.68 + RPMTAG_INSTALLTIME = 1008, /* i */
23.69 + RPMTAG_SIZE = 1009, /* i */
23.70 + RPMTAG_DISTRIBUTION = 1010, /* s */
23.71 + RPMTAG_VENDOR = 1011, /* s */
23.72 + RPMTAG_GIF = 1012, /* x */
23.73 + RPMTAG_XPM = 1013, /* x */
23.74 + RPMTAG_LICENSE = 1014, /* s */
23.75 + RPMTAG_PACKAGER = 1015, /* s */
23.76 + RPMTAG_GROUP = 1016, /* s{} */
23.77 + RPMTAG_CHANGELOG = 1017, /*!< s[] internal */
23.78 + RPMTAG_SOURCE = 1018, /* s[] */
23.79 + RPMTAG_PATCH = 1019, /* s[] */
23.80 + RPMTAG_URL = 1020, /* s */
23.81 + RPMTAG_OS = 1021, /* s legacy used int */
23.82 + RPMTAG_ARCH = 1022, /* s legacy used int */
23.83 + RPMTAG_PREIN = 1023, /* s */
23.84 + RPMTAG_POSTIN = 1024, /* s */
23.85 + RPMTAG_PREUN = 1025, /* s */
23.86 + RPMTAG_POSTUN = 1026, /* s */
23.87 + RPMTAG_OLDFILENAMES = 1027, /* s[] obsolete */
23.88 + RPMTAG_FILESIZES = 1028, /* i */
23.89 + RPMTAG_FILESTATES = 1029, /* c */
23.90 + RPMTAG_FILEMODES = 1030, /* h */
23.91 + RPMTAG_FILEUIDS = 1031, /*!< internal */
23.92 + RPMTAG_FILEGIDS = 1032, /*!< internal */
23.93 + RPMTAG_FILERDEVS = 1033, /* h */
23.94 + RPMTAG_FILEMTIMES = 1034, /* i */
23.95 + RPMTAG_FILEMD5S = 1035, /* s[] */
23.96 + RPMTAG_FILELINKTOS = 1036, /* s[] */
23.97 + RPMTAG_FILEFLAGS = 1037, /* i */
23.98 + RPMTAG_ROOT = 1038, /*!< internal - obsolete */
23.99 + RPMTAG_FILEUSERNAME = 1039, /* s[] */
23.100 + RPMTAG_FILEGROUPNAME = 1040, /* s[] */
23.101 + RPMTAG_EXCLUDE = 1041, /*!< internal - obsolete */
23.102 + RPMTAG_EXCLUSIVE = 1042, /*!< internal - obsolete */
23.103 + RPMTAG_ICON = 1043,
23.104 + RPMTAG_SOURCERPM = 1044, /* s */
23.105 + RPMTAG_FILEVERIFYFLAGS = 1045, /* i */
23.106 + RPMTAG_ARCHIVESIZE = 1046, /* i */
23.107 + RPMTAG_PROVIDENAME = 1047, /* s[] */
23.108 + RPMTAG_REQUIREFLAGS = 1048, /* i */
23.109 + RPMTAG_REQUIRENAME = 1049, /* s[] */
23.110 + RPMTAG_REQUIREVERSION = 1050, /* s[] */
23.111 + RPMTAG_NOSOURCE = 1051, /*!< internal */
23.112 + RPMTAG_NOPATCH = 1052, /*!< internal */
23.113 + RPMTAG_CONFLICTFLAGS = 1053, /* i */
23.114 + RPMTAG_CONFLICTNAME = 1054, /* s[] */
23.115 + RPMTAG_CONFLICTVERSION = 1055, /* s[] */
23.116 + RPMTAG_DEFAULTPREFIX = 1056, /*!< internal - deprecated */
23.117 + RPMTAG_BUILDROOT = 1057, /*!< internal */
23.118 + RPMTAG_INSTALLPREFIX = 1058, /*!< internal - deprecated */
23.119 + RPMTAG_EXCLUDEARCH = 1059,
23.120 + RPMTAG_EXCLUDEOS = 1060,
23.121 + RPMTAG_EXCLUSIVEARCH = 1061,
23.122 + RPMTAG_EXCLUSIVEOS = 1062,
23.123 + RPMTAG_AUTOREQPROV = 1063, /*!< internal */
23.124 + RPMTAG_RPMVERSION = 1064, /* s */
23.125 + RPMTAG_TRIGGERSCRIPTS = 1065, /* s[] */
23.126 + RPMTAG_TRIGGERNAME = 1066, /* s[] */
23.127 + RPMTAG_TRIGGERVERSION = 1067, /* s[] */
23.128 + RPMTAG_TRIGGERFLAGS = 1068, /* i */
23.129 + RPMTAG_TRIGGERINDEX = 1069, /* i */
23.130 + RPMTAG_VERIFYSCRIPT = 1079, /* s */
23.131 + RPMTAG_CHANGELOGTIME = 1080, /* i */
23.132 + RPMTAG_CHANGELOGNAME = 1081, /* s[] */
23.133 + RPMTAG_CHANGELOGTEXT = 1082, /* s[] */
23.134 + RPMTAG_BROKENMD5 = 1083, /*!< internal - obsolete */
23.135 + RPMTAG_PREREQ = 1084, /*!< internal */
23.136 + RPMTAG_PREINPROG = 1085, /* s */
23.137 + RPMTAG_POSTINPROG = 1086, /* s */
23.138 + RPMTAG_PREUNPROG = 1087, /* s */
23.139 + RPMTAG_POSTUNPROG = 1088, /* s */
23.140 + RPMTAG_BUILDARCHS = 1089,
23.141 + RPMTAG_OBSOLETENAME = 1090, /* s[] */
23.142 + RPMTAG_VERIFYSCRIPTPROG = 1091, /* s */
23.143 + RPMTAG_TRIGGERSCRIPTPROG = 1092, /* s */
23.144 + RPMTAG_DOCDIR = 1093, /*!< internal */
23.145 + RPMTAG_COOKIE = 1094, /* s */
23.146 + RPMTAG_FILEDEVICES = 1095, /* i */
23.147 + RPMTAG_FILEINODES = 1096, /* i */
23.148 + RPMTAG_FILELANGS = 1097, /* s[] */
23.149 + RPMTAG_PREFIXES = 1098, /* s[] */
23.150 + RPMTAG_INSTPREFIXES = 1099, /* s[] */
23.151 + RPMTAG_TRIGGERIN = 1100, /*!< internal */
23.152 + RPMTAG_TRIGGERUN = 1101, /*!< internal */
23.153 + RPMTAG_TRIGGERPOSTUN = 1102, /*!< internal */
23.154 + RPMTAG_AUTOREQ = 1103, /*!< internal */
23.155 + RPMTAG_AUTOPROV = 1104, /*!< internal */
23.156 + RPMTAG_CAPABILITY = 1105, /*!< internal - obsolete */
23.157 + RPMTAG_SOURCEPACKAGE = 1106, /*!< i src.rpm header marker */
23.158 + RPMTAG_OLDORIGFILENAMES = 1107, /*!< internal - obsolete */
23.159 + RPMTAG_BUILDPREREQ = 1108, /*!< internal */
23.160 + RPMTAG_BUILDREQUIRES = 1109, /*!< internal */
23.161 + RPMTAG_BUILDCONFLICTS = 1110, /*!< internal */
23.162 + RPMTAG_BUILDMACROS = 1111, /*!< internal - unused */
23.163 + RPMTAG_PROVIDEFLAGS = 1112, /* i */
23.164 + RPMTAG_PROVIDEVERSION = 1113, /* s[] */
23.165 + RPMTAG_OBSOLETEFLAGS = 1114, /* i */
23.166 + RPMTAG_OBSOLETEVERSION = 1115, /* s[] */
23.167 + RPMTAG_DIRINDEXES = 1116, /* i */
23.168 + RPMTAG_BASENAMES = 1117, /* s[] */
23.169 + RPMTAG_DIRNAMES = 1118, /* s[] */
23.170 + RPMTAG_ORIGDIRINDEXES = 1119, /*!< internal */
23.171 + RPMTAG_ORIGBASENAMES = 1120, /*!< internal */
23.172 + RPMTAG_ORIGDIRNAMES = 1121, /*!< internal */
23.173 + RPMTAG_OPTFLAGS = 1122, /* s */
23.174 + RPMTAG_DISTURL = 1123, /* s */
23.175 + RPMTAG_PAYLOADFORMAT = 1124, /* s */
23.176 + RPMTAG_PAYLOADCOMPRESSOR = 1125, /* s */
23.177 + RPMTAG_PAYLOADFLAGS = 1126, /* s */
23.178 + RPMTAG_INSTALLCOLOR = 1127, /*!< i transaction color when installed */
23.179 + RPMTAG_INSTALLTID = 1128, /* i */
23.180 + RPMTAG_REMOVETID = 1129, /* i */
23.181 + RPMTAG_SHA1RHN = 1130, /*!< internal - obsolete */
23.182 + RPMTAG_RHNPLATFORM = 1131, /* s */
23.183 + RPMTAG_PLATFORM = 1132, /* s */
23.184 + RPMTAG_PATCHESNAME = 1133, /*!< placeholder (SuSE) */
23.185 + RPMTAG_PATCHESFLAGS = 1134, /*!< placeholder (SuSE) */
23.186 + RPMTAG_PATCHESVERSION = 1135, /*!< placeholder (SuSE) */
23.187 + RPMTAG_CACHECTIME = 1136, /* i */
23.188 + RPMTAG_CACHEPKGPATH = 1137, /* s */
23.189 + RPMTAG_CACHEPKGSIZE = 1138, /* i */
23.190 + RPMTAG_CACHEPKGMTIME = 1139, /* i */
23.191 + RPMTAG_FILECOLORS = 1140, /* i */
23.192 + RPMTAG_FILECLASS = 1141, /* i */
23.193 + RPMTAG_CLASSDICT = 1142, /* s[] */
23.194 + RPMTAG_FILEDEPENDSX = 1143, /* i */
23.195 + RPMTAG_FILEDEPENDSN = 1144, /* i */
23.196 + RPMTAG_DEPENDSDICT = 1145, /* i */
23.197 + RPMTAG_SOURCEPKGID = 1146, /* x */
23.198 + RPMTAG_FILECONTEXTS = 1147, /* s[] */
23.199 + RPMTAG_FSCONTEXTS = 1148, /*!< s[] extension */
23.200 + RPMTAG_RECONTEXTS = 1149, /*!< s[] extension */
23.201 + RPMTAG_POLICIES = 1150, /*!< s[] selinux *.te policy file. */
23.202 + RPMTAG_PRETRANS = 1151, /* s */
23.203 + RPMTAG_POSTTRANS = 1152, /* s */
23.204 + RPMTAG_PRETRANSPROG = 1153, /* s */
23.205 + RPMTAG_POSTTRANSPROG = 1154, /* s */
23.206 + RPMTAG_DISTTAG = 1155, /* s */
23.207 + RPMTAG_SUGGESTSNAME = 1156, /* s[] extension placeholder */
23.208 + RPMTAG_SUGGESTSVERSION = 1157, /* s[] extension placeholder */
23.209 + RPMTAG_SUGGESTSFLAGS = 1158, /* i extension placeholder */
23.210 + RPMTAG_ENHANCESNAME = 1159, /* s[] extension placeholder */
23.211 + RPMTAG_ENHANCESVERSION = 1160, /* s[] extension placeholder */
23.212 + RPMTAG_ENHANCESFLAGS = 1161, /* i extension placeholder */
23.213 + RPMTAG_PRIORITY = 1162, /* i extension placeholder */
23.214 + RPMTAG_CVSID = 1163, /* s */
23.215 + RPMTAG_TRIGGERPREIN = 1171, /*!< internal */
23.216 +};
23.217 +
23.218 +struct rpm_header {
23.219 + unsigned char magic[4];
23.220 + unsigned char reserved[4];
23.221 + int nindex;
23.222 + int hsize;
23.223 +};
23.224 +
23.225 +struct rpm_header_index {
23.226 + int tag;
23.227 + int type;
23.228 + int offset;
23.229 + int count;
23.230 +};
23.231 +
23.232 +struct razor_rpm {
23.233 + struct rpm_header *signature;
23.234 + struct rpm_header *header;
23.235 + const char **dirs;
23.236 + const char *pool;
23.237 + void *map;
23.238 + size_t size;
23.239 + void *payload;
23.240 +};
23.241 +
23.242 +static struct rpm_header_index *
23.243 +razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
23.244 +{
23.245 + struct rpm_header_index *index, *end;
23.246 +
23.247 + index = (struct rpm_header_index *) (rpm->header + 1);
23.248 + end = index + ntohl(rpm->header->nindex);
23.249 + while (index < end) {
23.250 + if (ntohl(index->tag) == tag)
23.251 + return index;
23.252 + index++;
23.253 + }
23.254 +
23.255 + return NULL;
23.256 +}
23.257 +
23.258 +static const void *
23.259 +razor_rpm_get_indirect(struct razor_rpm *rpm,
23.260 + unsigned int tag, unsigned int *count)
23.261 +{
23.262 + struct rpm_header_index *index;
23.263 +
23.264 + index = razor_rpm_get_header(rpm, tag);
23.265 + if (index != NULL) {
23.266 + if (count)
23.267 + *count = ntohl(index->count);
23.268 +
23.269 + return rpm->pool + ntohl(index->offset);
23.270 + }
23.271 +
23.272 + return NULL;
23.273 +}
23.274 +
23.275 +static enum razor_version_relation
23.276 +rpm_to_razor_flags(uint32_t flags)
23.277 +{
23.278 + switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
23.279 + case RPMSENSE_LESS:
23.280 + return RAZOR_VERSION_LESS;
23.281 + case RPMSENSE_LESS|RPMSENSE_EQUAL:
23.282 + return RAZOR_VERSION_LESS_OR_EQUAL;
23.283 + case RPMSENSE_EQUAL:
23.284 + return RAZOR_VERSION_EQUAL;
23.285 + case RPMSENSE_GREATER|RPMSENSE_EQUAL:
23.286 + return RAZOR_VERSION_GREATER_OR_EQUAL;
23.287 + case RPMSENSE_GREATER:
23.288 + return RAZOR_VERSION_GREATER;
23.289 + }
23.290 +
23.291 + /* FIXME? */
23.292 + return RAZOR_VERSION_EQUAL;
23.293 +}
23.294 +
23.295 +static void
23.296 +import_properties(struct razor_importer *importer, unsigned long type,
23.297 + struct razor_rpm *rpm,
23.298 + int name_tag, int version_tag, int flags_tag)
23.299 +{
23.300 + const char *name, *version;
23.301 + const uint32_t *flags;
23.302 + uint32_t f;
23.303 + unsigned int i, count;
23.304 +
23.305 + name = razor_rpm_get_indirect(rpm, name_tag, &count);
23.306 + if (name == NULL)
23.307 + return;
23.308 +
23.309 + flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
23.310 +
23.311 + version = razor_rpm_get_indirect(rpm, version_tag, &count);
23.312 + for (i = 0; i < count; i++) {
23.313 + f = rpm_to_razor_flags(ntohl(flags[i]));
23.314 + razor_importer_add_property(importer, name, f, version, type);
23.315 + name += strlen(name) + 1;
23.316 + version += strlen(version) + 1;
23.317 + }
23.318 +}
23.319 +
23.320 +static void
23.321 +import_files(struct razor_importer *importer, struct razor_rpm *rpm)
23.322 +{
23.323 + const char *name;
23.324 + const uint32_t *index;
23.325 + unsigned int i, count;
23.326 + char buffer[256];
23.327 +
23.328 + /* assert: count is the same for all arrays */
23.329 +
23.330 + index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
23.331 + name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
23.332 + for (i = 0; i < count; i++) {
23.333 + snprintf(buffer, sizeof buffer,
23.334 + "%s%s", rpm->dirs[ntohl(*index)], name);
23.335 + razor_importer_add_file(importer, buffer);
23.336 + name += strlen(name) + 1;
23.337 + index++;
23.338 + }
23.339 +}
23.340 +
23.341 +struct razor_rpm *
23.342 +razor_rpm_open(const char *filename)
23.343 +{
23.344 + struct razor_rpm *rpm;
23.345 + struct rpm_header_index *base, *index;
23.346 + struct stat buf;
23.347 + unsigned int count, i, nindex, hsize;
23.348 + const char *name;
23.349 + int fd;
23.350 +
23.351 + rpm = malloc(sizeof *rpm);
23.352 + memset(rpm, 0, sizeof *rpm);
23.353 +
23.354 + fd = open(filename, O_RDONLY);
23.355 + if (fd < 0) {
23.356 + fprintf(stderr, "couldn't open %s\n", filename);
23.357 + return NULL;
23.358 + }
23.359 +
23.360 + if (fstat(fd, &buf) < 0) {
23.361 + fprintf(stderr, "failed to stat %s (%m)\n", filename);
23.362 + return NULL;
23.363 + }
23.364 +
23.365 + rpm->size = buf.st_size;
23.366 + rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
23.367 + if (rpm->map == MAP_FAILED) {
23.368 + fprintf(stderr, "couldn't mmap %s\n", filename);
23.369 + return NULL;
23.370 + }
23.371 + close(fd);
23.372 +
23.373 + rpm->signature = rpm->map + RPM_LEAD_SIZE;
23.374 + nindex = ntohl(rpm->signature->nindex);
23.375 + hsize = ntohl(rpm->signature->hsize);
23.376 + rpm->header = (void *) (rpm->signature + 1) +
23.377 + ALIGN(nindex * sizeof *index + hsize, 8);
23.378 + nindex = ntohl(rpm->header->nindex);
23.379 + hsize = ntohl(rpm->header->hsize);
23.380 + rpm->payload = (void *) (rpm->header + 1) +
23.381 + nindex * sizeof *index + hsize;
23.382 +
23.383 + base = (struct rpm_header_index *) (rpm->header + 1);
23.384 + rpm->pool = (void *) base + nindex * sizeof *index;
23.385 +
23.386 + /* Look up dir names now so we can index them directly. */
23.387 + name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
23.388 + if (name) {
23.389 + rpm->dirs = calloc(count, sizeof *rpm->dirs);
23.390 + for (i = 0; i < count; i++) {
23.391 + rpm->dirs[i] = name;
23.392 + name += strlen(name) + 1;
23.393 + }
23.394 + } else {
23.395 + name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
23.396 + &count);
23.397 + if (name) {
23.398 + fprintf(stderr, "old filenames not supported\n");
23.399 + return NULL;
23.400 + }
23.401 + }
23.402 +
23.403 + return rpm;
23.404 +}
23.405 +
23.406 +struct cpio_file_header {
23.407 + char magic[6];
23.408 + char inode[8];
23.409 + char mode[8];
23.410 + char uid[8];
23.411 + char gid[8];
23.412 + char nlink[8];
23.413 + char mtime[8];
23.414 + char filesize[8];
23.415 + char devmajor[8];
23.416 + char devminor[8];
23.417 + char rdevmajor[8];
23.418 + char rdevminor[8];
23.419 + char namesize[8];
23.420 + char checksum[8];
23.421 + char filename[0];
23.422 +};
23.423 +
23.424 +/* gzip flags */
23.425 +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
23.426 +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
23.427 +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
23.428 +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
23.429 +#define COMMENT 0x10 /* bit 4 set: file comment present */
23.430 +#define RESERVED 0xE0 /* bits 5..7: reserved */
23.431 +
23.432 +struct installer {
23.433 + const char *root;
23.434 + struct razor_rpm *rpm;
23.435 + z_stream stream;
23.436 + unsigned char buffer[32768];
23.437 + size_t rest, length;
23.438 +};
23.439 +
23.440 +static int
23.441 +installer_inflate(struct installer *installer)
23.442 +{
23.443 + size_t length;
23.444 + int err;
23.445 +
23.446 + if (installer->rest > sizeof installer->buffer)
23.447 + length = sizeof installer->buffer;
23.448 + else
23.449 + length = installer->rest;
23.450 +
23.451 + installer->stream.next_out = installer->buffer;
23.452 + installer->stream.avail_out = length;
23.453 + err = inflate(&installer->stream, Z_SYNC_FLUSH);
23.454 + if (err != Z_OK && err != Z_STREAM_END) {
23.455 + fprintf(stderr, "inflate error: %d (%m)\n", err);
23.456 + return -1;
23.457 + }
23.458 +
23.459 + installer->rest -= length;
23.460 + installer->length = length;
23.461 +
23.462 + return 0;
23.463 +}
23.464 +
23.465 +static int
23.466 +installer_align(struct installer *installer, size_t size)
23.467 +{
23.468 + unsigned char buffer[4];
23.469 + int err;
23.470 +
23.471 + installer->stream.next_out = buffer;
23.472 + installer->stream.avail_out =
23.473 + (size - installer->stream.total_out) & (size - 1);
23.474 +
23.475 + if (installer->stream.avail_out == 0)
23.476 + return 0;
23.477 +
23.478 + err = inflate(&installer->stream, Z_SYNC_FLUSH);
23.479 + if (err != Z_OK && err != Z_STREAM_END) {
23.480 + fprintf(stderr, "inflate error: %d (%m)\n", err);
23.481 + return -1;
23.482 + }
23.483 +
23.484 + return 0;
23.485 +}
23.486 +
23.487 +static int
23.488 +create_path(struct installer *installer, const char *path, unsigned int mode)
23.489 +{
23.490 + char buffer[PATH_MAX];
23.491 + struct stat buf;
23.492 + int fd, ret;
23.493 +
23.494 + if (razor_create_dir(installer->root, path) < 0)
23.495 + return -1;
23.496 +
23.497 + snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
23.498 +
23.499 + switch (mode >> 12) {
23.500 + case REG:
23.501 + /* FIXME: handle the case where a file is already there. */
23.502 + fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, mode & 0x1ff);
23.503 + if (fd < 0){
23.504 + fprintf(stderr, "failed to create file %s\n", buffer);
23.505 + return -1;
23.506 + }
23.507 + while (installer->rest > 0) {
23.508 + if (installer_inflate(installer)) {
23.509 + fprintf(stderr, "failed to inflate\n");
23.510 + return -1;
23.511 + }
23.512 + if (razor_write(fd, installer->buffer,
23.513 + installer->length)) {
23.514 + fprintf(stderr, "failed to write payload\n");
23.515 + return -1;
23.516 + }
23.517 + }
23.518 + if (close(fd) < 0) {
23.519 + fprintf(stderr, "failed to close %s: %m\n", buffer);
23.520 + return -1;
23.521 + }
23.522 + return 0;
23.523 + case XDIR:
23.524 + ret = mkdir(buffer, mode & 0x1ff);
23.525 + if (ret == 0 || errno != EEXIST)
23.526 + return ret;
23.527 + if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
23.528 + /* FIXME: also check that mode match. */
23.529 + fprintf(stderr,
23.530 + "%s exists but is not a directory\n", buffer);
23.531 + return -1;
23.532 + }
23.533 + return 0;
23.534 + case PIPE:
23.535 + case CDEV:
23.536 + case BDEV:
23.537 + case SOCK:
23.538 + printf("%s: unhandled file type %d\n", buffer, mode >> 12);
23.539 + return 0;
23.540 + case LINK:
23.541 + if (installer_inflate(installer)) {
23.542 + fprintf(stderr, "failed to inflate\n");
23.543 + return -1;
23.544 + }
23.545 + if (installer->length >= sizeof installer->buffer) {
23.546 + fprintf(stderr, "link name too long\n");
23.547 + return -1;
23.548 + }
23.549 + installer->buffer[installer->length] = '\0';
23.550 + if (symlink((const char *) installer->buffer, buffer)) {
23.551 + fprintf(stderr, "failed to create symlink, %m\n");
23.552 + return -1;
23.553 + }
23.554 + return 0;
23.555 + default:
23.556 + printf("%s: unknown file type %d\n", buffer, mode >> 12);
23.557 + return 0;
23.558 + }
23.559 +}
23.560 +
23.561 +static int
23.562 +run_script(struct installer *installer,
23.563 + unsigned int program_tag, unsigned int script_tag)
23.564 +{
23.565 + int pid, status, fd[2];
23.566 + const char *script = NULL, *program = NULL;
23.567 +
23.568 + program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
23.569 + script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
23.570 + if (program == NULL && script == NULL) {
23.571 + return 0;
23.572 + } else if (program == NULL) {
23.573 + program = "/bin/sh";
23.574 + }
23.575 +
23.576 + if (pipe(fd) < 0) {
23.577 + fprintf(stderr, "failed to create pipe\n");
23.578 + return -1;
23.579 + }
23.580 + pid = fork();
23.581 + if (pid < 0) {
23.582 + fprintf(stderr, "failed to fork, %m\n");
23.583 + } else if (pid == 0) {
23.584 + if (dup2(fd[0], STDIN_FILENO) < 0) {
23.585 + fprintf(stderr, "failed redirect stdin, %m\n");
23.586 + return -1;
23.587 + }
23.588 + if (close(fd[0]) < 0 || close(fd[1]) < 0) {
23.589 + fprintf(stderr, "failed to close pipe, %m\n");
23.590 + return -1;
23.591 + }
23.592 + if (chroot(installer->root) < 0) {
23.593 + fprintf(stderr, "failed to chroot to %s, %m\n",
23.594 + installer->root);
23.595 + return -1;
23.596 + }
23.597 + printf("executing program %s in chroot %s\n",
23.598 + program, installer->root);
23.599 + if (execl(program, program, NULL)) {
23.600 + fprintf(stderr, "failed to exec %s, %m\n", program);
23.601 + exit(-1);
23.602 + }
23.603 + } else {
23.604 + if (script && razor_write(fd[1], script, strlen(script)) < 0) {
23.605 + fprintf(stderr, "failed to pipe script, %m\n");
23.606 + return -1;
23.607 + }
23.608 + if (close(fd[0]) || close(fd[1])) {
23.609 + fprintf(stderr, "failed to close pipe, %m\n");
23.610 + return -1;
23.611 + }
23.612 + if (wait(&status) < 0) {
23.613 + fprintf(stderr, "wait for child failed, %m");
23.614 + return -1;
23.615 + }
23.616 + if (status)
23.617 + printf("script exited with status %d\n", status);
23.618 + }
23.619 +
23.620 + return 0;
23.621 +}
23.622 +
23.623 +static int
23.624 +installer_init(struct installer *installer)
23.625 +{
23.626 + unsigned char *gz_header;
23.627 + int method, flags, err;
23.628 +
23.629 + gz_header = installer->rpm->payload;
23.630 + if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
23.631 + fprintf(stderr, "payload section doesn't have gz header\n");
23.632 + return -1;
23.633 + }
23.634 +
23.635 + method = gz_header[2];
23.636 + flags = gz_header[3];
23.637 +
23.638 + if (method != Z_DEFLATED || flags != 0) {
23.639 + fprintf(stderr,
23.640 + "unknown payload compression method or flags set\n");
23.641 + return -1;
23.642 + }
23.643 +
23.644 + installer->stream.zalloc = NULL;
23.645 + installer->stream.zfree = NULL;
23.646 + installer->stream.opaque = NULL;
23.647 +
23.648 + installer->stream.next_in = gz_header + 10;
23.649 + installer->stream.avail_in =
23.650 + (installer->rpm->map + installer->rpm->size) -
23.651 + (void *) installer->stream.next_in;
23.652 + installer->stream.next_out = NULL;
23.653 + installer->stream.avail_out = 0;
23.654 +
23.655 + err = inflateInit2(&installer->stream, -MAX_WBITS);
23.656 + if (err != Z_OK) {
23.657 + fprintf(stderr, "inflateInit error: %d\n", err);
23.658 + return -1;
23.659 + }
23.660 +
23.661 + return 0;
23.662 +}
23.663 +
23.664 +static int
23.665 +installer_finish(struct installer *installer)
23.666 +{
23.667 + int err;
23.668 +
23.669 + err = inflateEnd(&installer->stream);
23.670 +
23.671 + if (err != Z_OK) {
23.672 + fprintf(stderr, "inflateEnd error: %d\n", err);
23.673 + return -1;
23.674 + }
23.675 +
23.676 + return 0;
23.677 +}
23.678 +
23.679 +static unsigned long
23.680 +fixed_hex_to_ulong(const char *hex, int length)
23.681 +{
23.682 + long l;
23.683 + int i;
23.684 +
23.685 + for (i = 0, l = 0; i < length; i++) {
23.686 + if (hex[i] < 'a')
23.687 + l = l * 16 + hex[i] - '0';
23.688 + else
23.689 + l = l * 16 + hex[i] - 'a' + 10;
23.690 + }
23.691 +
23.692 + return l;
23.693 +}
23.694 +
23.695 +int
23.696 +razor_rpm_install(struct razor_rpm *rpm, const char *root)
23.697 +{
23.698 + struct installer installer;
23.699 + struct cpio_file_header *header;
23.700 + struct stat buf;
23.701 + unsigned int mode;
23.702 + char *path;
23.703 + size_t filesize;
23.704 +
23.705 + installer.rpm = rpm;
23.706 + installer.root = root;
23.707 +
23.708 + /* FIXME: Only do this before a transaction, not per rpm. */
23.709 + if (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
23.710 + fprintf(stderr,
23.711 + "root installation directory \"%s\" does not exist\n",
23.712 + root);
23.713 + return -1;
23.714 + }
23.715 +
23.716 + if (installer_init(&installer))
23.717 + return -1;
23.718 +
23.719 + run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
23.720 +
23.721 + while (installer.stream.avail_in > 0) {
23.722 + installer.rest = sizeof *header;
23.723 + if (installer_inflate(&installer))
23.724 + return -1;
23.725 +
23.726 + header = (struct cpio_file_header *) installer.buffer;
23.727 + mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
23.728 + filesize = fixed_hex_to_ulong(header->filesize,
23.729 + sizeof header->filesize);
23.730 +
23.731 + installer.rest = fixed_hex_to_ulong(header->namesize,
23.732 + sizeof header->namesize);
23.733 +
23.734 + if (installer_inflate(&installer) ||
23.735 + installer_align(&installer, 4))
23.736 + return -1;
23.737 +
23.738 + path = (char *) installer.buffer;
23.739 + /* This convention is so lame... */
23.740 + if (strcmp(path, "TRAILER!!!") == 0)
23.741 + break;
23.742 +
23.743 + installer.rest = filesize;
23.744 + if (create_path(&installer, path + 1, mode) < 0)
23.745 + return -1;
23.746 + if (installer_align(&installer, 4))
23.747 + return -1;
23.748 + }
23.749 +
23.750 + if (installer_finish(&installer))
23.751 + return -1;
23.752 +
23.753 + run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
23.754 +
23.755 + return 0;
23.756 +}
23.757 +
23.758 +int
23.759 +razor_rpm_close(struct razor_rpm *rpm)
23.760 +{
23.761 + int err;
23.762 +
23.763 + free(rpm->dirs);
23.764 + err = munmap(rpm->map, rpm->size);
23.765 + free(rpm);
23.766 +
23.767 + return err;
23.768 +}
23.769 +
23.770 +int
23.771 +razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
23.772 +{
23.773 + const char *name, *version, *release, *arch;
23.774 + const uint32_t *epoch;
23.775 + char evr[128], buf[16];
23.776 +
23.777 + name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
23.778 + epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
23.779 + version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
23.780 + release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
23.781 + arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
23.782 +
23.783 + if (epoch) {
23.784 + snprintf(buf, sizeof buf, "%u", ntohl(*epoch));
23.785 + razor_build_evr(evr, sizeof evr, buf, version, release);
23.786 + } else {
23.787 + razor_build_evr(evr, sizeof evr, NULL, version, release);
23.788 + }
23.789 + razor_importer_begin_package(importer, name, evr, arch);
23.790 +
23.791 + import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
23.792 + RPMTAG_REQUIRENAME,
23.793 + RPMTAG_REQUIREVERSION,
23.794 + RPMTAG_REQUIREFLAGS);
23.795 +
23.796 + import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
23.797 + RPMTAG_PROVIDENAME,
23.798 + RPMTAG_PROVIDEVERSION,
23.799 + RPMTAG_PROVIDEFLAGS);
23.800 +
23.801 + import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
23.802 + RPMTAG_OBSOLETENAME,
23.803 + RPMTAG_OBSOLETEVERSION,
23.804 + RPMTAG_OBSOLETEFLAGS);
23.805 +
23.806 + import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
23.807 + RPMTAG_CONFLICTNAME,
23.808 + RPMTAG_CONFLICTVERSION,
23.809 + RPMTAG_CONFLICTFLAGS);
23.810 +
23.811 + import_files(importer, rpm);
23.812 +
23.813 + razor_importer_finish_package(importer);
23.814 +
23.815 + return 0;
23.816 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/librazor/types.c Mon Jun 16 15:40:30 2008 -0400
24.3 @@ -0,0 +1,246 @@
24.4 +#include <stdlib.h>
24.5 +#include <string.h>
24.6 +
24.7 +#include "types.h"
24.8 +
24.9 +void
24.10 +array_init(struct array *array)
24.11 +{
24.12 + memset(array, 0, sizeof *array);
24.13 +}
24.14 +
24.15 +void
24.16 +array_release(struct array *array)
24.17 +{
24.18 + free(array->data);
24.19 +}
24.20 +
24.21 +void *
24.22 +array_add(struct array *array, int size)
24.23 +{
24.24 + int alloc;
24.25 + void *data, *p;
24.26 +
24.27 + if (array->alloc > 0)
24.28 + alloc = array->alloc;
24.29 + else
24.30 + alloc = 16;
24.31 +
24.32 + while (alloc < array->size + size)
24.33 + alloc *= 2;
24.34 +
24.35 + if (array->alloc < alloc) {
24.36 + data = realloc(array->data, alloc);
24.37 + if (data == NULL)
24.38 + return 0;
24.39 + array->data = data;
24.40 + array->alloc = alloc;
24.41 + }
24.42 +
24.43 + p = array->data + array->size;
24.44 + array->size += size;
24.45 +
24.46 + return p;
24.47 +}
24.48 +
24.49 +/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
24.50 +#define RAZOR_ENTRY_LAST 0x80
24.51 +#define RAZOR_IMMEDIATE 0x80
24.52 +#define RAZOR_EMPTY_LIST 0xff
24.53 +
24.54 +void
24.55 +list_set_empty(struct list_head *head)
24.56 +{
24.57 + head->list_ptr = ~0;
24.58 + head->flags = RAZOR_EMPTY_LIST;
24.59 +}
24.60 +
24.61 +void
24.62 +list_set_ptr(struct list_head *head, uint32_t ptr)
24.63 +{
24.64 + head->list_ptr = ptr;
24.65 + head->flags = 0;
24.66 +}
24.67 +
24.68 +void
24.69 +list_set_array(struct list_head *head, struct array *pool,
24.70 + struct array *items, int force_indirect)
24.71 +{
24.72 + struct list *p;
24.73 +
24.74 + if (!force_indirect) {
24.75 + if (items->size == 0) {
24.76 + list_set_empty(head);
24.77 + return;
24.78 + } else if (items->size == sizeof (uint32_t)) {
24.79 + head->list_ptr = *(uint32_t *) items->data;
24.80 + head->flags = RAZOR_IMMEDIATE;
24.81 + return;
24.82 + }
24.83 + }
24.84 +
24.85 + p = array_add(pool, items->size);
24.86 + memcpy(p, items->data, items->size);
24.87 + p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
24.88 + list_set_ptr(head, p - (struct list *) pool->data);
24.89 +}
24.90 +
24.91 +struct list *
24.92 +list_first(struct list_head *head, struct array *pool)
24.93 +{
24.94 + if (head->flags == RAZOR_EMPTY_LIST)
24.95 + return NULL;
24.96 + else if (head->flags == RAZOR_IMMEDIATE)
24.97 + return (struct list *) head;
24.98 + else
24.99 + return (struct list *) pool->data + head->list_ptr;
24.100 +}
24.101 +
24.102 +struct list *
24.103 +list_next(struct list *list)
24.104 +{
24.105 + if (list->flags)
24.106 + return NULL;
24.107 + return ++list;
24.108 +}
24.109 +
24.110 +void
24.111 +list_remap_pool(struct array *pool, uint32_t *map)
24.112 +{
24.113 + struct list *p, *end;
24.114 +
24.115 + end = pool->data + pool->size;
24.116 + for (p = pool->data; p < end; p++)
24.117 + p->data = map[p->data];
24.118 +}
24.119 +
24.120 +void
24.121 +list_remap_head(struct list_head *head, uint32_t *map)
24.122 +{
24.123 + if (head->flags == RAZOR_IMMEDIATE)
24.124 + head->list_ptr = map[head->list_ptr];
24.125 +}
24.126 +
24.127 +
24.128 +void
24.129 +hashtable_init(struct hashtable *table, struct array *pool)
24.130 +{
24.131 + array_init(&table->buckets);
24.132 + table->pool = pool;
24.133 +}
24.134 +
24.135 +void
24.136 +hashtable_release(struct hashtable *table)
24.137 +{
24.138 + array_release(&table->buckets);
24.139 +}
24.140 +
24.141 +static unsigned int
24.142 +hash_string(const char *key)
24.143 +{
24.144 + const char *p;
24.145 + unsigned int hash = 0;
24.146 +
24.147 + for (p = key; *p; p++)
24.148 + hash = (hash * 617) ^ *p;
24.149 +
24.150 + return hash;
24.151 +}
24.152 +
24.153 +uint32_t
24.154 +hashtable_lookup(struct hashtable *table, const char *key)
24.155 +{
24.156 + unsigned int mask, start, i;
24.157 + uint32_t *b;
24.158 + char *pool;
24.159 +
24.160 + pool = table->pool->data;
24.161 + mask = table->buckets.alloc - 1;
24.162 + start = hash_string(key) * sizeof(uint32_t);
24.163 +
24.164 + for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
24.165 + b = table->buckets.data + ((start + i) & mask);
24.166 +
24.167 + if (*b == 0)
24.168 + return 0;
24.169 +
24.170 + if (strcmp(key, &pool[*b]) == 0)
24.171 + return *b;
24.172 + }
24.173 +
24.174 + return 0;
24.175 +}
24.176 +
24.177 +static void
24.178 +do_insert(struct hashtable *table, uint32_t value)
24.179 +{
24.180 + unsigned int mask, start, i;
24.181 + uint32_t *b;
24.182 + const char *key;
24.183 +
24.184 + key = (char *) table->pool->data + value;
24.185 + mask = table->buckets.alloc - 1;
24.186 + start = hash_string(key) * sizeof(uint32_t);
24.187 +
24.188 + for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
24.189 + b = table->buckets.data + ((start + i) & mask);
24.190 + if (*b == 0) {
24.191 + *b = value;
24.192 + break;
24.193 + }
24.194 + }
24.195 +}
24.196 +
24.197 +static uint32_t
24.198 +add_to_string_pool(struct hashtable *table, const char *key)
24.199 +{
24.200 + int len;
24.201 + char *p;
24.202 +
24.203 + len = strlen(key) + 1;
24.204 + p = array_add(table->pool, len);
24.205 + memcpy(p, key, len);
24.206 +
24.207 + return p - (char *) table->pool->data;
24.208 +}
24.209 +
24.210 +uint32_t
24.211 +hashtable_insert(struct hashtable *table, const char *key)
24.212 +{
24.213 + uint32_t value, *buckets, *b, *end;
24.214 + int alloc;
24.215 +
24.216 + alloc = table->buckets.alloc;
24.217 + array_add(&table->buckets, 4 * sizeof *buckets);
24.218 + if (alloc != table->buckets.alloc) {
24.219 + end = table->buckets.data + alloc;
24.220 + memset(end, 0, table->buckets.alloc - alloc);
24.221 + for (b = table->buckets.data; b < end; b++) {
24.222 + value = *b;
24.223 + if (value != 0) {
24.224 + *b = 0;
24.225 + do_insert(table, value);
24.226 + }
24.227 + }
24.228 + }
24.229 +
24.230 + value = add_to_string_pool(table, key);
24.231 + do_insert (table, value);
24.232 +
24.233 + return value;
24.234 +}
24.235 +
24.236 +uint32_t
24.237 +hashtable_tokenize(struct hashtable *table, const char *string)
24.238 +{
24.239 + uint32_t token;
24.240 +
24.241 + if (string == NULL)
24.242 + string = "";
24.243 +
24.244 + token = hashtable_lookup(table, string);
24.245 + if (token != 0)
24.246 + return token;
24.247 +
24.248 + return hashtable_insert(table, string);
24.249 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/librazor/types.h Mon Jun 16 15:40:30 2008 -0400
25.3 @@ -0,0 +1,59 @@
25.4 +#ifndef _RAZOR_TYPES_H_
25.5 +#define _RAZOR_TYPES_H_
25.6 +
25.7 +#include <stdint.h>
25.8 +
25.9 +struct array {
25.10 + void *data;
25.11 + int size, alloc;
25.12 +};
25.13 +
25.14 +void array_init(struct array *array);
25.15 +void array_release(struct array *array);
25.16 +void *array_add(struct array *array, int size);
25.17 +
25.18 +
25.19 +struct list_head {
25.20 + uint list_ptr : 24;
25.21 + uint flags : 8;
25.22 +};
25.23 +
25.24 +struct list {
25.25 + uint data : 24;
25.26 + uint flags : 8;
25.27 +};
25.28 +
25.29 +void list_set_empty(struct list_head *head);
25.30 +void list_set_ptr(struct list_head *head, uint32_t ptr);
25.31 +void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
25.32 +
25.33 +struct list *list_first(struct list_head *head, struct array *pool);
25.34 +struct list *list_next(struct list *list);
25.35 +
25.36 +void list_remap_pool(struct array *pool, uint32_t *map);
25.37 +void list_remap_head(struct list_head *list, uint32_t *map);
25.38 +
25.39 +
25.40 +struct hashtable {
25.41 + struct array buckets;
25.42 + struct array *pool;
25.43 +};
25.44 +
25.45 +void hashtable_init(struct hashtable *table, struct array *pool);
25.46 +void hashtable_release(struct hashtable *table);
25.47 +uint32_t hashtable_insert(struct hashtable *table, const char *key);
25.48 +uint32_t hashtable_lookup(struct hashtable *table, const char *key);
25.49 +uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
25.50 +
25.51 +
25.52 +struct bitarray {
25.53 + uint32_t *bits;
25.54 +};
25.55 +
25.56 +void bitarray_init(struct bitarray *bitarray, int size, int intial_value);
25.57 +void bitarray_release(struct bitarray *bitarray);
25.58 +void bitarray_set(struct bitarray *bitarray, int bit, int value);
25.59 +int bitarray_get(struct bitarray *bitarray, int bit);
25.60 +
25.61 +
25.62 +#endif /* _RAZOR_TYPES_H_ */
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/librazor/util.c Mon Jun 16 15:40:30 2008 -0400
26.3 @@ -0,0 +1,167 @@
26.4 +#include <limits.h>
26.5 +#include <string.h>
26.6 +#include <sys/stat.h>
26.7 +#include <stdlib.h>
26.8 +#include <stdio.h>
26.9 +#include <stdint.h>
26.10 +#include <unistd.h>
26.11 +
26.12 +#include "razor-internal.h"
26.13 +
26.14 +int
26.15 +razor_create_dir(const char *root, const char *path)
26.16 +{
26.17 + char buffer[PATH_MAX], *p;
26.18 + const char *slash, *next;
26.19 + struct stat buf;
26.20 +
26.21 + /* Create all sub-directories in dir. We know root exists and
26.22 + * is a dir, root does not end in a '/', and path has a
26.23 + * leading '/'. */
26.24 +
26.25 + strcpy(buffer, root);
26.26 + p = buffer + strlen(buffer);
26.27 + slash = path;
26.28 + for (slash = path; *slash != '\0'; slash = next) {
26.29 + next = strchr(slash + 1, '/');
26.30 + if (next == NULL)
26.31 + break;
26.32 +
26.33 + memcpy(p, slash, next - slash);
26.34 + p += next - slash;
26.35 + *p = '\0';
26.36 +
26.37 + if (stat(buffer, &buf) == 0) {
26.38 + if (!S_ISDIR(buf.st_mode)) {
26.39 + fprintf(stderr,
26.40 + "%s exists but is not a directory\n",
26.41 + buffer);
26.42 + return -1;
26.43 + }
26.44 + } else if (mkdir(buffer, 0777) < 0) {
26.45 + fprintf(stderr, "failed to make directory %s: %m\n",
26.46 + buffer);
26.47 + return -1;
26.48 + }
26.49 +
26.50 + /* FIXME: What to do about permissions for dirs we
26.51 + * have to create but are not in the cpio archive? */
26.52 + }
26.53 +
26.54 + return 0;
26.55 +}
26.56 +
26.57 +int
26.58 +razor_write(int fd, const void *data, size_t size)
26.59 +{
26.60 + size_t rest;
26.61 + ssize_t written;
26.62 + const unsigned char *p;
26.63 +
26.64 + rest = size;
26.65 + p = data;
26.66 + while (rest > 0) {
26.67 + written = write(fd, p, rest);
26.68 + if (written < 0) {
26.69 + fprintf(stderr, "write error: %m\n");
26.70 + return -1;
26.71 + }
26.72 + rest -= written;
26.73 + p += written;
26.74 + }
26.75 +
26.76 + return 0;
26.77 +}
26.78 +
26.79 +struct qsort_context {
26.80 + size_t size;
26.81 + razor_compare_with_data_func_t compare;
26.82 + void *data;
26.83 +};
26.84 +
26.85 +static void
26.86 +qsort_swap(void *p1, void *p2, size_t size)
26.87 +{
26.88 + char buffer[size];
26.89 +
26.90 + memcpy(buffer, p1, size);
26.91 + memcpy(p1, p2, size);
26.92 + memcpy(p2, buffer, size);
26.93 +}
26.94 +
26.95 +static void
26.96 +__qsort_with_data(void *base, size_t nelem, uint32_t *map,
26.97 + struct qsort_context *ctx)
26.98 +{
26.99 + void *p, *start, *end, *pivot;
26.100 + uint32_t *mp, *mstart, *mend, tmp;
26.101 + int left, right, result;
26.102 + size_t size = ctx->size;
26.103 +
26.104 + p = base;
26.105 + start = base;
26.106 + end = base + nelem * size;
26.107 + mp = map;
26.108 + mstart = map;
26.109 + mend = map + nelem;
26.110 + pivot = base + (random() % nelem) * size;
26.111 +
26.112 + while (p < end) {
26.113 + result = ctx->compare(p, pivot, ctx->data);
26.114 + if (result < 0) {
26.115 + qsort_swap(p, start, size);
26.116 + tmp = *mp;
26.117 + *mp = *mstart;
26.118 + *mstart = tmp;
26.119 + if (start == pivot)
26.120 + pivot = p;
26.121 + start += size;
26.122 + mstart++;
26.123 + p += size;
26.124 + mp++;
26.125 + } else if (result == 0) {
26.126 + p += size;
26.127 + mp++;
26.128 + } else {
26.129 + end -= size;
26.130 + mend--;
26.131 + qsort_swap(p, end, size);
26.132 + tmp = *mp;
26.133 + *mp = *mend;
26.134 + *mend = tmp;
26.135 + if (end == pivot)
26.136 + pivot = p;
26.137 + }
26.138 + }
26.139 +
26.140 + left = (start - base) / size;
26.141 + right = (base + nelem * size - end) / size;
26.142 + if (left > 1)
26.143 + __qsort_with_data(base, left, map, ctx);
26.144 + if (right > 1)
26.145 + __qsort_with_data(end, right, mend, ctx);
26.146 +}
26.147 +
26.148 +uint32_t *
26.149 +razor_qsort_with_data(void *base, size_t nelem, size_t size,
26.150 + razor_compare_with_data_func_t compare, void *data)
26.151 +{
26.152 + struct qsort_context ctx;
26.153 + uint32_t *map;
26.154 + int i;
26.155 +
26.156 + if (nelem == 0)
26.157 + return NULL;
26.158 +
26.159 + ctx.size = size;
26.160 + ctx.compare = compare;
26.161 + ctx.data = data;
26.162 +
26.163 + map = malloc(nelem * sizeof (uint32_t));
26.164 + for (i = 0; i < nelem; i++)
26.165 + map[i] = i;
26.166 +
26.167 + __qsort_with_data(base, nelem, map, &ctx);
26.168 +
26.169 + return map;
26.170 +}
27.1 --- a/main.c Sun Jun 15 23:15:59 2008 -0400
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,804 +0,0 @@
27.4 -/*
27.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
27.6 - * Copyright (C) 2008 Red Hat, Inc
27.7 - *
27.8 - * This program is free software; you can redistribute it and/or modify
27.9 - * it under the terms of the GNU General Public License as published by
27.10 - * the Free Software Foundation; either version 2 of the License, or
27.11 - * (at your option) any later version.
27.12 - *
27.13 - * This program is distributed in the hope that it will be useful,
27.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
27.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27.16 - * GNU General Public License for more details.
27.17 - *
27.18 - * You should have received a copy of the GNU General Public License along
27.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
27.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27.21 - */
27.22 -
27.23 -#include <stdlib.h>
27.24 -#include <stddef.h>
27.25 -#include <stdio.h>
27.26 -#include <stdint.h>
27.27 -#include <string.h>
27.28 -#include <sys/stat.h>
27.29 -#include <unistd.h>
27.30 -#include <fcntl.h>
27.31 -#include <dirent.h>
27.32 -#include <curl/curl.h>
27.33 -#include <fnmatch.h>
27.34 -#include <errno.h>
27.35 -#include "razor.h"
27.36 -
27.37 -static const char system_repo_filename[] = "system.repo";
27.38 -static const char next_repo_filename[] = "system-next.repo";
27.39 -static const char rawhide_repo_filename[] = "rawhide.repo";
27.40 -static const char updated_repo_filename[] = "system-updated.repo";
27.41 -static const char install_root[] = "install";
27.42 -static const char *repo_filename = system_repo_filename;
27.43 -static const char *yum_url;
27.44 -
27.45 -static int
27.46 -command_list(int argc, const char *argv[])
27.47 -{
27.48 - struct razor_set *set;
27.49 - struct razor_package_iterator *pi;
27.50 - struct razor_package *package;
27.51 - const char *pattern, *name, *version, *arch;
27.52 - int only_names = 0, i = 0;
27.53 -
27.54 - if (i < argc && strcmp(argv[i], "--only-names") == 0) {
27.55 - only_names = 1;
27.56 - i++;
27.57 - }
27.58 -
27.59 - pattern = argv[i];
27.60 - set = razor_set_open(repo_filename);
27.61 - pi = razor_package_iterator_create(set);
27.62 - while (razor_package_iterator_next(pi, &package,
27.63 - &name, &version, &arch)) {
27.64 - if (pattern && fnmatch(pattern, name, 0) != 0)
27.65 - continue;
27.66 -
27.67 - if (only_names)
27.68 - printf("%s\n", name);
27.69 - else
27.70 - printf("%s-%s.%s\n", name, version, arch);
27.71 - }
27.72 - razor_package_iterator_destroy(pi);
27.73 - razor_set_destroy(set);
27.74 -
27.75 - return 0;
27.76 -}
27.77 -
27.78 -static int
27.79 -list_properties(const char *package_name,
27.80 - enum razor_property_type required_type)
27.81 -{
27.82 - static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
27.83 - struct razor_set *set;
27.84 - struct razor_property *property;
27.85 - struct razor_package *package;
27.86 - struct razor_property_iterator *pi;
27.87 - const char *name, *version;
27.88 - enum razor_property_type type;
27.89 - enum razor_version_relation relation;
27.90 -
27.91 - set = razor_set_open(repo_filename);
27.92 - if (package_name)
27.93 - package = razor_set_get_package(set, package_name);
27.94 - else
27.95 - package = NULL;
27.96 -
27.97 - pi = razor_property_iterator_create(set, package);
27.98 - while (razor_property_iterator_next(pi, &property,
27.99 - &name, &relation, &version,
27.100 - &type)) {
27.101 - if (type != required_type)
27.102 - continue;
27.103 - if (version[0] == '\0')
27.104 - printf("%s\n", name);
27.105 - else
27.106 - printf("%s %s %s\n", name,
27.107 - relation_string[relation], version);
27.108 - }
27.109 - razor_property_iterator_destroy(pi);
27.110 -
27.111 - razor_set_destroy(set);
27.112 -
27.113 - return 0;
27.114 -}
27.115 -
27.116 -static int
27.117 -command_list_requires(int argc, const char *argv[])
27.118 -{
27.119 - return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
27.120 -}
27.121 -
27.122 -static int
27.123 -command_list_provides(int argc, const char *argv[])
27.124 -{
27.125 - return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
27.126 -}
27.127 -
27.128 -static int
27.129 -command_list_obsoletes(int argc, const char *argv[])
27.130 -{
27.131 - return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
27.132 -}
27.133 -
27.134 -static int
27.135 -command_list_conflicts(int argc, const char *argv[])
27.136 -{
27.137 - return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
27.138 -}
27.139 -
27.140 -static int
27.141 -command_list_files(int argc, const char *argv[])
27.142 -{
27.143 - struct razor_set *set;
27.144 -
27.145 - set = razor_set_open(repo_filename);
27.146 - if (set == NULL)
27.147 - return 1;
27.148 - razor_set_list_files(set, argv[0]);
27.149 - razor_set_destroy(set);
27.150 -
27.151 - return 0;
27.152 -}
27.153 -
27.154 -static int
27.155 -command_list_file_packages(int argc, const char *argv[])
27.156 -{
27.157 - struct razor_set *set;
27.158 - struct razor_package_iterator *pi;
27.159 - struct razor_package *package;
27.160 - const char *name, *version, *arch;
27.161 -
27.162 - set = razor_set_open(repo_filename);
27.163 - if (set == NULL)
27.164 - return 1;
27.165 -
27.166 - pi = razor_package_iterator_create_for_file(set, argv[0]);
27.167 - while (razor_package_iterator_next(pi, &package,
27.168 - &name, &version, &arch))
27.169 - printf("%s-%s\n", name, version);
27.170 - razor_package_iterator_destroy(pi);
27.171 -
27.172 - razor_set_destroy(set);
27.173 -
27.174 - return 0;
27.175 -}
27.176 -
27.177 -static int
27.178 -command_list_package_files(int argc, const char *argv[])
27.179 -{
27.180 - struct razor_set *set;
27.181 -
27.182 - set = razor_set_open(repo_filename);
27.183 - if (set == NULL)
27.184 - return 1;
27.185 - razor_set_list_package_files(set, argv[0]);
27.186 - razor_set_destroy(set);
27.187 -
27.188 - return 0;
27.189 -}
27.190 -
27.191 -static void
27.192 -list_packages_for_property(struct razor_set *set,
27.193 - struct razor_property *property)
27.194 -{
27.195 - struct razor_package_iterator *pi;
27.196 - struct razor_package *package;
27.197 - const char *name, *version, *arch;
27.198 -
27.199 - pi = razor_package_iterator_create_for_property(set, property);
27.200 - while (razor_package_iterator_next(pi, &package,
27.201 - &name, &version, &arch))
27.202 - printf("%s-%s.%s\n", name, version, arch);
27.203 - razor_package_iterator_destroy(pi);
27.204 -}
27.205 -
27.206 -static int
27.207 -list_property_packages(const char *ref_name,
27.208 - const char *ref_version,
27.209 - enum razor_property_type ref_type)
27.210 -{
27.211 - struct razor_set *set;
27.212 - struct razor_property *property;
27.213 - struct razor_property_iterator *pi;
27.214 - const char *name, *version;
27.215 - enum razor_property_type type;
27.216 - enum razor_version_relation relation;
27.217 -
27.218 - if (ref_name == NULL)
27.219 - return 0;
27.220 -
27.221 - set = razor_set_open(repo_filename);
27.222 - if (set == NULL)
27.223 - return 1;
27.224 -
27.225 - pi = razor_property_iterator_create(set, NULL);
27.226 - while (razor_property_iterator_next(pi, &property,
27.227 - &name, &relation, &version,
27.228 - &type)) {
27.229 - if (strcmp(ref_name, name) != 0)
27.230 - continue;
27.231 - if (ref_version && relation == RAZOR_VERSION_EQUAL &&
27.232 - strcmp(ref_version, version) != 0)
27.233 - continue;
27.234 - if (ref_type != type)
27.235 - continue;
27.236 -
27.237 - list_packages_for_property(set, property);
27.238 - }
27.239 - razor_property_iterator_destroy(pi);
27.240 -
27.241 - return 0;
27.242 -}
27.243 -
27.244 -static int
27.245 -command_what_requires(int argc, const char *argv[])
27.246 -{
27.247 - return list_property_packages(argv[0], argv[1],
27.248 - RAZOR_PROPERTY_REQUIRES);
27.249 -}
27.250 -
27.251 -static int
27.252 -command_what_provides(int argc, const char *argv[])
27.253 -{
27.254 - return list_property_packages(argv[0], argv[1],
27.255 - RAZOR_PROPERTY_PROVIDES);
27.256 -}
27.257 -
27.258 -static int
27.259 -show_progress(void *clientp,
27.260 - double dltotal, double dlnow, double ultotal, double ulnow)
27.261 -{
27.262 - const char *file = clientp;
27.263 -
27.264 - if (!dlnow < dltotal)
27.265 - fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
27.266 - file, (int) dlnow / 1024, (int) dltotal / 1024);
27.267 -
27.268 - return 0;
27.269 -}
27.270 -
27.271 -static int
27.272 -download_if_missing(const char *url, const char *file)
27.273 -{
27.274 - CURL *curl;
27.275 - struct stat buf;
27.276 - char error[256];
27.277 - FILE *fp;
27.278 - CURLcode res;
27.279 - long response;
27.280 -
27.281 - curl = curl_easy_init();
27.282 - if (curl == NULL)
27.283 - return 1;
27.284 -
27.285 - curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
27.286 - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
27.287 - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
27.288 - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
27.289 -
27.290 - if (stat(file, &buf) < 0) {
27.291 - fp = fopen(file, "w");
27.292 - if (fp == NULL) {
27.293 - fprintf(stderr,
27.294 - "failed to open %s for writing\n", file);
27.295 - return -1;
27.296 - }
27.297 - curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
27.298 - curl_easy_setopt(curl, CURLOPT_URL, url);
27.299 - res = curl_easy_perform(curl);
27.300 - fclose(fp);
27.301 - if (res != CURLE_OK) {
27.302 - fprintf(stderr, "curl error: %s\n", error);
27.303 - unlink(file);
27.304 - return -1;
27.305 - }
27.306 - res = curl_easy_getinfo(curl,
27.307 - CURLINFO_RESPONSE_CODE, &response);
27.308 - if (res != CURLE_OK) {
27.309 - fprintf(stderr, "curl error: %s\n", error);
27.310 - unlink(file);
27.311 - return -1;
27.312 - }
27.313 - if (response != 200) {
27.314 - fprintf(stderr, " - failed %ld\n", response);
27.315 - unlink(file);
27.316 - return -1;
27.317 - }
27.318 - fprintf(stderr, "\n");
27.319 - }
27.320 -
27.321 - curl_easy_cleanup(curl);
27.322 -
27.323 - return 0;
27.324 -}
27.325 -
27.326 -#define YUM_URL "http://download.fedora.redhat.com" \
27.327 - "/pub/fedora/linux/development/i386/os"
27.328 -
27.329 -static int
27.330 -command_import_yum(int argc, const char *argv[])
27.331 -{
27.332 - struct razor_set *set;
27.333 - char buffer[512];
27.334 -
27.335 - printf("downloading from %s.\n", yum_url);
27.336 - snprintf(buffer, sizeof buffer,
27.337 - "%s/repodata/primary.xml.gz", yum_url);
27.338 - if (download_if_missing(buffer, "primary.xml.gz") < 0)
27.339 - return -1;
27.340 - snprintf(buffer, sizeof buffer,
27.341 - "%s/repodata/filelists.xml.gz", yum_url);
27.342 - if (download_if_missing(buffer, "filelists.xml.gz") < 0)
27.343 - return -1;
27.344 -
27.345 - set = razor_set_create_from_yum();
27.346 - if (set == NULL)
27.347 - return 1;
27.348 - razor_set_write(set, rawhide_repo_filename);
27.349 - razor_set_destroy(set);
27.350 - printf("wrote %s\n", rawhide_repo_filename);
27.351 -
27.352 - return 0;
27.353 -}
27.354 -
27.355 -static int
27.356 -command_import_rpmdb(int argc, const char *argv[])
27.357 -{
27.358 - struct razor_set *set;
27.359 -
27.360 - set = razor_set_create_from_rpmdb();
27.361 - if (set == NULL)
27.362 - return 1;
27.363 - razor_set_write(set, repo_filename);
27.364 - razor_set_destroy(set);
27.365 - printf("wrote %s\n", repo_filename);
27.366 -
27.367 - return 0;
27.368 -}
27.369 -
27.370 -static int
27.371 -mark_packages_for_update(struct razor_transaction *trans,
27.372 - struct razor_set *set, const char *pattern)
27.373 -{
27.374 - struct razor_package_iterator *pi;
27.375 - struct razor_package *package;
27.376 - const char *name, *version, *arch;
27.377 - int matches = 0;
27.378 -
27.379 - pi = razor_package_iterator_create(set);
27.380 - while (razor_package_iterator_next(pi, &package,
27.381 - &name, &version, &arch)) {
27.382 - if (pattern && fnmatch(pattern, name, 0) == 0) {
27.383 - razor_transaction_update_package(trans, package);
27.384 - matches++;
27.385 - }
27.386 - }
27.387 - razor_package_iterator_destroy(pi);
27.388 -
27.389 - return matches;
27.390 -}
27.391 -
27.392 -static int
27.393 -mark_packages_for_removal(struct razor_transaction *trans,
27.394 - struct razor_set *set, const char *pattern)
27.395 -{
27.396 - struct razor_package_iterator *pi;
27.397 - struct razor_package *package;
27.398 - const char *name, *version, *arch;
27.399 - int matches = 0;
27.400 -
27.401 - pi = razor_package_iterator_create(set);
27.402 - while (razor_package_iterator_next(pi, &package,
27.403 - &name, &version, &arch)) {
27.404 - if (pattern && fnmatch(pattern, name, 0) == 0) {
27.405 - razor_transaction_remove_package(trans, package);
27.406 - matches++;
27.407 - }
27.408 - }
27.409 - razor_package_iterator_destroy(pi);
27.410 -
27.411 - return matches;
27.412 -}
27.413 -
27.414 -static int
27.415 -command_update(int argc, const char *argv[])
27.416 -{
27.417 - struct razor_set *set, *upstream;
27.418 - struct razor_transaction *trans;
27.419 - int i, errors;
27.420 -
27.421 - set = razor_set_open(repo_filename);
27.422 - upstream = razor_set_open(rawhide_repo_filename);
27.423 - if (set == NULL || upstream == NULL)
27.424 - return 1;
27.425 -
27.426 - trans = razor_transaction_create(set, upstream);
27.427 - if (argc == 0)
27.428 - razor_transaction_update_all(trans);
27.429 - for (i = 0; i < argc; i++) {
27.430 - if (mark_packages_for_update(trans, set, argv[i]) == 0) {
27.431 - fprintf(stderr, "no match for %s\n", argv[i]);
27.432 - return 1;
27.433 - }
27.434 - }
27.435 -
27.436 - errors = razor_transaction_resolve(trans);
27.437 - if (errors)
27.438 - return 1;
27.439 -
27.440 - set = razor_transaction_finish(trans);
27.441 - razor_set_write(set, updated_repo_filename);
27.442 - razor_set_destroy(set);
27.443 - razor_set_destroy(upstream);
27.444 - printf("wrote system-updated.repo\n");
27.445 -
27.446 - return 0;
27.447 -}
27.448 -
27.449 -static int
27.450 -command_remove(int argc, const char *argv[])
27.451 -{
27.452 - struct razor_set *set, *upstream;
27.453 - struct razor_transaction *trans;
27.454 - int i, errors;
27.455 -
27.456 - set = razor_set_open(repo_filename);
27.457 - if (set == NULL)
27.458 - return 1;
27.459 -
27.460 - upstream = razor_set_create();
27.461 - trans = razor_transaction_create(set, upstream);
27.462 - for (i = 0; i < argc; i++) {
27.463 - if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
27.464 - fprintf(stderr, "no match for %s\n", argv[i]);
27.465 - return 1;
27.466 - }
27.467 - }
27.468 -
27.469 - errors = razor_transaction_resolve(trans);
27.470 - if (errors)
27.471 - return 1;
27.472 -
27.473 - set = razor_transaction_finish(trans);
27.474 - razor_set_write(set, updated_repo_filename);
27.475 - razor_set_destroy(set);
27.476 - razor_set_destroy(upstream);
27.477 - printf("wrote system-updated.repo\n");
27.478 -
27.479 - return 0;
27.480 -}
27.481 -
27.482 -static void
27.483 -print_diff(const char *name,
27.484 - const char *old_version, const char *new_version, const char *arch,
27.485 - void *data)
27.486 -{
27.487 - if (old_version)
27.488 - printf("removing %s %s\n", name, old_version);
27.489 - else
27.490 - printf("install %s %s\n", name, new_version);
27.491 -}
27.492 -
27.493 -static int
27.494 -command_diff(int argc, const char *argv[])
27.495 -{
27.496 - struct razor_set *set, *updated;
27.497 -
27.498 - set = razor_set_open(repo_filename);
27.499 - updated = razor_set_open(updated_repo_filename);
27.500 - if (set == NULL || updated == NULL)
27.501 - return 1;
27.502 -
27.503 - razor_set_diff(set, updated, print_diff, NULL);
27.504 -
27.505 - razor_set_destroy(set);
27.506 - razor_set_destroy(updated);
27.507 -
27.508 - return 0;
27.509 -}
27.510 -
27.511 -static int
27.512 -command_import_rpms(int argc, const char *argv[])
27.513 -{
27.514 - DIR *dir;
27.515 - struct dirent *de;
27.516 - struct razor_importer *importer;
27.517 - struct razor_set *set;
27.518 - struct razor_rpm *rpm;
27.519 - int len;
27.520 - char filename[256];
27.521 - const char *dirname = argv[0];
27.522 -
27.523 - if (dirname == NULL) {
27.524 - fprintf(stderr, "usage: razor import-rpms DIR\n");
27.525 - return -1;
27.526 - }
27.527 -
27.528 - dir = opendir(dirname);
27.529 - if (dir == NULL) {
27.530 - fprintf(stderr, "couldn't read dir %s\n", dirname);
27.531 - return -1;
27.532 - }
27.533 -
27.534 - importer = razor_importer_new();
27.535 -
27.536 - while (de = readdir(dir), de != NULL) {
27.537 - len = strlen(de->d_name);
27.538 - if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
27.539 - continue;
27.540 - snprintf(filename, sizeof filename,
27.541 - "%s/%s", dirname, de->d_name);
27.542 - rpm = razor_rpm_open(filename);
27.543 - if (rpm == NULL) {
27.544 - fprintf(stderr,
27.545 - "failed to open rpm \"%s\"\n", filename);
27.546 - continue;
27.547 - }
27.548 - if (razor_importer_add_rpm(importer, rpm)) {
27.549 - fprintf(stderr, "couldn't import %s\n", filename);
27.550 - break;
27.551 - }
27.552 - razor_rpm_close(rpm);
27.553 - }
27.554 -
27.555 - if (de != NULL) {
27.556 - razor_importer_destroy(importer);
27.557 - return -1;
27.558 - }
27.559 -
27.560 - set = razor_importer_finish(importer);
27.561 -
27.562 - razor_set_write(set, repo_filename);
27.563 - razor_set_destroy(set);
27.564 - printf("wrote %s\n", repo_filename);
27.565 -
27.566 - return 0;
27.567 -}
27.568 -
27.569 -static void
27.570 -download_package(const char *name,
27.571 - const char *old_version,
27.572 - const char *new_version,
27.573 - const char *arch,
27.574 - void *data)
27.575 -{
27.576 - char file[PATH_MAX], url[256];
27.577 - const char *v;
27.578 - int *errors = data;
27.579 -
27.580 - if (old_version)
27.581 - return;
27.582 -
27.583 - /* Skip epoch */
27.584 - v = strchr(new_version, ':');
27.585 - if (v != NULL)
27.586 - v = v + 1;
27.587 - else
27.588 - v = new_version;
27.589 -
27.590 - snprintf(url, sizeof url,
27.591 - "%s/Packages/%s-%s.%s.rpm", yum_url, name, v, arch);
27.592 - snprintf(file, sizeof file,
27.593 - "rpms/%s-%s.%s.rpm", name, v, arch);
27.594 - if (download_if_missing(url, file) < 0)
27.595 - (*errors)++;
27.596 -}
27.597 -
27.598 -static void
27.599 -install_package(const char *name,
27.600 - const char *old_version,
27.601 - const char *new_version,
27.602 - const char *arch,
27.603 - void *data)
27.604 -{
27.605 - const char *v, *root = data;
27.606 - char file[PATH_MAX];
27.607 - struct razor_rpm *rpm;
27.608 -
27.609 - if (old_version) {
27.610 - printf("removing %s %s not handled\n", name, old_version);
27.611 - return;
27.612 - }
27.613 -
27.614 - /* Skip epoch */
27.615 - v = strchr(new_version, ':');
27.616 - if (v != NULL)
27.617 - v = v + 1;
27.618 - else
27.619 - v = new_version;
27.620 -
27.621 - printf("install %s %s\n", name, v);
27.622 - snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
27.623 -
27.624 - rpm = razor_rpm_open(file);
27.625 - if (rpm == NULL) {
27.626 - fprintf(stderr, "failed to open rpm %s\n", file);
27.627 - return;
27.628 - }
27.629 - if (razor_rpm_install(rpm, root) < 0) {
27.630 - fprintf(stderr,
27.631 - "failed to install rpm %s\n", file);
27.632 - return;
27.633 - }
27.634 - razor_rpm_close(rpm);
27.635 -}
27.636 -
27.637 -static int
27.638 -command_install(int argc, const char *argv[])
27.639 -{
27.640 - struct razor_root *root;
27.641 - struct razor_set *upstream, *next;
27.642 - struct razor_transaction *trans;
27.643 - int i = 0, errors, dependencies = 1;
27.644 -
27.645 - if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
27.646 - dependencies = 0;
27.647 - i++;
27.648 - }
27.649 -
27.650 - root = razor_root_open(install_root, RAZOR_ROOT_OPEN_WRITE);
27.651 - upstream = razor_set_open(rawhide_repo_filename);
27.652 - trans = razor_root_create_transaction(root, upstream);
27.653 -
27.654 - for (; i < argc; i++) {
27.655 - if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
27.656 - fprintf(stderr, "no package matched %s\n", argv[i]);
27.657 - razor_root_close(root);
27.658 - return 1;
27.659 - }
27.660 - }
27.661 -
27.662 - if (dependencies) {
27.663 - errors = razor_transaction_resolve(trans);
27.664 - if (errors) {
27.665 - razor_root_close(root);
27.666 - return 1;
27.667 - }
27.668 - }
27.669 -
27.670 - next = razor_transaction_finish(trans);
27.671 -
27.672 - razor_root_update(root, next);
27.673 -
27.674 - if (mkdir("rpms", 0777) && errno != EEXIST) {
27.675 - fprintf(stderr, "failed to create rpms directory.\n");
27.676 - razor_root_close(root);
27.677 - return 1;
27.678 - }
27.679 -
27.680 - razor_root_diff(root, download_package, &errors);
27.681 - if (errors > 0) {
27.682 - fprintf(stderr, "failed to download %d packages\n", errors);
27.683 - razor_root_close(root);
27.684 - return 1;
27.685 - }
27.686 -
27.687 - /* FIXME: We need to figure out the right install order here,
27.688 - * so the post and pre scripts can run. */
27.689 - razor_root_diff(root, install_package, (void *) root);
27.690 -
27.691 - razor_set_destroy(next);
27.692 - razor_set_destroy(upstream);
27.693 -
27.694 - return razor_root_commit(root);
27.695 -}
27.696 -
27.697 -static int
27.698 -command_init(int argc, const char *argv[])
27.699 -{
27.700 - return razor_root_create(install_root);
27.701 -}
27.702 -
27.703 -static int
27.704 -command_download(int argc, const char *argv[])
27.705 -{
27.706 - struct razor_set *set;
27.707 - struct razor_package_iterator *pi;
27.708 - struct razor_package *package;
27.709 - const char *pattern = argv[0], *name, *version, *arch;
27.710 - char url[256], file[256];
27.711 - int matches = 0;
27.712 -
27.713 - if (mkdir("rpms", 0777) && errno != EEXIST) {
27.714 - fprintf(stderr, "failed to create rpms directory.\n");
27.715 - return 1;
27.716 - }
27.717 -
27.718 - set = razor_set_open(rawhide_repo_filename);
27.719 - pi = razor_package_iterator_create(set);
27.720 - while (razor_package_iterator_next(pi, &package,
27.721 - &name, &version, &arch)) {
27.722 - if (pattern && fnmatch(pattern, name, 0) != 0)
27.723 - continue;
27.724 -
27.725 - matches++;
27.726 - snprintf(url, sizeof url,
27.727 - "%s/Packages/%s-%s.%s.rpm",
27.728 - yum_url, name, version, arch);
27.729 - snprintf(file, sizeof file,
27.730 - "rpms/%s-%s.%s.rpm", name, version, arch);
27.731 - download_if_missing(url, file);
27.732 - }
27.733 - razor_package_iterator_destroy(pi);
27.734 - razor_set_destroy(set);
27.735 -
27.736 - if (matches == 0)
27.737 - fprintf(stderr, "no packages matched \"%s\"\n", pattern);
27.738 - else if (matches == 1)
27.739 - fprintf(stderr, "downloaded 1 package\n");
27.740 - else
27.741 - fprintf(stderr, "downloaded %d packages\n", matches);
27.742 -
27.743 - return 0;
27.744 -}
27.745 -
27.746 -static struct {
27.747 - const char *name;
27.748 - const char *description;
27.749 - int (*func)(int argc, const char *argv[]);
27.750 -} razor_commands[] = {
27.751 - { "list", "list all packages", command_list },
27.752 - { "list-requires", "list all requires for the given package", command_list_requires },
27.753 - { "list-provides", "list all provides for the given package", command_list_provides },
27.754 - { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
27.755 - { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
27.756 - { "list-files", "list files for package set", command_list_files },
27.757 - { "list-file-packages", "list packages owning file", command_list_file_packages },
27.758 - { "list-package-files", "list files in package", command_list_package_files },
27.759 - { "what-requires", "list the packages that have the given requires", command_what_requires },
27.760 - { "what-provides", "list the packages that have the given provides", command_what_provides },
27.761 - { "import-yum", "import yum metadata files", command_import_yum },
27.762 - { "import-rpmdb", "import the system rpm database", command_import_rpmdb },
27.763 - { "import-rpms", "import rpms from the given directory", command_import_rpms },
27.764 - { "update", "update all or specified packages", command_update },
27.765 - { "remove", "remove specified packages", command_remove },
27.766 - { "diff", "show diff between two package sets", command_diff },
27.767 - { "install", "install rpm", command_install },
27.768 - { "init", "init razor root", command_init },
27.769 - { "download", "download packages", command_download }
27.770 -};
27.771 -
27.772 -static int
27.773 -usage(void)
27.774 -{
27.775 - int i;
27.776 -
27.777 - printf("usage:\n");
27.778 - for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
27.779 - printf(" %-20s%s\n",
27.780 - razor_commands[i].name, razor_commands[i].description);
27.781 -
27.782 - return 1;
27.783 -}
27.784 -
27.785 -int
27.786 -main(int argc, const char *argv[])
27.787 -{
27.788 - char *repo;
27.789 - int i;
27.790 -
27.791 - repo = getenv("RAZOR_REPO");
27.792 - if (repo != NULL)
27.793 - repo_filename = repo;
27.794 -
27.795 - yum_url = getenv("YUM_URL");
27.796 - if (yum_url == NULL)
27.797 - yum_url = YUM_URL;
27.798 -
27.799 - if (argc < 2)
27.800 - return usage();
27.801 -
27.802 - for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
27.803 - if (strcmp(razor_commands[i].name, argv[1]) == 0)
27.804 - return razor_commands[i].func(argc - 2, argv + 2);
27.805 -
27.806 - return usage();
27.807 -}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/po/.gitignore Mon Jun 16 15:40:30 2008 -0400
28.3 @@ -0,0 +1,4 @@
28.4 +POTFILES
28.5 +Makefile.in.in
28.6 +stamp-it
28.7 +
29.1 --- a/razor-internal.h Sun Jun 15 23:15:59 2008 -0400
29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
29.3 @@ -1,19 +0,0 @@
29.4 -#ifndef _RAZOR_INTERNAL_H_
29.5 -#define _RAZOR_INTERNAL_H_
29.6 -
29.7 -#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
29.8 -
29.9 -/* Utility functions */
29.10 -
29.11 -int razor_create_dir(const char *root, const char *path);
29.12 -int razor_write(int fd, const void *data, size_t size);
29.13 -
29.14 -
29.15 -typedef int (*razor_compare_with_data_func_t)(const void *p1,
29.16 - const void *p,
29.17 - void *data);
29.18 -uint32_t *
29.19 -razor_qsort_with_data(void *base, size_t nelem, size_t size,
29.20 - razor_compare_with_data_func_t compare, void *data);
29.21 -
29.22 -#endif /* _RAZOR_INTERNAL_H_ */
30.1 --- a/razor-root.c Sun Jun 15 23:15:59 2008 -0400
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,168 +0,0 @@
30.4 -#include <stdlib.h>
30.5 -#include <stdint.h>
30.6 -#include <stdio.h>
30.7 -#include <sys/stat.h>
30.8 -#include <dirent.h>
30.9 -#include <unistd.h>
30.10 -#include <fcntl.h>
30.11 -#include "razor.h"
30.12 -#include "razor-internal.h"
30.13 -
30.14 -static const char system_repo_filename[] = "system.repo";
30.15 -static const char next_repo_filename[] = "system-next.repo";
30.16 -static const char razor_root_path[] = "/var/lib/razor";
30.17 -
30.18 -struct razor_root {
30.19 - struct razor_set *system;
30.20 - struct razor_set *next;
30.21 - int fd;
30.22 - char path[PATH_MAX];
30.23 - char new_path[PATH_MAX];
30.24 -};
30.25 -
30.26 -int
30.27 -razor_root_create(const char *root)
30.28 -{
30.29 - struct stat buf;
30.30 - struct razor_set *set;
30.31 - char path[PATH_MAX];
30.32 -
30.33 - if (stat(root, &buf) < 0) {
30.34 - if (mkdir(root, 0777) < 0) {
30.35 - fprintf(stderr,
30.36 - "could not create install root \"%s\"\n",
30.37 - root);
30.38 - return -1;
30.39 - }
30.40 - fprintf(stderr, "created install root \"%s\"\n", root);
30.41 - } else if (!S_ISDIR(buf.st_mode)) {
30.42 - fprintf(stderr,
30.43 - "install root \"%s\" exists, but is not a directory\n",
30.44 - root);
30.45 - return -1;
30.46 - }
30.47 -
30.48 - snprintf(path, sizeof path, "%s/%s",
30.49 - razor_root_path, system_repo_filename);
30.50 - if (razor_create_dir(root, path) < 0) {
30.51 - fprintf(stderr, "could not create %s%s\n",
30.52 - root, razor_root_path);
30.53 - return -1;
30.54 - }
30.55 -
30.56 - set = razor_set_create();
30.57 - snprintf(path, sizeof path, "%s%s/%s",
30.58 - root, razor_root_path, system_repo_filename);
30.59 - if (stat(path, &buf) == 0) {
30.60 - fprintf(stderr,
30.61 - "a razor install root is already initialized\n");
30.62 - return -1;
30.63 - }
30.64 - if (razor_set_write(set, path) < 0) {
30.65 - fprintf(stderr, "could not write initial package set\n");
30.66 - return -1;
30.67 - }
30.68 - razor_set_destroy(set);
30.69 -
30.70 - return 0;
30.71 -}
30.72 -
30.73 -struct razor_root *
30.74 -razor_root_open(const char *root, int flags)
30.75 -{
30.76 - struct razor_root *image;
30.77 -
30.78 - image = malloc(sizeof *image);
30.79 - if (image == NULL)
30.80 - return NULL;
30.81 -
30.82 - /* Create the new next repo file up front to ensure exclusive
30.83 - * access. */
30.84 - snprintf(image->new_path, sizeof image->new_path,
30.85 - "%s%s/%s", root, root, next_repo_filename);
30.86 - image->fd = open(image->new_path,
30.87 - O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
30.88 - if (image->fd < 0) {
30.89 - fprintf(stderr, "failed to get lock file, "
30.90 - "maybe previous operation crashed?\n");
30.91 -
30.92 - /* FIXME: Use fcntl advisory locking on the system
30.93 - * package set file to figure out whether previous
30.94 - * operation crashed or is still in progress. */
30.95 -
30.96 - free(image);
30.97 - return NULL;
30.98 - }
30.99 -
30.100 - snprintf(image->path, sizeof image->path,
30.101 - "%s%s/%s", root, razor_root_path, system_repo_filename);
30.102 - image->system = razor_set_open(image->path);
30.103 - if (image->system == NULL) {
30.104 - unlink(image->new_path);
30.105 - close(image->fd);
30.106 - free(image);
30.107 - return NULL;
30.108 - }
30.109 -
30.110 - return image;
30.111 -}
30.112 -
30.113 -struct razor_set *
30.114 -razor_root_open_read_only(const char *root)
30.115 -{
30.116 - char path[PATH_MAX];
30.117 -
30.118 - snprintf(path, sizeof path, "%s%s/%s",
30.119 - root, razor_root_path, system_repo_filename);
30.120 -
30.121 - return razor_set_open(path);
30.122 -}
30.123 -
30.124 -struct razor_transaction *
30.125 -razor_root_create_transaction(struct razor_root *image,
30.126 - struct razor_set *upstream)
30.127 -{
30.128 - /* FIXME: This should take a number of upstream repos. */
30.129 - return razor_transaction_create(image->system, upstream);
30.130 -}
30.131 -
30.132 -int
30.133 -razor_root_close(struct razor_root *image)
30.134 -{
30.135 - unlink(image->new_path);
30.136 - close(image->fd);
30.137 - free(image);
30.138 -
30.139 - return 0;
30.140 -}
30.141 -
30.142 -void
30.143 -razor_root_update(struct razor_root *root, struct razor_set *next)
30.144 -{
30.145 - razor_set_write_to_fd(next, root->fd);
30.146 - root->next = next;
30.147 -
30.148 - /* Sync the new repo file so the new package set is on disk
30.149 - * before we start upgrading. */
30.150 - fsync(root->fd);
30.151 - printf("wrote %s\n", root->new_path);
30.152 -}
30.153 -
30.154 -int
30.155 -razor_root_commit(struct razor_root *image)
30.156 -{
30.157 - /* Make it so. */
30.158 - rename(image->new_path, image->path);
30.159 - printf("renamed %s to %s\n", image->new_path, image->path);
30.160 - close(image->fd);
30.161 - free(image);
30.162 -
30.163 - return 0;
30.164 -}
30.165 -
30.166 -void
30.167 -razor_root_diff(struct razor_root *root,
30.168 - razor_package_callback_t callback, void *data)
30.169 -{
30.170 - return razor_set_diff(root->system, root->next, callback, data);
30.171 -}
31.1 --- a/razor.c Sun Jun 15 23:15:59 2008 -0400
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,2611 +0,0 @@
31.4 -/*
31.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
31.6 - * Copyright (C) 2008 Red Hat, Inc
31.7 - *
31.8 - * This program is free software; you can redistribute it and/or modify
31.9 - * it under the terms of the GNU General Public License as published by
31.10 - * the Free Software Foundation; either version 2 of the License, or
31.11 - * (at your option) any later version.
31.12 - *
31.13 - * This program is distributed in the hope that it will be useful,
31.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
31.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31.16 - * GNU General Public License for more details.
31.17 - *
31.18 - * You should have received a copy of the GNU General Public License along
31.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
31.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31.21 - */
31.22 -
31.23 -#define _GNU_SOURCE
31.24 -
31.25 -#include <stdlib.h>
31.26 -#include <stddef.h>
31.27 -#include <stdint.h>
31.28 -#include <stdio.h>
31.29 -#include <string.h>
31.30 -#include <sys/types.h>
31.31 -#include <sys/stat.h>
31.32 -#include <sys/mman.h>
31.33 -#include <unistd.h>
31.34 -#include <fcntl.h>
31.35 -#include <errno.h>
31.36 -#include <ctype.h>
31.37 -#include <fnmatch.h>
31.38 -
31.39 -#include "razor.h"
31.40 -#include "razor-internal.h"
31.41 -#include "types.h"
31.42 -
31.43 -struct razor_set_section {
31.44 - uint32_t type;
31.45 - uint32_t offset;
31.46 - uint32_t size;
31.47 -};
31.48 -
31.49 -struct razor_set_header {
31.50 - uint32_t magic;
31.51 - uint32_t version;
31.52 - struct razor_set_section sections[0];
31.53 -};
31.54 -
31.55 -#define RAZOR_MAGIC 0x7a7a7a7a
31.56 -#define RAZOR_VERSION 1
31.57 -
31.58 -#define RAZOR_STRING_POOL 0
31.59 -#define RAZOR_PACKAGES 1
31.60 -#define RAZOR_PROPERTIES 2
31.61 -#define RAZOR_FILES 3
31.62 -#define RAZOR_PACKAGE_POOL 4
31.63 -#define RAZOR_PROPERTY_POOL 5
31.64 -#define RAZOR_FILE_POOL 6
31.65 -
31.66 -struct razor_package {
31.67 - uint name : 24;
31.68 - uint flags : 8;
31.69 - uint32_t version;
31.70 - uint32_t arch;
31.71 - struct list_head properties;
31.72 - struct list_head files;
31.73 -};
31.74 -
31.75 -struct razor_property {
31.76 - uint name : 24;
31.77 - uint flags : 6;
31.78 - enum razor_property_type type : 2;
31.79 - enum razor_version_relation relation : 32;
31.80 - uint32_t version;
31.81 - struct list_head packages;
31.82 -};
31.83 -
31.84 -struct razor_entry {
31.85 - uint name : 24;
31.86 - uint flags : 8;
31.87 - uint32_t start;
31.88 - struct list_head packages;
31.89 -};
31.90 -
31.91 -#define RAZOR_ENTRY_LAST 0x80
31.92 -
31.93 -struct razor_set {
31.94 - struct array string_pool;
31.95 - struct array packages;
31.96 - struct array properties;
31.97 - struct array files;
31.98 - struct array package_pool;
31.99 - struct array property_pool;
31.100 - struct array file_pool;
31.101 - struct razor_set_header *header;
31.102 -};
31.103 -
31.104 -struct import_entry {
31.105 - uint32_t package;
31.106 - char *name;
31.107 -};
31.108 -
31.109 -struct import_directory {
31.110 - uint32_t name, count;
31.111 - struct array files;
31.112 - struct array packages;
31.113 - struct import_directory *last;
31.114 -};
31.115 -
31.116 -struct razor_importer {
31.117 - struct razor_set *set;
31.118 - struct hashtable table;
31.119 - struct razor_package *package;
31.120 - struct array properties;
31.121 - struct array files;
31.122 - struct array file_requires;
31.123 -};
31.124 -
31.125 -static void *
31.126 -zalloc(size_t size)
31.127 -{
31.128 - void *p;
31.129 -
31.130 - p = malloc(size);
31.131 - memset(p, 0, size);
31.132 -
31.133 - return p;
31.134 -}
31.135 -
31.136 -struct razor_set_section razor_sections[] = {
31.137 - { RAZOR_STRING_POOL, offsetof(struct razor_set, string_pool) },
31.138 - { RAZOR_PACKAGES, offsetof(struct razor_set, packages) },
31.139 - { RAZOR_PROPERTIES, offsetof(struct razor_set, properties) },
31.140 - { RAZOR_FILES, offsetof(struct razor_set, files) },
31.141 - { RAZOR_PACKAGE_POOL, offsetof(struct razor_set, package_pool) },
31.142 - { RAZOR_PROPERTY_POOL, offsetof(struct razor_set, property_pool) },
31.143 - { RAZOR_FILE_POOL, offsetof(struct razor_set, file_pool) },
31.144 -};
31.145 -
31.146 -struct razor_set *
31.147 -razor_set_create(void)
31.148 -{
31.149 - struct razor_set *set;
31.150 - struct razor_entry *e;
31.151 - char *empty;
31.152 -
31.153 - set = zalloc(sizeof *set);
31.154 -
31.155 - e = array_add(&set->files, sizeof *e);
31.156 - empty = array_add(&set->string_pool, 1);
31.157 - *empty = '\0';
31.158 - e->name = 0;
31.159 - e->flags = RAZOR_ENTRY_LAST;
31.160 - e->start = 0;
31.161 - list_set_empty(&e->packages);
31.162 -
31.163 - return set;
31.164 -}
31.165 -
31.166 -struct razor_set *
31.167 -razor_set_open(const char *filename)
31.168 -{
31.169 - struct razor_set *set;
31.170 - struct razor_set_section *s;
31.171 - struct stat stat;
31.172 - struct array *array;
31.173 - int fd;
31.174 -
31.175 - set = zalloc(sizeof *set);
31.176 - fd = open(filename, O_RDONLY);
31.177 - if (fstat(fd, &stat) < 0)
31.178 - return NULL;
31.179 - set->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
31.180 - if (set->header == MAP_FAILED) {
31.181 - free(set);
31.182 - return NULL;
31.183 - }
31.184 -
31.185 - for (s = set->header->sections; ~s->type; s++) {
31.186 - if (s->type >= ARRAY_SIZE(razor_sections))
31.187 - continue;
31.188 - if (s->type != razor_sections[s->type].type)
31.189 - continue;
31.190 - array = (void *) set + razor_sections[s->type].offset;
31.191 - array->data = (void *) set->header + s->offset;
31.192 - array->size = s->size;
31.193 - array->alloc = s->size;
31.194 - }
31.195 - close(fd);
31.196 -
31.197 - return set;
31.198 -}
31.199 -
31.200 -void
31.201 -razor_set_destroy(struct razor_set *set)
31.202 -{
31.203 - unsigned int size;
31.204 - struct array *a;
31.205 - int i;
31.206 -
31.207 - if (set->header) {
31.208 - for (i = 0; set->header->sections[i].type; i++)
31.209 - ;
31.210 - size = set->header->sections[i].type;
31.211 - munmap(set->header, size);
31.212 - } else {
31.213 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
31.214 - a = (void *) set + razor_sections[i].offset;
31.215 - free(a->data);
31.216 - }
31.217 - }
31.218 -
31.219 - free(set);
31.220 -}
31.221 -
31.222 -int
31.223 -razor_set_write_to_fd(struct razor_set *set, int fd)
31.224 -{
31.225 - char data[4096];
31.226 - struct razor_set_header *header = (struct razor_set_header *) data;
31.227 - struct array *a;
31.228 - uint32_t offset;
31.229 - int i;
31.230 -
31.231 - memset(data, 0, sizeof data);
31.232 - header->magic = RAZOR_MAGIC;
31.233 - header->version = RAZOR_VERSION;
31.234 - offset = sizeof data;
31.235 -
31.236 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
31.237 - if (razor_sections[i].type != i)
31.238 - continue;
31.239 - a = (void *) set + razor_sections[i].offset;
31.240 - header->sections[i].type = i;
31.241 - header->sections[i].offset = offset;
31.242 - header->sections[i].size = a->size;
31.243 - offset += ALIGN(a->size, 4096);
31.244 - }
31.245 -
31.246 - header->sections[i].type = ~0;
31.247 - header->sections[i].offset = 0;
31.248 - header->sections[i].size = 0;
31.249 -
31.250 - razor_write(fd, data, sizeof data);
31.251 - memset(data, 0, sizeof data);
31.252 - for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
31.253 - if (razor_sections[i].type != i)
31.254 - continue;
31.255 - a = (void *) set + razor_sections[i].offset;
31.256 - razor_write(fd, a->data, a->size);
31.257 - razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
31.258 - }
31.259 -
31.260 - return 0;
31.261 -}
31.262 -
31.263 -int
31.264 -razor_set_write(struct razor_set *set, const char *filename)
31.265 -{
31.266 - int fd, status;
31.267 -
31.268 - fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
31.269 - if (fd < 0)
31.270 - return -1;
31.271 -
31.272 - status = razor_set_write_to_fd(set, fd);
31.273 - if (status) {
31.274 - close(fd);
31.275 - return status;
31.276 - }
31.277 -
31.278 - return close(fd);
31.279 -}
31.280 -
31.281 -void
31.282 -razor_build_evr(char *evr_buf, int size, const char *epoch,
31.283 - const char *version, const char *release)
31.284 -{
31.285 - int len;
31.286 -
31.287 - if (!version || !*version) {
31.288 - *evr_buf = '\0';
31.289 - return;
31.290 - }
31.291 -
31.292 - if (epoch && *epoch && strcmp(epoch, "0") != 0) {
31.293 - len = snprintf(evr_buf, size, "%s:", epoch);
31.294 - evr_buf += len;
31.295 - size -= len;
31.296 - }
31.297 - len = snprintf(evr_buf, size, "%s", version);
31.298 - evr_buf += len;
31.299 - size -= len;
31.300 - if (release && *release)
31.301 - snprintf(evr_buf, size, "-%s", release);
31.302 -}
31.303 -
31.304 -void
31.305 -razor_importer_begin_package(struct razor_importer *importer,
31.306 - const char *name,
31.307 - const char *version,
31.308 - const char *arch)
31.309 -{
31.310 - struct razor_package *p;
31.311 -
31.312 - p = array_add(&importer->set->packages, sizeof *p);
31.313 - p->name = hashtable_tokenize(&importer->table, name);
31.314 - p->flags = 0;
31.315 - p->version = hashtable_tokenize(&importer->table, version);
31.316 - p->arch = hashtable_tokenize(&importer->table, arch);
31.317 -
31.318 - importer->package = p;
31.319 - array_init(&importer->properties);
31.320 -}
31.321 -
31.322 -void
31.323 -razor_importer_finish_package(struct razor_importer *importer)
31.324 -{
31.325 - list_set_array(&importer->package->properties,
31.326 - &importer->set->property_pool,
31.327 - &importer->properties,
31.328 - 1);
31.329 -
31.330 - array_release(&importer->properties);
31.331 -}
31.332 -
31.333 -void
31.334 -razor_importer_add_property(struct razor_importer *importer,
31.335 - const char *name,
31.336 - enum razor_version_relation relation,
31.337 - const char *version,
31.338 - enum razor_property_type type)
31.339 -{
31.340 - struct razor_property *p;
31.341 - uint32_t *r;
31.342 -
31.343 - p = array_add(&importer->set->properties, sizeof *p);
31.344 - p->name = hashtable_tokenize(&importer->table, name);
31.345 - p->flags = 0;
31.346 - p->type = type;
31.347 - p->relation = relation;
31.348 - p->version = hashtable_tokenize(&importer->table, version);
31.349 - list_set_ptr(&p->packages, importer->package -
31.350 - (struct razor_package *) importer->set->packages.data);
31.351 -
31.352 - r = array_add(&importer->properties, sizeof *r);
31.353 - *r = p - (struct razor_property *) importer->set->properties.data;
31.354 -
31.355 - if (type == RAZOR_PROPERTY_REQUIRES && *name == '/') {
31.356 - r = array_add(&importer->file_requires, sizeof *r);
31.357 - *r = p->name;
31.358 - }
31.359 -}
31.360 -
31.361 -void
31.362 -razor_importer_add_file(struct razor_importer *importer, const char *name)
31.363 -{
31.364 - struct import_entry *e;
31.365 -
31.366 - e = array_add(&importer->files, sizeof *e);
31.367 -
31.368 - e->package = importer->package -
31.369 - (struct razor_package *) importer->set->packages.data;
31.370 - e->name = strdup(name);
31.371 -}
31.372 -
31.373 -struct razor_importer *
31.374 -razor_importer_new(void)
31.375 -{
31.376 - struct razor_importer *importer;
31.377 -
31.378 - importer = zalloc(sizeof *importer);
31.379 - importer->set = razor_set_create();
31.380 - hashtable_init(&importer->table, &importer->set->string_pool);
31.381 -
31.382 - return importer;
31.383 -}
31.384 -
31.385 -/* Destroy an importer without creating the set. */
31.386 -void
31.387 -razor_importer_destroy(struct razor_importer *importer)
31.388 -{
31.389 - /* FIXME: write this */
31.390 -}
31.391 -
31.392 -static int
31.393 -versioncmp(const char *s1, const char *s2)
31.394 -{
31.395 - const char *p1, *p2;
31.396 - long n1, n2;
31.397 - int res;
31.398 -
31.399 - n1 = strtol(s1, (char **) &p1, 10);
31.400 - n2 = strtol(s2, (char **) &p2, 10);
31.401 -
31.402 - /* Epoch; if one but not the other has an epoch set, default
31.403 - * the epoch-less version to 0. */
31.404 - res = (*p1 == ':') - (*p2 == ':');
31.405 - if (res < 0) {
31.406 - n1 = 0;
31.407 - p1 = s1;
31.408 - p2++;
31.409 - } else if (res > 0) {
31.410 - p1++;
31.411 - n2 = 0;
31.412 - p2 = s2;
31.413 - }
31.414 -
31.415 - if (n1 != n2)
31.416 - return n1 - n2;
31.417 - while (*p1 && *p2) {
31.418 - if (*p1 != *p2)
31.419 - return *p1 - *p2;
31.420 - p1++;
31.421 - p2++;
31.422 - if (isdigit(*p1) && isdigit(*p2))
31.423 - return versioncmp(p1, p2);
31.424 - }
31.425 -
31.426 - return *p1 - *p2;
31.427 -}
31.428 -
31.429 -static int
31.430 -compare_packages(const void *p1, const void *p2, void *data)
31.431 -{
31.432 - const struct razor_package *pkg1 = p1, *pkg2 = p2;
31.433 - struct razor_set *set = data;
31.434 - char *pool = set->string_pool.data;
31.435 -
31.436 - /* FIXME: what if the flags are different? */
31.437 - if (pkg1->name == pkg2->name)
31.438 - return versioncmp(&pool[pkg1->version], &pool[pkg2->version]);
31.439 - else
31.440 - return strcmp(&pool[pkg1->name], &pool[pkg2->name]);
31.441 -}
31.442 -
31.443 -static int
31.444 -compare_properties(const void *p1, const void *p2, void *data)
31.445 -{
31.446 - const struct razor_property *prop1 = p1, *prop2 = p2;
31.447 - struct razor_set *set = data;
31.448 - char *pool = set->string_pool.data;
31.449 -
31.450 - if (prop1->name != prop2->name)
31.451 - return strcmp(&pool[prop1->name], &pool[prop2->name]);
31.452 - else if (prop1->type != prop2->type)
31.453 - return prop1->type - prop2->type;
31.454 - else if (prop1->relation != prop2->relation)
31.455 - return prop1->relation - prop2->relation;
31.456 - else
31.457 - return versioncmp(&pool[prop1->version], &pool[prop2->version]);
31.458 -}
31.459 -
31.460 -static uint32_t *
31.461 -uniqueify_properties(struct razor_set *set)
31.462 -{
31.463 - struct razor_property *rp, *up, *rp_end;
31.464 - struct array *pkgs, *p;
31.465 - struct list_head *r;
31.466 - uint32_t *map, *rmap;
31.467 - int i, count, unique;
31.468 -
31.469 - count = set->properties.size / sizeof(struct razor_property);
31.470 - map = razor_qsort_with_data(set->properties.data,
31.471 - count,
31.472 - sizeof(struct razor_property),
31.473 - compare_properties,
31.474 - set);
31.475 -
31.476 - rp_end = set->properties.data + set->properties.size;
31.477 - rmap = malloc(count * sizeof *map);
31.478 - pkgs = zalloc(count * sizeof *pkgs);
31.479 - for (rp = set->properties.data, up = rp, i = 0; rp < rp_end; rp++, i++) {
31.480 - if (rp->name != up->name || rp->type != up->type ||
31.481 - rp->relation != up->relation || rp->version != up->version) {
31.482 - up++;
31.483 - up->name = rp->name;
31.484 - up->flags = 0;
31.485 - up->type = rp->type;
31.486 - up->relation = rp->relation;
31.487 - up->version = rp->version;
31.488 - }
31.489 -
31.490 - unique = up - (struct razor_property *) set->properties.data;
31.491 - rmap[map[i]] = unique;
31.492 - r = array_add(&pkgs[unique], sizeof *r);
31.493 - *r = rp->packages;
31.494 - }
31.495 - free(map);
31.496 -
31.497 - if (up != rp)
31.498 - up++;
31.499 - set->properties.size = (void *) up - set->properties.data;
31.500 - rp_end = up;
31.501 - for (rp = set->properties.data, p = pkgs; rp < rp_end; rp++, p++) {
31.502 - list_set_array(&rp->packages, &set->package_pool, p, 0);
31.503 - array_release(p);
31.504 - }
31.505 -
31.506 - free(pkgs);
31.507 -
31.508 - return rmap;
31.509 -}
31.510 -
31.511 -static int
31.512 -compare_filenames(const void *p1, const void *p2, void *data)
31.513 -{
31.514 - const struct import_entry *e1 = p1;
31.515 - const struct import_entry *e2 = p2;
31.516 - const char *n1 = e1->name;
31.517 - const char *n2 = e2->name;
31.518 -
31.519 - /* Need to make sure that the contents of a directory
31.520 - * are sorted immediately after it. So "foo/bar" has to
31.521 - * sort before "foo.conf"
31.522 - *
31.523 - * FIXME: this is about 60% slower than strcmp
31.524 - */
31.525 - while (*n1 && *n2) {
31.526 - if (*n1 < *n2)
31.527 - return *n2 == '/' ? 1 : -1;
31.528 - else if (*n1 > *n2)
31.529 - return *n1 == '/' ? -1 : 1;
31.530 - n1++;
31.531 - n2++;
31.532 - }
31.533 - if (*n1)
31.534 - return 1;
31.535 - else if (*n2)
31.536 - return -1;
31.537 - else
31.538 - return 0;
31.539 -}
31.540 -
31.541 -static void
31.542 -count_entries(struct import_directory *d)
31.543 -{
31.544 - struct import_directory *p, *end;
31.545 -
31.546 - p = d->files.data;
31.547 - end = d->files.data + d->files.size;
31.548 - d->count = 0;
31.549 - while (p < end) {
31.550 - count_entries(p);
31.551 - d->count += p->count + 1;
31.552 - p++;
31.553 - }
31.554 -}
31.555 -
31.556 -static void
31.557 -serialize_files(struct razor_set *set,
31.558 - struct import_directory *d, struct array *array)
31.559 -{
31.560 - struct import_directory *p, *end;
31.561 - struct razor_entry *e = NULL;
31.562 - uint32_t s;
31.563 -
31.564 - p = d->files.data;
31.565 - end = d->files.data + d->files.size;
31.566 - s = array->size / sizeof *e + d->files.size / sizeof *p;
31.567 - while (p < end) {
31.568 - e = array_add(array, sizeof *e);
31.569 - e->name = p->name;
31.570 - e->flags = 0;
31.571 - e->start = p->count > 0 ? s : 0;
31.572 - s += p->count;
31.573 -
31.574 - list_set_array(&e->packages, &set->package_pool, &p->packages, 0);
31.575 - array_release(&p->packages);
31.576 - p++;
31.577 - }
31.578 - if (e != NULL)
31.579 - e->flags |= RAZOR_ENTRY_LAST;
31.580 -
31.581 - p = d->files.data;
31.582 - end = d->files.data + d->files.size;
31.583 - while (p < end) {
31.584 - serialize_files(set, p, array);
31.585 - p++;
31.586 - }
31.587 -}
31.588 -
31.589 -static void
31.590 -remap_property_package_links(struct array *properties, uint32_t *rmap)
31.591 -{
31.592 - struct razor_property *p, *end;
31.593 -
31.594 - end = properties->data + properties->size;
31.595 - for (p = properties->data; p < end; p++)
31.596 - list_remap_head(&p->packages, rmap);
31.597 -}
31.598 -
31.599 -static void
31.600 -build_file_tree(struct razor_importer *importer)
31.601 -{
31.602 - int count, i, length;
31.603 - struct import_entry *filenames;
31.604 - char *f, *end;
31.605 - uint32_t name, *r;
31.606 - char dirname[256];
31.607 - struct import_directory *d, root;
31.608 - struct razor_entry *e;
31.609 -
31.610 - count = importer->files.size / sizeof (struct import_entry);
31.611 - razor_qsort_with_data(importer->files.data,
31.612 - count,
31.613 - sizeof (struct import_entry),
31.614 - compare_filenames,
31.615 - NULL);
31.616 -
31.617 - root.name = hashtable_tokenize(&importer->table, "");
31.618 - array_init(&root.files);
31.619 - array_init(&root.packages);
31.620 - root.last = NULL;
31.621 -
31.622 - filenames = importer->files.data;
31.623 - for (i = 0; i < count; i++) {
31.624 - f = filenames[i].name;
31.625 - if (*f != '/')
31.626 - continue;
31.627 - f++;
31.628 -
31.629 - d = &root;
31.630 - while (*f) {
31.631 - end = strchr(f, '/');
31.632 - if (end == NULL)
31.633 - end = f + strlen(f);
31.634 - length = end - f;
31.635 - memcpy(dirname, f, length);
31.636 - dirname[length] ='\0';
31.637 - name = hashtable_tokenize(&importer->table, dirname);
31.638 - if (d->last == NULL || d->last->name != name) {
31.639 - d->last = array_add(&d->files, sizeof *d);
31.640 - d->last->name = name;
31.641 - d->last->last = NULL;
31.642 - array_init(&d->last->files);
31.643 - array_init(&d->last->packages);
31.644 - }
31.645 - d = d->last;
31.646 - f = end + 1;
31.647 - if (*end == '\0')
31.648 - break;
31.649 - }
31.650 -
31.651 - r = array_add(&d->packages, sizeof *r);
31.652 - *r = filenames[i].package;
31.653 - free(filenames[i].name);
31.654 - }
31.655 -
31.656 - count_entries(&root);
31.657 - e = importer->set->files.data;
31.658 - e->name = root.name;
31.659 - e->flags = RAZOR_ENTRY_LAST;
31.660 - e->start = importer->files.size ? 1 : 0;
31.661 - list_set_empty(&e->packages);
31.662 -
31.663 - serialize_files(importer->set, &root, &importer->set->files);
31.664 -
31.665 - array_release(&importer->files);
31.666 -}
31.667 -
31.668 -static struct razor_entry *
31.669 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern);
31.670 -
31.671 -static void
31.672 -list_to_array(struct list *list, struct array *array)
31.673 -{
31.674 - uint32_t *item;
31.675 -
31.676 - while (list) {
31.677 - item = array_add(array, sizeof *item);
31.678 - *item = list->data;
31.679 - list = list_next(list);
31.680 - }
31.681 -}
31.682 -
31.683 -static int
31.684 -compare_file_requires(const void *p1, const void *p2, void *data)
31.685 -{
31.686 - uint32_t *f1 = (void *)p1, *f2 = (void *)p2;
31.687 - const char *pool = data;
31.688 -
31.689 - return strcmp(&pool[*f1], &pool[*f2]);
31.690 -}
31.691 -
31.692 -static void
31.693 -find_file_provides(struct razor_importer *importer)
31.694 -{
31.695 - struct razor_property *prop;
31.696 - struct razor_entry *top, *entry;
31.697 - struct razor_package *packages;
31.698 - struct array pkgprops;
31.699 - struct list *pkg;
31.700 - uint32_t *req, *req_start, *req_end;
31.701 - uint32_t *map, *newprop;
31.702 - char *pool;
31.703 -
31.704 - pool = importer->set->string_pool.data;
31.705 - packages = importer->set->packages.data;
31.706 - top = importer->set->files.data;
31.707 -
31.708 - req = req_start = importer->file_requires.data;
31.709 - req_end = importer->file_requires.data + importer->file_requires.size;
31.710 - map = razor_qsort_with_data(req, req_end - req, sizeof *req,
31.711 - compare_file_requires, pool);
31.712 - free(map);
31.713 -
31.714 - for (req = req_start; req < req_end; req++) {
31.715 - if (req > req_start && req[0] == req[-1])
31.716 - continue;
31.717 - entry = find_entry(importer->set, top, &pool[*req]);
31.718 - if (!entry)
31.719 - continue;
31.720 -
31.721 - for (pkg = list_first(&entry->packages, &importer->set->package_pool); pkg; pkg = list_next(pkg)) {
31.722 - prop = array_add(&importer->set->properties, sizeof *prop);
31.723 - prop->name = *req;
31.724 - prop->type = RAZOR_PROPERTY_PROVIDES;
31.725 - prop->relation = RAZOR_VERSION_EQUAL;
31.726 - prop->version = hashtable_tokenize(&importer->table, "");
31.727 - list_set_ptr(&prop->packages, pkg->data);
31.728 -
31.729 - /* Update property list of pkg */
31.730 - array_init(&pkgprops);
31.731 - list_to_array(list_first(&packages[pkg->data].properties, &importer->set->property_pool), &pkgprops);
31.732 - newprop = array_add(&pkgprops, sizeof *newprop);
31.733 - *newprop = prop - (struct razor_property *)importer->set->properties.data;
31.734 - list_set_array(&packages[pkg->data].properties, &importer->set->property_pool, &pkgprops, 1);
31.735 - array_release(&pkgprops);
31.736 - }
31.737 - }
31.738 -
31.739 - array_release(&importer->file_requires);
31.740 -}
31.741 -
31.742 -static void
31.743 -build_package_file_lists(struct razor_set *set, uint32_t *rmap)
31.744 -{
31.745 - struct razor_package *p, *packages;
31.746 - struct array *pkgs;
31.747 - struct razor_entry *e, *end;
31.748 - struct list *r;
31.749 - uint32_t *q;
31.750 - int i, count;
31.751 -
31.752 - count = set->packages.size / sizeof *p;
31.753 - pkgs = zalloc(count * sizeof *pkgs);
31.754 -
31.755 - end = set->files.data + set->files.size;
31.756 - for (e = set->files.data; e < end; e++) {
31.757 - list_remap_head(&e->packages, rmap);
31.758 - r = list_first(&e->packages, &set->package_pool);
31.759 - while (r) {
31.760 - q = array_add(&pkgs[r->data], sizeof *q);
31.761 - *q = e - (struct razor_entry *) set->files.data;
31.762 - r = list_next(r);
31.763 - }
31.764 - }
31.765 -
31.766 - packages = set->packages.data;
31.767 - for (i = 0; i < count; i++) {
31.768 - list_set_array(&packages[i].files, &set->file_pool, &pkgs[i], 0);
31.769 - array_release(&pkgs[i]);
31.770 - }
31.771 - free(pkgs);
31.772 -}
31.773 -
31.774 -struct razor_set *
31.775 -razor_importer_finish(struct razor_importer *importer)
31.776 -{
31.777 - struct razor_set *set;
31.778 - uint32_t *map, *rmap;
31.779 - int i, count;
31.780 -
31.781 - build_file_tree(importer);
31.782 - find_file_provides(importer);
31.783 -
31.784 - map = uniqueify_properties(importer->set);
31.785 - list_remap_pool(&importer->set->property_pool, map);
31.786 - free(map);
31.787 -
31.788 - count = importer->set->packages.size / sizeof(struct razor_package);
31.789 - map = razor_qsort_with_data(importer->set->packages.data,
31.790 - count,
31.791 - sizeof(struct razor_package),
31.792 - compare_packages,
31.793 - importer->set);
31.794 -
31.795 - rmap = malloc(count * sizeof *rmap);
31.796 - for (i = 0; i < count; i++)
31.797 - rmap[map[i]] = i;
31.798 - free(map);
31.799 -
31.800 - list_remap_pool(&importer->set->package_pool, rmap);
31.801 - build_package_file_lists(importer->set, rmap);
31.802 - remap_property_package_links(&importer->set->properties, rmap);
31.803 - free(rmap);
31.804 -
31.805 - set = importer->set;
31.806 - hashtable_release(&importer->table);
31.807 - free(importer);
31.808 -
31.809 - return set;
31.810 -}
31.811 -
31.812 -struct razor_package_iterator {
31.813 - struct razor_set *set;
31.814 - struct razor_package *package, *end;
31.815 - struct list *index;
31.816 - int free_index;
31.817 -};
31.818 -
31.819 -static struct razor_package_iterator *
31.820 -razor_package_iterator_create_with_index(struct razor_set *set,
31.821 - struct list *index)
31.822 -{
31.823 - struct razor_package_iterator *pi;
31.824 -
31.825 - pi = zalloc(sizeof *pi);
31.826 - pi->set = set;
31.827 - pi->index = index;
31.828 -
31.829 - return pi;
31.830 -}
31.831 -
31.832 -struct razor_package_iterator *
31.833 -razor_package_iterator_create(struct razor_set *set)
31.834 -{
31.835 - struct razor_package_iterator *pi;
31.836 -
31.837 - pi = zalloc(sizeof *pi);
31.838 - pi->set = set;
31.839 - pi->end = set->packages.data + set->packages.size;
31.840 - pi->package = set->packages.data;
31.841 -
31.842 - return pi;
31.843 -}
31.844 -
31.845 -static void
31.846 -razor_package_iterator_init_for_property(struct razor_package_iterator *pi,
31.847 - struct razor_set *set,
31.848 - struct razor_property *property)
31.849 -{
31.850 - memset(pi, 0, sizeof *pi);
31.851 - pi->set = set;
31.852 - pi->index = list_first(&property->packages, &set->package_pool);
31.853 -}
31.854 -
31.855 -struct razor_package_iterator *
31.856 -razor_package_iterator_create_for_property(struct razor_set *set,
31.857 - struct razor_property *property)
31.858 -{
31.859 - struct list *index;
31.860 -
31.861 - index = list_first(&property->packages, &set->package_pool);
31.862 - return razor_package_iterator_create_with_index(set, index);
31.863 -}
31.864 -
31.865 -int
31.866 -razor_package_iterator_next(struct razor_package_iterator *pi,
31.867 - struct razor_package **package,
31.868 - const char **name,
31.869 - const char **version,
31.870 - const char **arch)
31.871 -{
31.872 - char *pool;
31.873 - int valid;
31.874 - struct razor_package *p, *packages;
31.875 -
31.876 - if (pi->package) {
31.877 - p = pi->package++;
31.878 - valid = p < pi->end;
31.879 - } else if (pi->index) {
31.880 - packages = pi->set->packages.data;
31.881 - p = &packages[pi->index->data];
31.882 - pi->index = list_next(pi->index);
31.883 - valid = 1;
31.884 - } else
31.885 - valid = 0;
31.886 -
31.887 - if (valid) {
31.888 - pool = pi->set->string_pool.data;
31.889 - *package = p;
31.890 - *name = &pool[p->name];
31.891 - *version = &pool[p->version];
31.892 - *arch = &pool[p->arch];
31.893 - } else {
31.894 - *package = NULL;
31.895 - }
31.896 -
31.897 - return valid;
31.898 -}
31.899 -
31.900 -void
31.901 -razor_package_iterator_destroy(struct razor_package_iterator *pi)
31.902 -{
31.903 - if (pi->free_index)
31.904 - free(pi->index);
31.905 -
31.906 - free(pi);
31.907 -}
31.908 -
31.909 -struct razor_package *
31.910 -razor_set_get_package(struct razor_set *set, const char *package)
31.911 -{
31.912 - struct razor_package_iterator *pi;
31.913 - struct razor_package *p;
31.914 - const char *name, *version, *arch;
31.915 -
31.916 - pi = razor_package_iterator_create(set);
31.917 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
31.918 - if (strcmp(package, name) == 0)
31.919 - break;
31.920 - }
31.921 - razor_package_iterator_destroy(pi);
31.922 -
31.923 - return p;
31.924 -}
31.925 -
31.926 -struct razor_property_iterator {
31.927 - struct razor_set *set;
31.928 - struct razor_property *property, *end;
31.929 - struct list *index;
31.930 -};
31.931 -
31.932 -struct razor_property_iterator *
31.933 -razor_property_iterator_create(struct razor_set *set,
31.934 - struct razor_package *package)
31.935 -{
31.936 - struct razor_property_iterator *pi;
31.937 -
31.938 - pi = zalloc(sizeof *pi);
31.939 - pi->set = set;
31.940 -
31.941 - if (package) {
31.942 - pi->index = list_first(&package->properties,
31.943 - &set->property_pool);
31.944 - } else {
31.945 - pi->property = set->properties.data;
31.946 - pi->end = set->properties.data + set->properties.size;
31.947 - }
31.948 -
31.949 - return pi;
31.950 -}
31.951 -
31.952 -int
31.953 -razor_property_iterator_next(struct razor_property_iterator *pi,
31.954 - struct razor_property **property,
31.955 - const char **name,
31.956 - enum razor_version_relation *relation,
31.957 - const char **version,
31.958 - enum razor_property_type *type)
31.959 -{
31.960 - char *pool;
31.961 - int valid;
31.962 - struct razor_property *p, *properties;
31.963 -
31.964 - if (pi->property) {
31.965 - p = pi->property++;
31.966 - valid = p < pi->end;
31.967 - } else if (pi->index) {
31.968 - properties = pi->set->properties.data;
31.969 - p = &properties[pi->index->data];
31.970 - pi->index = list_next(pi->index);
31.971 - valid = 1;
31.972 - } else
31.973 - valid = 0;
31.974 -
31.975 - if (valid) {
31.976 - pool = pi->set->string_pool.data;
31.977 - *property = p;
31.978 - *name = &pool[p->name];
31.979 - *relation = p->relation;
31.980 - *version = &pool[p->version];
31.981 - *type = p->type;
31.982 - } else {
31.983 - *property = NULL;
31.984 - }
31.985 -
31.986 - return valid;
31.987 -}
31.988 -
31.989 -void
31.990 -razor_property_iterator_destroy(struct razor_property_iterator *pi)
31.991 -{
31.992 - free(pi);
31.993 -}
31.994 -
31.995 -static struct razor_entry *
31.996 -find_entry(struct razor_set *set, struct razor_entry *dir, const char *pattern)
31.997 -{
31.998 - struct razor_entry *e;
31.999 - const char *n, *pool = set->string_pool.data;
31.1000 - int len;
31.1001 -
31.1002 - e = (struct razor_entry *) set->files.data + dir->start;
31.1003 - do {
31.1004 - n = pool + e->name;
31.1005 - if (strcmp(pattern + 1, n) == 0)
31.1006 - return e;
31.1007 - len = strlen(n);
31.1008 - if (e->start != 0 && strncmp(pattern + 1, n, len) == 0 &&
31.1009 - pattern[len + 1] == '/') {
31.1010 - return find_entry(set, e, pattern + len + 1);
31.1011 - }
31.1012 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
31.1013 -
31.1014 - return NULL;
31.1015 -}
31.1016 -
31.1017 -static void
31.1018 -list_dir(struct razor_set *set, struct razor_entry *dir,
31.1019 - char *prefix, const char *pattern)
31.1020 -{
31.1021 - struct razor_entry *e;
31.1022 - const char *n, *pool = set->string_pool.data;
31.1023 -
31.1024 - e = (struct razor_entry *) set->files.data + dir->start;
31.1025 - do {
31.1026 - n = pool + e->name;
31.1027 - if (pattern && pattern[0] && fnmatch(pattern, n, 0) != 0)
31.1028 - continue;
31.1029 - printf("%s/%s\n", prefix, n);
31.1030 - if (e->start) {
31.1031 - char *sub = prefix + strlen (prefix);
31.1032 - *sub = '/';
31.1033 - strcpy (sub + 1, n);
31.1034 - list_dir(set, e, prefix, pattern);
31.1035 - *sub = '\0';
31.1036 - }
31.1037 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
31.1038 -}
31.1039 -
31.1040 -void
31.1041 -razor_set_list_files(struct razor_set *set, const char *pattern)
31.1042 -{
31.1043 - struct razor_entry *e;
31.1044 - char buffer[512], *p, *base;
31.1045 -
31.1046 - if (pattern == NULL || !strcmp (pattern, "/")) {
31.1047 - buffer[0] = '\0';
31.1048 - list_dir(set, set->files.data, buffer, NULL);
31.1049 - return;
31.1050 - }
31.1051 -
31.1052 - strcpy(buffer, pattern);
31.1053 - e = find_entry(set, set->files.data, buffer);
31.1054 - if (e && e->start > 0) {
31.1055 - base = NULL;
31.1056 - } else {
31.1057 - p = strrchr(buffer, '/');
31.1058 - if (p) {
31.1059 - *p = '\0';
31.1060 - base = p + 1;
31.1061 - } else {
31.1062 - base = NULL;
31.1063 - }
31.1064 - }
31.1065 - e = find_entry(set, set->files.data, buffer);
31.1066 - if (e->start != 0)
31.1067 - list_dir(set, e, buffer, base);
31.1068 -}
31.1069 -
31.1070 -struct razor_package_iterator *
31.1071 -razor_package_iterator_create_for_file(struct razor_set *set,
31.1072 - const char *filename)
31.1073 -{
31.1074 - struct razor_entry *entry;
31.1075 - struct list *index;
31.1076 -
31.1077 - entry = find_entry(set, set->files.data, filename);
31.1078 - if (entry == NULL)
31.1079 - return NULL;
31.1080 -
31.1081 - index = list_first(&entry->packages, &set->package_pool);
31.1082 - return razor_package_iterator_create_with_index(set, index);
31.1083 -}
31.1084 -
31.1085 -static struct list *
31.1086 -list_package_files(struct razor_set *set, struct list *r,
31.1087 - struct razor_entry *dir, uint32_t end,
31.1088 - char *prefix)
31.1089 -{
31.1090 - struct razor_entry *e, *f, *entries;
31.1091 - uint32_t next, file;
31.1092 - char *pool;
31.1093 - int len;
31.1094 -
31.1095 - entries = (struct razor_entry *) set->files.data;
31.1096 - pool = set->string_pool.data;
31.1097 -
31.1098 - e = entries + dir->start;
31.1099 - do {
31.1100 - if (entries + r->data == e) {
31.1101 - printf("%s/%s\n", prefix, pool + e->name);
31.1102 - r = list_next(r);
31.1103 - if (!r)
31.1104 - return NULL;
31.1105 - if (r->data >= end)
31.1106 - return r;
31.1107 - }
31.1108 - } while (!((e++)->flags & RAZOR_ENTRY_LAST));
31.1109 -
31.1110 - e = entries + dir->start;
31.1111 - do {
31.1112 - if (e->start == 0)
31.1113 - continue;
31.1114 -
31.1115 - if (e->flags & RAZOR_ENTRY_LAST)
31.1116 - next = end;
31.1117 - else {
31.1118 - f = e + 1;
31.1119 - while (f->start == 0 && !(f->flags & RAZOR_ENTRY_LAST))
31.1120 - f++;
31.1121 - if (f->start == 0)
31.1122 - next = end;
31.1123 - else
31.1124 - next = f->start;
31.1125 - }
31.1126 -
31.1127 - file = r->data;
31.1128 - if (e->start <= file && file < next) {
31.1129 - len = strlen(prefix);
31.1130 - prefix[len] = '/';
31.1131 - strcpy(prefix + len + 1, pool + e->name);
31.1132 - r = list_package_files(set, r, e, next, prefix);
31.1133 - prefix[len] = '\0';
31.1134 - }
31.1135 - } while (!((e++)->flags & RAZOR_ENTRY_LAST) && r != NULL);
31.1136 -
31.1137 - return r;
31.1138 -}
31.1139 -
31.1140 -void
31.1141 -razor_set_list_package_files(struct razor_set *set, const char *name)
31.1142 -{
31.1143 - struct razor_package *package;
31.1144 - struct list *r;
31.1145 - uint32_t end;
31.1146 - char buffer[512];
31.1147 -
31.1148 - package = razor_set_get_package(set, name);
31.1149 -
31.1150 - r = list_first(&package->files, &set->file_pool);
31.1151 - end = set->files.size / sizeof (struct razor_entry);
31.1152 - buffer[0] = '\0';
31.1153 - list_package_files(set, r, set->files.data, end, buffer);
31.1154 -}
31.1155 -
31.1156 -#define UPSTREAM_SOURCE 0x80
31.1157 -
31.1158 -struct source {
31.1159 - struct razor_set *set;
31.1160 - uint32_t *property_map;
31.1161 - uint32_t *file_map;
31.1162 -};
31.1163 -
31.1164 -struct razor_merger {
31.1165 - struct razor_set *set;
31.1166 - struct hashtable table;
31.1167 - struct source source1;
31.1168 - struct source source2;
31.1169 -};
31.1170 -
31.1171 -static struct razor_merger *
31.1172 -razor_merger_create(struct razor_set *set1, struct razor_set *set2)
31.1173 -{
31.1174 - struct razor_merger *merger;
31.1175 - int count;
31.1176 - size_t size;
31.1177 -
31.1178 - merger = zalloc(sizeof *merger);
31.1179 - merger->set = razor_set_create();
31.1180 - hashtable_init(&merger->table, &merger->set->string_pool);
31.1181 -
31.1182 - merger->source1.set = set1;
31.1183 - count = set1->properties.size / sizeof (struct razor_property);
31.1184 - size = count * sizeof merger->source1.property_map[0];
31.1185 - merger->source1.property_map = zalloc(size);
31.1186 - count = set1->files.size / sizeof (struct razor_entry);
31.1187 - size = count * sizeof merger->source1.file_map[0];
31.1188 - merger->source1.file_map = zalloc(size);
31.1189 -
31.1190 - merger->source2.set = set2;
31.1191 - count = set2->properties.size / sizeof (struct razor_property);
31.1192 - size = count * sizeof merger->source2.property_map[0];
31.1193 - merger->source2.property_map = zalloc(size);
31.1194 - count = set2->files.size / sizeof (struct razor_entry);
31.1195 - size = count * sizeof merger->source2.file_map[0];
31.1196 - merger->source2.file_map = zalloc(size);
31.1197 -
31.1198 - return merger;
31.1199 -}
31.1200 -
31.1201 -static void
31.1202 -razor_merger_add_package(struct razor_merger *merger,
31.1203 - struct razor_package *package)
31.1204 -{
31.1205 - char *pool;
31.1206 - struct list *r;
31.1207 - struct razor_package *p;
31.1208 - struct razor_set *set1;
31.1209 - struct source *source;
31.1210 - uint32_t flags;
31.1211 -
31.1212 - set1 = merger->source1.set;
31.1213 - if (set1->packages.data <= (void *) package &&
31.1214 - (void *) package < set1->packages.data + set1->packages.size) {
31.1215 - source = &merger->source1;
31.1216 - flags = 0;
31.1217 - } else {
31.1218 - source = &merger->source2;
31.1219 - flags = UPSTREAM_SOURCE;
31.1220 - }
31.1221 -
31.1222 - pool = source->set->string_pool.data;
31.1223 - p = array_add(&merger->set->packages, sizeof *p);
31.1224 - p->name = hashtable_tokenize(&merger->table, &pool[package->name]);
31.1225 - p->flags = flags;
31.1226 - p->version = hashtable_tokenize(&merger->table,
31.1227 - &pool[package->version]);
31.1228 - p->arch = hashtable_tokenize(&merger->table,
31.1229 - &pool[package->arch]);
31.1230 -
31.1231 - p->properties = package->properties;
31.1232 - r = list_first(&package->properties, &source->set->property_pool);
31.1233 - while (r) {
31.1234 - source->property_map[r->data] = 1;
31.1235 - r = list_next(r);
31.1236 - }
31.1237 -
31.1238 - p->files = package->files;
31.1239 - r = list_first(&package->files, &source->set->file_pool);
31.1240 - while (r) {
31.1241 - source->file_map[r->data] = 1;
31.1242 - r = list_next(r);
31.1243 - }
31.1244 -}
31.1245 -
31.1246 -static uint32_t
31.1247 -add_property(struct razor_merger *merger,
31.1248 - const char *name, enum razor_version_relation relation,
31.1249 - const char *version, int type)
31.1250 -{
31.1251 - struct razor_property *p;
31.1252 -
31.1253 - p = array_add(&merger->set->properties, sizeof *p);
31.1254 - p->name = hashtable_tokenize(&merger->table, name);
31.1255 - p->flags = 0;
31.1256 - p->type = type;
31.1257 - p->relation = relation;
31.1258 - p->version = hashtable_tokenize(&merger->table, version);
31.1259 -
31.1260 - return p - (struct razor_property *) merger->set->properties.data;
31.1261 -}
31.1262 -
31.1263 -static void
31.1264 -merge_properties(struct razor_merger *merger)
31.1265 -{
31.1266 - struct razor_property *p1, *p2;
31.1267 - struct razor_set *set1, *set2;
31.1268 - uint32_t *map1, *map2;
31.1269 - int i, j, cmp, count1, count2;
31.1270 - char *pool1, *pool2;
31.1271 -
31.1272 - set1 = merger->source1.set;
31.1273 - set2 = merger->source2.set;
31.1274 - map1 = merger->source1.property_map;
31.1275 - map2 = merger->source2.property_map;
31.1276 -
31.1277 - i = 0;
31.1278 - j = 0;
31.1279 - pool1 = set1->string_pool.data;
31.1280 - pool2 = set2->string_pool.data;
31.1281 -
31.1282 - count1 = set1->properties.size / sizeof *p1;
31.1283 - count2 = set2->properties.size / sizeof *p2;
31.1284 - while (i < count1 || j < count2) {
31.1285 - if (i < count1 && map1[i] == 0) {
31.1286 - i++;
31.1287 - continue;
31.1288 - }
31.1289 - if (j < count2 && map2[j] == 0) {
31.1290 - j++;
31.1291 - continue;
31.1292 - }
31.1293 - p1 = (struct razor_property *) set1->properties.data + i;
31.1294 - p2 = (struct razor_property *) set2->properties.data + j;
31.1295 - if (i < count1 && j < count2)
31.1296 - cmp = strcmp(&pool1[p1->name], &pool2[p2->name]);
31.1297 - else if (i < count1)
31.1298 - cmp = -1;
31.1299 - else
31.1300 - cmp = 1;
31.1301 - if (cmp == 0)
31.1302 - cmp = p1->type - p2->type;
31.1303 - if (cmp == 0)
31.1304 - cmp = p1->relation - p2->relation;
31.1305 - if (cmp == 0)
31.1306 - cmp = versioncmp(&pool1[p1->version],
31.1307 - &pool2[p2->version]);
31.1308 - if (cmp < 0) {
31.1309 - map1[i++] = add_property(merger,
31.1310 - &pool1[p1->name],
31.1311 - p1->relation,
31.1312 - &pool1[p1->version],
31.1313 - p1->type);
31.1314 - } else if (cmp > 0) {
31.1315 - map2[j++] = add_property(merger,
31.1316 - &pool2[p2->name],
31.1317 - p2->relation,
31.1318 - &pool2[p2->version],
31.1319 - p2->type);
31.1320 - } else {
31.1321 - map1[i++] = map2[j++] = add_property(merger,
31.1322 - &pool1[p1->name],
31.1323 - p1->relation,
31.1324 - &pool1[p1->version],
31.1325 - p1->type);
31.1326 - }
31.1327 - }
31.1328 -}
31.1329 -
31.1330 -static void
31.1331 -emit_properties(struct list_head *properties, struct array *source_pool,
31.1332 - uint32_t *map, struct array *pool)
31.1333 -{
31.1334 - uint32_t r;
31.1335 - struct list *p, *q;
31.1336 -
31.1337 - r = pool->size / sizeof *q;
31.1338 - p = list_first(properties, source_pool);
31.1339 - while (p) {
31.1340 - q = array_add(pool, sizeof *q);
31.1341 - q->data = map[p->data];
31.1342 - q->flags = p->flags;
31.1343 - p = list_next(p);
31.1344 - }
31.1345 -
31.1346 - list_set_ptr(properties, r);
31.1347 -}
31.1348 -
31.1349 -static uint32_t
31.1350 -add_file(struct razor_merger *merger, const char *name)
31.1351 -{
31.1352 - struct razor_entry *e;
31.1353 -
31.1354 - e = array_add(&merger->set->files, sizeof *e);
31.1355 - e->name = hashtable_tokenize(&merger->table, name);
31.1356 - e->flags = 0;
31.1357 - e->start = 0;
31.1358 -
31.1359 - return e - (struct razor_entry *)merger->set->files.data;
31.1360 -}
31.1361 -
31.1362 -/* FIXME. Blah */
31.1363 -static int
31.1364 -fix_file_map(uint32_t *map,
31.1365 - struct razor_entry *files,
31.1366 - struct razor_entry *top)
31.1367 -{
31.1368 - uint32_t e;
31.1369 - int found_file = 0;
31.1370 -
31.1371 - e = top->start;
31.1372 - do {
31.1373 - if (files[e].start)
31.1374 - fix_file_map(map, files, &files[e]);
31.1375 - if (map[e])
31.1376 - found_file = 1;
31.1377 - } while (!(files[e++].flags & RAZOR_ENTRY_LAST));
31.1378 -
31.1379 - if (found_file)
31.1380 - map[top - files] = 1;
31.1381 - return found_file;
31.1382 -}
31.1383 -
31.1384 -struct merge_directory {
31.1385 - uint32_t merged, dir1, dir2;
31.1386 -};
31.1387 -
31.1388 -static void
31.1389 -merge_one_directory(struct razor_merger *merger, struct merge_directory *md)
31.1390 -{
31.1391 - struct razor_entry *root1, *root2, *mroot, *e1, *e2;
31.1392 - struct razor_set *set1, *set2;
31.1393 - struct array merge_stack;
31.1394 - struct merge_directory *child_md, *end_md;
31.1395 - uint32_t *map1, *map2, start, last;
31.1396 - int cmp;
31.1397 - char *pool1, *pool2;
31.1398 -
31.1399 - set1 = merger->source1.set;
31.1400 - set2 = merger->source2.set;
31.1401 - map1 = merger->source1.file_map;
31.1402 - map2 = merger->source2.file_map;
31.1403 - pool1 = set1->string_pool.data;
31.1404 - pool2 = set2->string_pool.data;
31.1405 - root1 = (struct razor_entry *) set1->files.data;
31.1406 - root2 = (struct razor_entry *) set2->files.data;
31.1407 -
31.1408 - array_init(&merge_stack);
31.1409 -
31.1410 - start = merger->set->files.size / sizeof (struct razor_entry);
31.1411 - last = 0;
31.1412 - e1 = md->dir1 ? root1 + md->dir1 : NULL;
31.1413 - e2 = md->dir2 ? root2 + md->dir2 : NULL;
31.1414 - while (e1 || e2) {
31.1415 - if (!e2 && !map1[e1 - root1]) {
31.1416 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
31.1417 - e1 = NULL;
31.1418 - continue;
31.1419 - }
31.1420 - if (!e1 && !map2[e2 - root2]) {
31.1421 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
31.1422 - e2 = NULL;
31.1423 - continue;
31.1424 - }
31.1425 - if (e1 && !map1[e1 - root1] &&
31.1426 - e2 && !map1[e2 - root2]) {
31.1427 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
31.1428 - e1 = NULL;
31.1429 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
31.1430 - e2 = NULL;
31.1431 - continue;
31.1432 - }
31.1433 -
31.1434 - if (!e1)
31.1435 - cmp = 1;
31.1436 - else if (!e2)
31.1437 - cmp = -1;
31.1438 - else {
31.1439 - cmp = strcmp (&pool1[e1->name],
31.1440 - &pool2[e2->name]);
31.1441 - }
31.1442 -
31.1443 - if (cmp < 0) {
31.1444 - if (map1[e1 - root1]) {
31.1445 - map1[e1 - root1] = last =
31.1446 - add_file(merger, &pool1[e1->name]);
31.1447 - if (e1->start) {
31.1448 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
31.1449 - child_md->merged = last;
31.1450 - child_md->dir1 = e1->start;
31.1451 - child_md->dir2 = 0;
31.1452 - }
31.1453 - }
31.1454 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
31.1455 - e1 = NULL;
31.1456 - } else if (cmp > 0) {
31.1457 - if (map2[e2 - root2]) {
31.1458 - map2[e2 - root2] = last =
31.1459 - add_file(merger, &pool2[e2->name]);
31.1460 - if (e2->start) {
31.1461 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
31.1462 - child_md->merged = last;
31.1463 - child_md->dir1 = 0;
31.1464 - child_md->dir2 = e2->start;
31.1465 - }
31.1466 - }
31.1467 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
31.1468 - e2 = NULL;
31.1469 - } else {
31.1470 - map1[e1 - root1] = map2[e2- root2] = last =
31.1471 - add_file(merger, &pool1[e1->name]);
31.1472 - if (e1->start || e2->start) {
31.1473 - child_md = array_add(&merge_stack, sizeof (struct merge_directory));
31.1474 - child_md->merged = last;
31.1475 - child_md->dir1 = e1->start;
31.1476 - child_md->dir2 = e2->start;
31.1477 - }
31.1478 - if ((e1++)->flags & RAZOR_ENTRY_LAST)
31.1479 - e1 = NULL;
31.1480 - if ((e2++)->flags & RAZOR_ENTRY_LAST)
31.1481 - e2 = NULL;
31.1482 - }
31.1483 - }
31.1484 -
31.1485 - mroot = (struct razor_entry *)merger->set->files.data;
31.1486 - if (last) {
31.1487 - mroot[last].flags = RAZOR_ENTRY_LAST;
31.1488 - mroot[md->merged].start = start;
31.1489 - } else
31.1490 - mroot[md->merged].start = 0;
31.1491 -
31.1492 - end_md = merge_stack.data + merge_stack.size;
31.1493 - for (child_md = merge_stack.data; child_md < end_md; child_md++)
31.1494 - merge_one_directory(merger, child_md);
31.1495 - array_release(&merge_stack);
31.1496 -}
31.1497 -
31.1498 -static void
31.1499 -merge_files(struct razor_merger *merger)
31.1500 -{
31.1501 - struct razor_entry *root;
31.1502 - struct merge_directory md;
31.1503 - uint32_t *map1, *map2;
31.1504 -
31.1505 - map1 = merger->source1.file_map;
31.1506 - map2 = merger->source2.file_map;
31.1507 -
31.1508 - md.merged = 0;
31.1509 -
31.1510 - if (merger->source1.set->files.size) {
31.1511 - root = (struct razor_entry *) merger->source1.set->files.data;
31.1512 - if (root->start)
31.1513 - fix_file_map(map1, root, root);
31.1514 - md.dir1 = root->start;
31.1515 - } else
31.1516 - md.dir1 = 0;
31.1517 -
31.1518 - if (merger->source2.set->files.size) {
31.1519 - root = (struct razor_entry *) merger->source2.set->files.data;
31.1520 - if (root->start)
31.1521 - fix_file_map(map2, root, root);
31.1522 - md.dir2 = root->start;
31.1523 - } else
31.1524 - md.dir2 = 0;
31.1525 -
31.1526 - merge_one_directory(merger, &md);
31.1527 -}
31.1528 -
31.1529 -static void
31.1530 -emit_files(struct list_head *files, struct array *source_pool,
31.1531 - uint32_t *map, struct array *pool)
31.1532 -{
31.1533 - uint32_t r;
31.1534 - struct list *p, *q;
31.1535 -
31.1536 - r = pool->size / sizeof *q;
31.1537 - p = list_first(files, source_pool);
31.1538 - while (p) {
31.1539 - q = array_add(pool, sizeof *q);
31.1540 - q->data = map[p->data];
31.1541 - q->flags = p->flags;
31.1542 - p = list_next(p);
31.1543 - }
31.1544 -
31.1545 - list_set_ptr(files, r);
31.1546 -}
31.1547 -
31.1548 -/* Rebuild property->packages maps. We can't just remap these, as a
31.1549 - * property may have lost or gained a number of packages. Allocate an
31.1550 - * array per property and loop through the packages and add them to
31.1551 - * the arrays for their properties. */
31.1552 -static void
31.1553 -rebuild_property_package_lists(struct razor_set *set)
31.1554 -{
31.1555 - struct array *pkgs, *a;
31.1556 - struct razor_package *pkg, *pkg_end;
31.1557 - struct razor_property *prop, *prop_end;
31.1558 - struct list *r;
31.1559 - uint32_t *q;
31.1560 - int count;
31.1561 -
31.1562 - count = set->properties.size / sizeof (struct razor_property);
31.1563 - pkgs = zalloc(count * sizeof *pkgs);
31.1564 - pkg_end = set->packages.data + set->packages.size;
31.1565 -
31.1566 - for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
31.1567 - r = list_first(&pkg->properties, &set->property_pool);
31.1568 - while (r) {
31.1569 - q = array_add(&pkgs[r->data], sizeof *q);
31.1570 - *q = pkg - (struct razor_package *) set->packages.data;
31.1571 - r = list_next(r);
31.1572 - }
31.1573 - }
31.1574 -
31.1575 - prop_end = set->properties.data + set->properties.size;
31.1576 - a = pkgs;
31.1577 - for (prop = set->properties.data; prop < prop_end; prop++, a++) {
31.1578 - list_set_array(&prop->packages, &set->package_pool, a, 0);
31.1579 - array_release(a);
31.1580 - }
31.1581 - free(pkgs);
31.1582 -}
31.1583 -
31.1584 -static void
31.1585 -rebuild_file_package_lists(struct razor_set *set)
31.1586 -{
31.1587 - struct array *pkgs, *a;
31.1588 - struct razor_package *pkg, *pkg_end;
31.1589 - struct razor_entry *entry, *entry_end;
31.1590 - struct list *r;
31.1591 - uint32_t *q;
31.1592 - int count;
31.1593 -
31.1594 - count = set->files.size / sizeof (struct razor_entry);
31.1595 - pkgs = zalloc(count * sizeof *pkgs);
31.1596 - pkg_end = set->packages.data + set->packages.size;
31.1597 -
31.1598 - for (pkg = set->packages.data; pkg < pkg_end; pkg++) {
31.1599 - r = list_first(&pkg->files, &set->file_pool);
31.1600 - while (r) {
31.1601 - q = array_add(&pkgs[r->data], sizeof *q);
31.1602 - *q = pkg - (struct razor_package *) set->packages.data;
31.1603 - r = list_next(r);
31.1604 - }
31.1605 - }
31.1606 -
31.1607 - entry_end = set->files.data + set->files.size;
31.1608 - a = pkgs;
31.1609 - for (entry = set->files.data; entry < entry_end; entry++, a++) {
31.1610 - list_set_array(&entry->packages, &set->package_pool, a, 0);
31.1611 - array_release(a);
31.1612 - }
31.1613 - free(pkgs);
31.1614 -}
31.1615 -
31.1616 -static struct razor_set *
31.1617 -razor_merger_finish(struct razor_merger *merger)
31.1618 -{
31.1619 - struct razor_set *result;
31.1620 - struct razor_package *p, *pend;
31.1621 -
31.1622 - /* As we built the package list, we filled out a bitvector of
31.1623 - * the properties that are referenced by the packages in the
31.1624 - * new set. Now we do a parallel loop through the properties
31.1625 - * and emit those marked in the bit vector to the new set. In
31.1626 - * the process, we update the bit vector to actually map from
31.1627 - * indices in the old property list to indices in the new
31.1628 - * property list for both sets. */
31.1629 -
31.1630 - merge_properties(merger);
31.1631 - merge_files(merger);
31.1632 -
31.1633 - /* Now we loop through the packages again and emit the
31.1634 - * property lists, remapped to point to the new properties. */
31.1635 -
31.1636 - pend = merger->set->packages.data + merger->set->packages.size;
31.1637 - for (p = merger->set->packages.data; p < pend; p++) {
31.1638 - struct source *src;
31.1639 -
31.1640 - if (p->flags & UPSTREAM_SOURCE)
31.1641 - src = &merger->source2;
31.1642 - else
31.1643 - src = &merger->source1;
31.1644 -
31.1645 - emit_properties(&p->properties,
31.1646 - &src->set->property_pool,
31.1647 - src->property_map,
31.1648 - &merger->set->property_pool);
31.1649 - emit_files(&p->files,
31.1650 - &src->set->file_pool,
31.1651 - src->file_map,
31.1652 - &merger->set->file_pool);
31.1653 - p->flags &= ~UPSTREAM_SOURCE;
31.1654 - }
31.1655 -
31.1656 - rebuild_property_package_lists(merger->set);
31.1657 - rebuild_file_package_lists(merger->set);
31.1658 -
31.1659 - result = merger->set;
31.1660 - hashtable_release(&merger->table);
31.1661 - free(merger);
31.1662 -
31.1663 - return result;
31.1664 -}
31.1665 -
31.1666 -/* The diff order matters. We should sort the packages so that a
31.1667 - * REMOVE of a package comes before the INSTALL, and so that all
31.1668 - * requires for a package have been installed before the package.
31.1669 - **/
31.1670 -
31.1671 -void
31.1672 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
31.1673 - razor_package_callback_t callback, void *data)
31.1674 -{
31.1675 - struct razor_package_iterator *pi1, *pi2;
31.1676 - struct razor_package *p1, *p2;
31.1677 - const char *name1, *name2, *version1, *version2, *arch1, *arch2;
31.1678 - int res;
31.1679 -
31.1680 - pi1 = razor_package_iterator_create(set);
31.1681 - pi2 = razor_package_iterator_create(upstream);
31.1682 -
31.1683 - razor_package_iterator_next(pi1, &p1, &name1, &version1, &arch1);
31.1684 - razor_package_iterator_next(pi2, &p2, &name2, &version2, &arch2);
31.1685 -
31.1686 - while (p1 || p2) {
31.1687 - if (p1 && p2) {
31.1688 - res = strcmp(name1, name2);
31.1689 - if (res == 0)
31.1690 - res = versioncmp(version1, version2);
31.1691 - } else {
31.1692 - res = 0;
31.1693 - }
31.1694 -
31.1695 - if (p2 == NULL || res < 0)
31.1696 - callback(name1, version1, NULL, arch1, data);
31.1697 - else if (p1 == NULL || res > 0)
31.1698 - callback(name2, NULL, version2, arch2, data);
31.1699 -
31.1700 - if (p1 != NULL && res <= 0)
31.1701 - razor_package_iterator_next(pi1, &p1,
31.1702 - &name1, &version1, &arch1);
31.1703 - if (p2 != NULL && res >= 0)
31.1704 - razor_package_iterator_next(pi2, &p2,
31.1705 - &name2, &version2, &arch2);
31.1706 - }
31.1707 -
31.1708 - razor_package_iterator_destroy(pi1);
31.1709 - razor_package_iterator_destroy(pi2);
31.1710 -}
31.1711 -
31.1712 -static int
31.1713 -provider_satisfies_requirement(struct razor_property *provider,
31.1714 - const char *provider_strings,
31.1715 - enum razor_version_relation relation,
31.1716 - const char *required)
31.1717 -{
31.1718 - int cmp, len;
31.1719 - const char *provided = &provider_strings[provider->version];
31.1720 -
31.1721 - if (!*required)
31.1722 - return 1;
31.1723 - if (!*provided) {
31.1724 - if (relation >= RAZOR_VERSION_EQUAL)
31.1725 - return 1;
31.1726 - else
31.1727 - return 0;
31.1728 - }
31.1729 -
31.1730 - cmp = versioncmp(provided, required);
31.1731 -
31.1732 - switch (relation) {
31.1733 - case RAZOR_VERSION_LESS:
31.1734 - return cmp < 0;
31.1735 -
31.1736 - case RAZOR_VERSION_LESS_OR_EQUAL:
31.1737 - if (cmp <= 0)
31.1738 - return 1;
31.1739 - /* fall through: FIXME, make sure this is correct */
31.1740 -
31.1741 - case RAZOR_VERSION_EQUAL:
31.1742 - if (cmp == 0)
31.1743 - return 1;
31.1744 -
31.1745 - /* "foo == 1.1" is satisfied by "foo 1.1-2" */
31.1746 - len = strlen(required);
31.1747 - if (!strncmp(required, provided, len) && provided[len] == '-')
31.1748 - return 1;
31.1749 - return 0;
31.1750 -
31.1751 - case RAZOR_VERSION_GREATER_OR_EQUAL:
31.1752 - return cmp >= 0;
31.1753 -
31.1754 - case RAZOR_VERSION_GREATER:
31.1755 - return cmp > 0;
31.1756 - }
31.1757 -
31.1758 - /* shouldn't happen */
31.1759 - return 0;
31.1760 -}
31.1761 -
31.1762 -#define TRANS_PACKAGE_PRESENT 1
31.1763 -#define TRANS_PACKAGE_UPDATE 2
31.1764 -#define TRANS_PROPERTY_SATISFIED 0x80000000
31.1765 -
31.1766 -struct transaction_set {
31.1767 - struct razor_set *set;
31.1768 - uint32_t *packages;
31.1769 - uint32_t *properties;
31.1770 -};
31.1771 -
31.1772 -struct razor_transaction {
31.1773 - int package_count, errors;
31.1774 - struct transaction_set system, upstream;
31.1775 - int changes;
31.1776 -};
31.1777 -
31.1778 -static void
31.1779 -transaction_set_init(struct transaction_set *ts, struct razor_set *set)
31.1780 -{
31.1781 - int count;
31.1782 -
31.1783 - ts->set = set;
31.1784 - count = set->packages.size / sizeof (struct razor_package);
31.1785 - ts->packages = zalloc(count * sizeof *ts->packages);
31.1786 - count = set->properties.size / sizeof (struct razor_property);
31.1787 - ts->properties = zalloc(count * sizeof *ts->properties);
31.1788 -}
31.1789 -
31.1790 -static void
31.1791 -transaction_set_release(struct transaction_set *ts)
31.1792 -{
31.1793 - free(ts->packages);
31.1794 - free(ts->properties);
31.1795 -}
31.1796 -
31.1797 -static void
31.1798 -transaction_set_install_package(struct transaction_set *ts,
31.1799 - struct razor_package *package)
31.1800 -{
31.1801 - struct razor_package *pkgs;
31.1802 - struct list *prop;
31.1803 - int i;
31.1804 -
31.1805 - pkgs = ts->set->packages.data;
31.1806 - i = package - pkgs;
31.1807 - if (ts->packages[i] == TRANS_PACKAGE_PRESENT)
31.1808 - return;
31.1809 -
31.1810 - ts->packages[i] = TRANS_PACKAGE_PRESENT;
31.1811 -
31.1812 - prop = list_first(&package->properties, &ts->set->property_pool);
31.1813 - while (prop) {
31.1814 - ts->properties[prop->data]++;
31.1815 - prop = list_next(prop);
31.1816 - }
31.1817 -}
31.1818 -
31.1819 -static void
31.1820 -transaction_set_remove_package(struct transaction_set *ts,
31.1821 - struct razor_package *package)
31.1822 -{
31.1823 - struct razor_package *pkgs;
31.1824 - struct list *prop;
31.1825 - int i;
31.1826 -
31.1827 - pkgs = ts->set->packages.data;
31.1828 - i = package - pkgs;
31.1829 - if (ts->packages[i] == 0)
31.1830 - return;
31.1831 -
31.1832 - ts->packages[i] = 0;
31.1833 -
31.1834 - prop = list_first(&package->properties, &ts->set->property_pool);
31.1835 - while (prop) {
31.1836 - ts->properties[prop->data]--;
31.1837 - prop = list_next(prop);
31.1838 - }
31.1839 -}
31.1840 -
31.1841 -struct razor_transaction *
31.1842 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream)
31.1843 -{
31.1844 - struct razor_transaction *trans;
31.1845 - struct razor_package *p, *spkgs, *pend;
31.1846 -
31.1847 - trans = zalloc(sizeof *trans);
31.1848 - transaction_set_init(&trans->system, system);
31.1849 - transaction_set_init(&trans->upstream, upstream);
31.1850 -
31.1851 - spkgs = trans->system.set->packages.data;
31.1852 - pend = trans->system.set->packages.data +
31.1853 - trans->system.set->packages.size;
31.1854 - for (p = spkgs; p < pend; p++)
31.1855 - transaction_set_install_package(&trans->system, p);
31.1856 -
31.1857 - return trans;
31.1858 -}
31.1859 -
31.1860 -void
31.1861 -razor_transaction_install_package(struct razor_transaction *trans,
31.1862 - struct razor_package *package)
31.1863 -{
31.1864 - transaction_set_install_package(&trans->upstream, package);
31.1865 - trans->changes++;
31.1866 -}
31.1867 -
31.1868 -void
31.1869 -razor_transaction_remove_package(struct razor_transaction *trans,
31.1870 - struct razor_package *package)
31.1871 -{
31.1872 - transaction_set_remove_package(&trans->system, package);
31.1873 - trans->changes++;
31.1874 -}
31.1875 -
31.1876 -void
31.1877 -razor_transaction_update_package(struct razor_transaction *trans,
31.1878 - struct razor_package *package)
31.1879 -{
31.1880 - struct razor_package *spkgs, *upkgs, *end;
31.1881 -
31.1882 - spkgs = trans->system.set->packages.data;
31.1883 - upkgs = trans->upstream.set->packages.data;
31.1884 - end = trans->system.set->packages.data +
31.1885 - trans->system.set->packages.size;
31.1886 - if (spkgs <= package && package < end)
31.1887 - trans->system.packages[package - spkgs] |= TRANS_PACKAGE_UPDATE;
31.1888 - else
31.1889 - trans->upstream.packages[package - upkgs] |= TRANS_PACKAGE_UPDATE;
31.1890 -}
31.1891 -
31.1892 -struct prop_iter {
31.1893 - struct razor_property *p, *start, *end;
31.1894 - const char *pool;
31.1895 - uint32_t *present;
31.1896 -};
31.1897 -
31.1898 -static void
31.1899 -prop_iter_init(struct prop_iter *pi, struct transaction_set *ts)
31.1900 -{
31.1901 - pi->p = ts->set->properties.data;
31.1902 - pi->start = ts->set->properties.data;
31.1903 - pi->end = ts->set->properties.data + ts->set->properties.size;
31.1904 - pi->pool = ts->set->string_pool.data;
31.1905 - pi->present = ts->properties;
31.1906 -}
31.1907 -
31.1908 -static int
31.1909 -prop_iter_next(struct prop_iter *pi,
31.1910 - enum razor_property_type type, struct razor_property **p)
31.1911 -{
31.1912 - while (pi->p < pi->end) {
31.1913 - if ((pi->present[pi->p - pi->start] & ~TRANS_PROPERTY_SATISFIED) &&
31.1914 - pi->p->type == type) {
31.1915 - *p = pi->p++;
31.1916 - return 1;
31.1917 - }
31.1918 - pi->p++;
31.1919 - }
31.1920 -
31.1921 - return 0;
31.1922 -}
31.1923 -
31.1924 -static struct razor_property *
31.1925 -prop_iter_seek_to(struct prop_iter *pi,
31.1926 - enum razor_property_type type, const char *match)
31.1927 -{
31.1928 - uint32_t name;
31.1929 -
31.1930 - while (pi->p < pi->end && strcmp(&pi->pool[pi->p->name], match) < 0)
31.1931 - pi->p++;
31.1932 -
31.1933 - if (pi->p == pi->end || strcmp(&pi->pool[pi->p->name], match) > 0)
31.1934 - return NULL;
31.1935 -
31.1936 - name = pi->p->name;
31.1937 - while (pi->p < pi->end &&
31.1938 - pi->p->name == name &&
31.1939 - pi->p->type != type)
31.1940 - pi->p++;
31.1941 -
31.1942 - if (pi->p == pi->end || pi->p->name != name)
31.1943 - return NULL;
31.1944 -
31.1945 - return pi->p;
31.1946 -}
31.1947 -
31.1948 -/* Remove packages from set that provide any of the matching (same
31.1949 - * name and type) providers from ppi onwards that match the
31.1950 - * requirement that rpi points to. */
31.1951 -static void
31.1952 -remove_matching_providers(struct razor_transaction *trans,
31.1953 - struct prop_iter *ppi,
31.1954 - enum razor_version_relation relation,
31.1955 - const char *version)
31.1956 -{
31.1957 - struct razor_property *p;
31.1958 - struct razor_package *pkg, *pkgs;
31.1959 - struct razor_package_iterator pkg_iter;
31.1960 - struct razor_set *set;
31.1961 - const char *n, *v, *a;
31.1962 -
31.1963 - if (ppi->present == trans->system.properties)
31.1964 - set = trans->system.set;
31.1965 - else
31.1966 - set = trans->upstream.set;
31.1967 -
31.1968 - pkgs = (struct razor_package *) set->packages.data;
31.1969 - for (p = ppi->p;
31.1970 - p < ppi->end &&
31.1971 - p->name == ppi->p->name &&
31.1972 - p->type == ppi->p->type;
31.1973 - p++) {
31.1974 - if (!ppi->present[p - ppi->start])
31.1975 - continue;
31.1976 - if (!provider_satisfies_requirement(p, ppi->pool,
31.1977 - relation, version))
31.1978 - continue;
31.1979 -
31.1980 - razor_package_iterator_init_for_property(&pkg_iter, set, p);
31.1981 - while (razor_package_iterator_next(&pkg_iter,
31.1982 - &pkg, &n, &v, &a)) {
31.1983 - fprintf(stderr, "removing %s-%s\n", n, v);
31.1984 - razor_transaction_remove_package(trans, pkg);
31.1985 - }
31.1986 - }
31.1987 -}
31.1988 -
31.1989 -static void
31.1990 -flag_matching_providers(struct razor_transaction *trans,
31.1991 - struct prop_iter *ppi,
31.1992 - struct razor_property *r,
31.1993 - struct prop_iter *rpi,
31.1994 - unsigned int flag)
31.1995 -{
31.1996 - struct razor_property *p;
31.1997 - struct razor_package *pkg, *pkgs;
31.1998 - struct razor_package_iterator pkg_iter;
31.1999 - struct razor_set *set;
31.2000 - const char *name, *version, *arch;
31.2001 - uint32_t *flags;
31.2002 -
31.2003 - if (ppi->present == trans->system.properties) {
31.2004 - set = trans->system.set;
31.2005 - flags = trans->system.packages;
31.2006 - } else {
31.2007 - set = trans->upstream.set;
31.2008 - flags = trans->upstream.packages;
31.2009 - }
31.2010 -
31.2011 - pkgs = (struct razor_package *) set->packages.data;
31.2012 - for (p = ppi->p;
31.2013 - p < ppi->end &&
31.2014 - p->name == ppi->p->name &&
31.2015 - p->type == ppi->p->type;
31.2016 - p++) {
31.2017 - if (!ppi->present[p - ppi->start])
31.2018 - continue;
31.2019 - if (!provider_satisfies_requirement(p, ppi->pool,
31.2020 - r->relation,
31.2021 - &rpi->pool[r->version]))
31.2022 - continue;
31.2023 -
31.2024 - razor_package_iterator_init_for_property(&pkg_iter, set, p);
31.2025 - while (razor_package_iterator_next(&pkg_iter, &pkg,
31.2026 - &name, &version, &arch)) {
31.2027 -
31.2028 - fprintf(stderr, "flagging %s-%s for providing %s matching %s %s\n",
31.2029 - name, version,
31.2030 - ppi->pool + p->name,
31.2031 - rpi->pool + r->name,
31.2032 - rpi->pool + r->version);
31.2033 - flags[pkg - pkgs] |= flag;
31.2034 - }
31.2035 - }
31.2036 -}
31.2037 -
31.2038 -static struct razor_package *
31.2039 -pick_matching_provider(struct razor_set *set,
31.2040 - struct prop_iter *ppi,
31.2041 - enum razor_version_relation relation,
31.2042 - const char *version)
31.2043 -{
31.2044 - struct razor_property *p;
31.2045 - struct razor_package *pkgs;
31.2046 - struct list *i;
31.2047 -
31.2048 - /* This is where we decide which pkgs to pull in to satisfy a
31.2049 - * requirement. There may be several different providers
31.2050 - * (different versions) and each version of a provider may
31.2051 - * come from a number of packages. We pick the first package
31.2052 - * from the first provider that matches. */
31.2053 -
31.2054 - pkgs = set->packages.data;
31.2055 - for (p = ppi->p;
31.2056 - p < ppi->end &&
31.2057 - p->name == ppi->p->name &&
31.2058 - p->type == ppi->p->type &&
31.2059 - ppi->present[p - ppi->start] == 0;
31.2060 - p++) {
31.2061 - if (!provider_satisfies_requirement(p, ppi->pool,
31.2062 - relation, version))
31.2063 - continue;
31.2064 -
31.2065 - i = list_first(&p->packages, &set->package_pool);
31.2066 -
31.2067 - return &pkgs[i->data];
31.2068 - }
31.2069 -
31.2070 - return NULL;
31.2071 -}
31.2072 -
31.2073 -static void
31.2074 -remove_obsoleted_packages(struct razor_transaction *trans)
31.2075 -{
31.2076 - struct razor_property *up;
31.2077 - struct razor_package *spkgs;
31.2078 - struct prop_iter spi, upi;
31.2079 -
31.2080 - spkgs = trans->system.set->packages.data;
31.2081 - prop_iter_init(&spi, &trans->system);
31.2082 - prop_iter_init(&upi, &trans->upstream);
31.2083 -
31.2084 - while (prop_iter_next(&upi, RAZOR_PROPERTY_OBSOLETES, &up)) {
31.2085 - if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
31.2086 - &upi.pool[up->name]))
31.2087 - continue;
31.2088 - remove_matching_providers(trans, &spi, up->relation,
31.2089 - &upi.pool[up->version]);
31.2090 - }
31.2091 -}
31.2092 -
31.2093 -static int
31.2094 -any_provider_satisfies_requirement(struct prop_iter *ppi,
31.2095 - enum razor_version_relation relation,
31.2096 - const char *version)
31.2097 -{
31.2098 - struct razor_property *p;
31.2099 -
31.2100 - for (p = ppi->p;
31.2101 - p < ppi->end &&
31.2102 - p->name == ppi->p->name &&
31.2103 - p->type == ppi->p->type;
31.2104 - p++) {
31.2105 - if (ppi->present[p - ppi->start] > 0 &&
31.2106 - provider_satisfies_requirement(p, ppi->pool,
31.2107 - relation, version))
31.2108 - return 1;
31.2109 - }
31.2110 -
31.2111 - return 0;
31.2112 -}
31.2113 -
31.2114 -static void
31.2115 -clear_requires_flags(struct transaction_set *ts)
31.2116 -{
31.2117 - struct razor_property *p;
31.2118 - const char *pool;
31.2119 - int i, count;
31.2120 -
31.2121 - count = ts->set->properties.size / sizeof *p;
31.2122 - p = ts->set->properties.data;
31.2123 - pool = ts->set->string_pool.data;
31.2124 - for (i = 0; i < count; i++) {
31.2125 - ts->properties[i] &= ~TRANS_PROPERTY_SATISFIED;
31.2126 - if (strncmp(&pool[p[i].name], "rpmlib(", 7) == 0)
31.2127 - ts->properties[i] |= TRANS_PROPERTY_SATISFIED;
31.2128 - }
31.2129 -}
31.2130 -
31.2131 -static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
31.2132 -
31.2133 -static void
31.2134 -mark_satisfied_requires(struct razor_transaction *trans,
31.2135 - struct transaction_set *rts,
31.2136 - struct transaction_set *pts)
31.2137 -{
31.2138 - struct prop_iter rpi, ppi;
31.2139 - struct razor_property *rp;
31.2140 -
31.2141 - prop_iter_init(&rpi, rts);
31.2142 - prop_iter_init(&ppi, pts);
31.2143 -
31.2144 - while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
31.2145 - if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES,
31.2146 - &rpi.pool[rp->name]))
31.2147 - continue;
31.2148 -
31.2149 - if (any_provider_satisfies_requirement(&ppi, rp->relation,
31.2150 - &rpi.pool[rp->version]))
31.2151 - rpi.present[rp - rpi.start] |= TRANS_PROPERTY_SATISFIED;
31.2152 - }
31.2153 -}
31.2154 -
31.2155 -static void
31.2156 -mark_all_satisfied_requires(struct razor_transaction *trans)
31.2157 -{
31.2158 - clear_requires_flags(&trans->system);
31.2159 - clear_requires_flags(&trans->upstream);
31.2160 - mark_satisfied_requires(trans, &trans->system, &trans->system);
31.2161 - mark_satisfied_requires(trans, &trans->system, &trans->upstream);
31.2162 - mark_satisfied_requires(trans, &trans->upstream, &trans->system);
31.2163 - mark_satisfied_requires(trans, &trans->upstream, &trans->upstream);
31.2164 -}
31.2165 -
31.2166 -static void
31.2167 -update_unsatisfied_packages(struct razor_transaction *trans)
31.2168 -{
31.2169 - struct razor_package *spkgs, *pkg;
31.2170 - struct razor_property *sp;
31.2171 - struct prop_iter spi;
31.2172 - struct razor_package_iterator pkg_iter;
31.2173 - const char *name, *version, *arch;
31.2174 -
31.2175 - spkgs = trans->system.set->packages.data;
31.2176 - prop_iter_init(&spi, &trans->system);
31.2177 -
31.2178 - while (prop_iter_next(&spi, RAZOR_PROPERTY_REQUIRES, &sp)) {
31.2179 - if (spi.present[sp - spi.start] & TRANS_PROPERTY_SATISFIED)
31.2180 - continue;
31.2181 -
31.2182 - razor_package_iterator_init_for_property(&pkg_iter,
31.2183 - trans->system.set,
31.2184 - sp);
31.2185 - while (razor_package_iterator_next(&pkg_iter, &pkg,
31.2186 - &name, &version, &arch)) {
31.2187 - fprintf(stderr, "updating %s because %s %s %s "
31.2188 - "isn't satisfied\n",
31.2189 - name, spi.pool + sp->name,
31.2190 - relation_string[sp->relation],
31.2191 - spi.pool + sp->version);
31.2192 - trans->system.packages[pkg - spkgs] |=
31.2193 - TRANS_PACKAGE_UPDATE;
31.2194 - }
31.2195 - }
31.2196 -}
31.2197 -
31.2198 -void
31.2199 -razor_transaction_update_all(struct razor_transaction *trans)
31.2200 -{
31.2201 - struct razor_package *p;
31.2202 - int i, count;
31.2203 -
31.2204 - count = trans->system.set->packages.size / sizeof *p;
31.2205 - for (i = 0; i < count; i++)
31.2206 - trans->system.packages[i] |= TRANS_PACKAGE_UPDATE;
31.2207 -}
31.2208 -
31.2209 -static void
31.2210 -update_conflicted_packages(struct razor_transaction *trans)
31.2211 -{
31.2212 - struct razor_package *pkg, *spkgs;
31.2213 - struct razor_property *up, *sp;
31.2214 - struct prop_iter spi, upi;
31.2215 - struct razor_package_iterator pkg_iter;
31.2216 - const char *name, *version, *arch;
31.2217 -
31.2218 - spkgs = trans->system.set->packages.data;
31.2219 - prop_iter_init(&spi, &trans->system);
31.2220 - prop_iter_init(&upi, &trans->upstream);
31.2221 -
31.2222 - while (prop_iter_next(&spi, RAZOR_PROPERTY_CONFLICTS, &sp)) {
31.2223 - if (!prop_iter_seek_to(&upi, RAZOR_PROPERTY_PROVIDES,
31.2224 - &spi.pool[sp->name]))
31.2225 - continue;
31.2226 -
31.2227 - if (!any_provider_satisfies_requirement(&upi, sp->relation,
31.2228 - &spi.pool[sp->version]))
31.2229 - continue;
31.2230 -
31.2231 - razor_package_iterator_init_for_property(&pkg_iter,
31.2232 - trans->system.set,
31.2233 - sp);
31.2234 - while (razor_package_iterator_next(&pkg_iter, &pkg,
31.2235 - &name, &version, &arch)) {
31.2236 - fprintf(stderr, "updating %s %s because it conflicts with %s",
31.2237 - name, version, spi.pool + sp->name);
31.2238 - trans->system.packages[pkg - spkgs] |=
31.2239 - TRANS_PACKAGE_UPDATE;
31.2240 - }
31.2241 - }
31.2242 -
31.2243 - prop_iter_init(&spi, &trans->system);
31.2244 - prop_iter_init(&upi, &trans->upstream);
31.2245 -
31.2246 - while (prop_iter_next(&upi, RAZOR_PROPERTY_CONFLICTS, &up)) {
31.2247 - sp = prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES,
31.2248 - &upi.pool[upi.p->name]);
31.2249 -
31.2250 - if (sp)
31.2251 - flag_matching_providers(trans, &spi, up, &upi,
31.2252 - TRANS_PACKAGE_UPDATE);
31.2253 - }
31.2254 -}
31.2255 -
31.2256 -static void
31.2257 -pull_in_requirements(struct razor_transaction *trans,
31.2258 - struct prop_iter *rpi, struct prop_iter *ppi)
31.2259 -{
31.2260 - struct razor_property *rp, *pp;
31.2261 - struct razor_package *pkg, *upkgs;
31.2262 -
31.2263 - upkgs = trans->upstream.set->packages.data;
31.2264 - while (prop_iter_next(rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
31.2265 - if (rpi->present[rp - rpi->start] & TRANS_PROPERTY_SATISFIED)
31.2266 - continue;
31.2267 -
31.2268 - pp = prop_iter_seek_to(ppi, RAZOR_PROPERTY_PROVIDES,
31.2269 - &rpi->pool[rp->name]);
31.2270 - if (pp == NULL)
31.2271 - continue;
31.2272 - pkg = pick_matching_provider(trans->upstream.set,
31.2273 - ppi, rp->relation,
31.2274 - &rpi->pool[rp->version]);
31.2275 - if (pkg == NULL)
31.2276 - continue;
31.2277 -
31.2278 - rpi->present[rp - rpi->start] |= TRANS_PROPERTY_SATISFIED;
31.2279 -
31.2280 - fprintf(stderr, "pulling in %s which provides %s %s %s "
31.2281 - "to satisfy %s %s %s\n",
31.2282 - ppi->pool + pkg->name,
31.2283 - ppi->pool + pp->name,
31.2284 - relation_string[pp->relation],
31.2285 - ppi->pool + pp->version,
31.2286 - &rpi->pool[rp->name],
31.2287 - relation_string[rp->relation],
31.2288 - &rpi->pool[rp->version]);
31.2289 -
31.2290 - trans->upstream.packages[pkg - upkgs] |= TRANS_PACKAGE_UPDATE;
31.2291 - }
31.2292 -}
31.2293 -
31.2294 -static void
31.2295 -pull_in_all_requirements(struct razor_transaction *trans)
31.2296 -{
31.2297 - struct prop_iter rpi, ppi;
31.2298 -
31.2299 - prop_iter_init(&rpi, &trans->system);
31.2300 - prop_iter_init(&ppi, &trans->upstream);
31.2301 - pull_in_requirements(trans, &rpi, &ppi);
31.2302 -
31.2303 - prop_iter_init(&rpi, &trans->upstream);
31.2304 - prop_iter_init(&ppi, &trans->upstream);
31.2305 - pull_in_requirements(trans, &rpi, &ppi);
31.2306 -}
31.2307 -
31.2308 -static void
31.2309 -flush_scheduled_system_updates(struct razor_transaction *trans)
31.2310 -{
31.2311 - struct razor_package_iterator *pi;
31.2312 - struct razor_package *p, *pkg, *spkgs;
31.2313 - struct prop_iter ppi;
31.2314 - const char *name, *version, *arch;
31.2315 -
31.2316 - spkgs = trans->system.set->packages.data;
31.2317 - pi = razor_package_iterator_create(trans->system.set);
31.2318 - prop_iter_init(&ppi, &trans->upstream);
31.2319 -
31.2320 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
31.2321 - if (!(trans->system.packages[p - spkgs] & TRANS_PACKAGE_UPDATE))
31.2322 - continue;
31.2323 -
31.2324 - if (!prop_iter_seek_to(&ppi, RAZOR_PROPERTY_PROVIDES, name))
31.2325 - continue;
31.2326 -
31.2327 - pkg = pick_matching_provider(trans->upstream.set, &ppi,
31.2328 - RAZOR_VERSION_GREATER, version);
31.2329 - if (pkg == NULL)
31.2330 - continue;
31.2331 -
31.2332 - fprintf(stderr, "updating %s-%s to %s-%s\n",
31.2333 - name, version,
31.2334 - &ppi.pool[pkg->name], &ppi.pool[pkg->version]);
31.2335 -
31.2336 - razor_transaction_remove_package(trans, p);
31.2337 - razor_transaction_install_package(trans, pkg);
31.2338 - }
31.2339 -
31.2340 - razor_package_iterator_destroy(pi);
31.2341 -}
31.2342 -
31.2343 -static void
31.2344 -flush_scheduled_upstream_updates(struct razor_transaction *trans)
31.2345 -{
31.2346 - struct razor_package_iterator *pi;
31.2347 - struct razor_package *p, *upkgs;
31.2348 - struct prop_iter spi;
31.2349 - const char *name, *version, *arch;
31.2350 -
31.2351 - upkgs = trans->upstream.set->packages.data;
31.2352 - pi = razor_package_iterator_create(trans->upstream.set);
31.2353 - prop_iter_init(&spi, &trans->system);
31.2354 -
31.2355 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
31.2356 - if (!(trans->upstream.packages[p - upkgs] & TRANS_PACKAGE_UPDATE))
31.2357 - continue;
31.2358 -
31.2359 - if (!prop_iter_seek_to(&spi, RAZOR_PROPERTY_PROVIDES, name))
31.2360 - continue;
31.2361 - remove_matching_providers(trans, &spi,
31.2362 - RAZOR_VERSION_LESS, version);
31.2363 - razor_transaction_install_package(trans, p);
31.2364 - fprintf(stderr, "installing %s-%s\n", name, version);
31.2365 - }
31.2366 -}
31.2367 -
31.2368 -int
31.2369 -razor_transaction_resolve(struct razor_transaction *trans)
31.2370 -{
31.2371 - int last = 0;
31.2372 -
31.2373 - flush_scheduled_system_updates(trans);
31.2374 -
31.2375 - while (last < trans->changes) {
31.2376 - last = trans->changes;
31.2377 - remove_obsoleted_packages(trans);
31.2378 - mark_all_satisfied_requires(trans);
31.2379 - update_unsatisfied_packages(trans);
31.2380 - update_conflicted_packages(trans);
31.2381 - pull_in_all_requirements(trans);
31.2382 - flush_scheduled_system_updates(trans);
31.2383 - flush_scheduled_upstream_updates(trans);
31.2384 - }
31.2385 -
31.2386 - return trans->changes;
31.2387 -}
31.2388 -
31.2389 -static void
31.2390 -describe_unsatisfied(struct razor_set *set, struct razor_property *rp)
31.2391 -{
31.2392 - struct razor_package_iterator pi;
31.2393 - struct razor_package *pkg;
31.2394 - const char *name, *version, *arch, *pool;
31.2395 -
31.2396 - pool = set->string_pool.data;
31.2397 - if (pool[rp->version] == '\0') {
31.2398 - razor_package_iterator_init_for_property(&pi, set, rp);
31.2399 - while (razor_package_iterator_next(&pi, &pkg,
31.2400 - &name, &version, &arch))
31.2401 - fprintf(stderr, "%s is needed by %s-%s.%s\n",
31.2402 - &pool[rp->name],
31.2403 - name, version, arch);
31.2404 - } else {
31.2405 - razor_package_iterator_init_for_property(&pi, set, rp);
31.2406 - while (razor_package_iterator_next(&pi, &pkg,
31.2407 - &name, &version, &arch))
31.2408 - fprintf(stderr, "%s %s %s is needed by %s-%s.%s\n",
31.2409 - &pool[rp->name],
31.2410 - relation_string[rp->relation],
31.2411 - &pool[rp->version],
31.2412 - name, version, arch);
31.2413 - }
31.2414 -}
31.2415 -
31.2416 -int
31.2417 -razor_transaction_describe(struct razor_transaction *trans)
31.2418 -{
31.2419 - struct prop_iter rpi;
31.2420 - struct razor_property *rp;
31.2421 - int unsatisfied;
31.2422 -
31.2423 - flush_scheduled_system_updates(trans);
31.2424 - flush_scheduled_upstream_updates(trans);
31.2425 - mark_all_satisfied_requires(trans);
31.2426 -
31.2427 - unsatisfied = 0;
31.2428 - prop_iter_init(&rpi, &trans->system);
31.2429 - while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
31.2430 - if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
31.2431 - describe_unsatisfied(trans->system.set, rp);
31.2432 - unsatisfied++;
31.2433 - }
31.2434 - }
31.2435 -
31.2436 - prop_iter_init(&rpi, &trans->upstream);
31.2437 - while (prop_iter_next(&rpi, RAZOR_PROPERTY_REQUIRES, &rp)) {
31.2438 - if (!(rpi.present[rp - rpi.start] & TRANS_PROPERTY_SATISFIED)) {
31.2439 - describe_unsatisfied(trans->upstream.set, rp);
31.2440 - unsatisfied++;
31.2441 - }
31.2442 - }
31.2443 -
31.2444 - return unsatisfied;
31.2445 -}
31.2446 -
31.2447 -int
31.2448 -razor_transaction_unsatisfied_property(struct razor_transaction *trans,
31.2449 - const char *name,
31.2450 - enum razor_version_relation rel,
31.2451 - const char *version,
31.2452 - enum razor_property_type type)
31.2453 -{
31.2454 - struct prop_iter pi;
31.2455 - struct razor_property *p;
31.2456 -
31.2457 - prop_iter_init(&pi, &trans->system);
31.2458 - while (prop_iter_next(&pi, type, &p)) {
31.2459 - if (!(trans->system.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
31.2460 - p->relation == rel &&
31.2461 - strcmp(&pi.pool[p->name], name) == 0 &&
31.2462 - strcmp(&pi.pool[p->version], version) == 0)
31.2463 -
31.2464 - return 1;
31.2465 - }
31.2466 -
31.2467 - prop_iter_init(&pi, &trans->upstream);
31.2468 - while (prop_iter_next(&pi, type, &p)) {
31.2469 - if (!(trans->upstream.properties[p - pi.start] & TRANS_PROPERTY_SATISFIED) &&
31.2470 - p->relation == rel &&
31.2471 - strcmp(&pi.pool[p->name], name) == 0 &&
31.2472 - strcmp(&pi.pool[p->version], version) == 0)
31.2473 -
31.2474 - return 1;
31.2475 - }
31.2476 -
31.2477 - return 0;
31.2478 -}
31.2479 -
31.2480 -struct razor_set *
31.2481 -razor_transaction_finish(struct razor_transaction *trans)
31.2482 -{
31.2483 - struct razor_merger *merger;
31.2484 - struct razor_package *u, *uend, *upkgs, *s, *send, *spkgs;
31.2485 - char *upool, *spool;
31.2486 - int cmp;
31.2487 -
31.2488 - s = trans->system.set->packages.data;
31.2489 - spkgs = trans->system.set->packages.data;
31.2490 - send = trans->system.set->packages.data +
31.2491 - trans->system.set->packages.size;
31.2492 - spool = trans->system.set->string_pool.data;
31.2493 -
31.2494 - u = trans->upstream.set->packages.data;
31.2495 - upkgs = trans->upstream.set->packages.data;
31.2496 - uend = trans->upstream.set->packages.data +
31.2497 - trans->upstream.set->packages.size;
31.2498 - upool = trans->upstream.set->string_pool.data;
31.2499 -
31.2500 - merger = razor_merger_create(trans->system.set, trans->upstream.set);
31.2501 - while (s < send || u < uend) {
31.2502 - if (s < send && u < uend)
31.2503 - cmp = strcmp(&spool[s->name], &upool[u->name]);
31.2504 - else if (s < send)
31.2505 - cmp = -1;
31.2506 - else
31.2507 - cmp = 1;
31.2508 -
31.2509 - if (cmp < 0) {
31.2510 - if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
31.2511 - razor_merger_add_package(merger, s);
31.2512 - s++;
31.2513 - } else if (cmp == 0) {
31.2514 - if (trans->system.packages[s - spkgs] & TRANS_PACKAGE_PRESENT)
31.2515 - razor_merger_add_package(merger, s);
31.2516 - if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
31.2517 - razor_merger_add_package(merger, u);
31.2518 -
31.2519 - s++;
31.2520 - u++;
31.2521 - } else {
31.2522 - if (trans->upstream.packages[u - upkgs] & TRANS_PACKAGE_PRESENT)
31.2523 - razor_merger_add_package(merger, u);
31.2524 - u++;
31.2525 - }
31.2526 - }
31.2527 -
31.2528 - razor_transaction_destroy(trans);
31.2529 -
31.2530 - return razor_merger_finish(merger);
31.2531 -}
31.2532 -
31.2533 -void
31.2534 -razor_transaction_destroy(struct razor_transaction *trans)
31.2535 -{
31.2536 - transaction_set_release(&trans->system);
31.2537 - transaction_set_release(&trans->upstream);
31.2538 - free(trans);
31.2539 -}
31.2540 -
31.2541 -struct razor_package_query {
31.2542 - struct razor_set *set;
31.2543 - char *vector;
31.2544 - int count;
31.2545 -};
31.2546 -
31.2547 -struct razor_package_query *
31.2548 -razor_package_query_create(struct razor_set *set)
31.2549 -{
31.2550 - struct razor_package_query *pq;
31.2551 - int count;
31.2552 -
31.2553 - pq = zalloc(sizeof *pq);
31.2554 - pq->set = set;
31.2555 - count = set->packages.size / sizeof(struct razor_package);
31.2556 - pq->vector = zalloc(count * sizeof(char));
31.2557 -
31.2558 - return pq;
31.2559 -}
31.2560 -
31.2561 -void
31.2562 -razor_package_query_add_package(struct razor_package_query *pq,
31.2563 - struct razor_package *p)
31.2564 -{
31.2565 - struct razor_package *packages;
31.2566 -
31.2567 - packages = pq->set->packages.data;
31.2568 - pq->count += pq->vector[p - packages] ^ 1;
31.2569 - pq->vector[p - packages] = 1;
31.2570 -}
31.2571 -
31.2572 -void
31.2573 -razor_package_query_add_iterator(struct razor_package_query *pq,
31.2574 - struct razor_package_iterator *pi)
31.2575 -{
31.2576 - struct razor_package *packages, *p;
31.2577 - const char *name, *version, *arch;
31.2578 -
31.2579 - packages = pq->set->packages.data;
31.2580 - while (razor_package_iterator_next(pi, &p, &name, &version, &arch)) {
31.2581 - pq->count += pq->vector[p - packages] ^ 1;
31.2582 - pq->vector[p - packages] = 1;
31.2583 - }
31.2584 -}
31.2585 -
31.2586 -struct razor_package_iterator *
31.2587 -razor_package_query_finish(struct razor_package_query *pq)
31.2588 -{
31.2589 - struct razor_package_iterator *pi;
31.2590 - struct razor_set *set;
31.2591 - struct list *index;
31.2592 - int i, j, count;
31.2593 -
31.2594 - set = pq->set;
31.2595 - count = set->packages.size / sizeof(struct razor_package);
31.2596 - index = zalloc(pq->count * sizeof *index);
31.2597 -
31.2598 - for (i = 0, j = 0; i < count; i++) {
31.2599 - if (!pq->vector[i])
31.2600 - continue;
31.2601 -
31.2602 - index[j].data = i;
31.2603 - if (j == pq->count - 1)
31.2604 - index[j].flags = 0x80;
31.2605 - j++;
31.2606 - }
31.2607 -
31.2608 - free(pq);
31.2609 -
31.2610 - pi = razor_package_iterator_create_with_index(set, index);
31.2611 - pi->free_index = 1;
31.2612 -
31.2613 - return pi;
31.2614 -}
32.1 --- a/razor.h Sun Jun 15 23:15:59 2008 -0400
32.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
32.3 @@ -1,189 +0,0 @@
32.4 -/*
32.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
32.6 - * Copyright (C) 2008 Red Hat, Inc
32.7 - *
32.8 - * This program is free software; you can redistribute it and/or modify
32.9 - * it under the terms of the GNU General Public License as published by
32.10 - * the Free Software Foundation; either version 2 of the License, or
32.11 - * (at your option) any later version.
32.12 - *
32.13 - * This program is distributed in the hope that it will be useful,
32.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
32.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32.16 - * GNU General Public License for more details.
32.17 - *
32.18 - * You should have received a copy of the GNU General Public License along
32.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
32.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32.21 - */
32.22 -
32.23 -#ifndef _RAZOR_H_
32.24 -#define _RAZOR_H_
32.25 -
32.26 -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
32.27 -
32.28 -struct razor_set;
32.29 -struct razor_package;
32.30 -struct razor_property;
32.31 -
32.32 -enum razor_property_type {
32.33 - RAZOR_PROPERTY_REQUIRES,
32.34 - RAZOR_PROPERTY_PROVIDES,
32.35 - RAZOR_PROPERTY_CONFLICTS,
32.36 - RAZOR_PROPERTY_OBSOLETES
32.37 -};
32.38 -
32.39 -enum razor_version_relation {
32.40 - RAZOR_VERSION_LESS,
32.41 - RAZOR_VERSION_LESS_OR_EQUAL,
32.42 - RAZOR_VERSION_EQUAL,
32.43 - RAZOR_VERSION_GREATER_OR_EQUAL,
32.44 - RAZOR_VERSION_GREATER
32.45 -};
32.46 -extern const char * const razor_version_relations[];
32.47 -
32.48 -struct razor_set *razor_set_create(void);
32.49 -struct razor_set *razor_set_open(const char *filename);
32.50 -void razor_set_destroy(struct razor_set *set);
32.51 -int razor_set_write_to_fd(struct razor_set *set, int fd);
32.52 -int razor_set_write(struct razor_set *set, const char *filename);
32.53 -
32.54 -struct razor_package *
32.55 -razor_set_get_package(struct razor_set *set, const char *package);
32.56 -
32.57 -struct razor_package_iterator;
32.58 -struct razor_package_iterator *
32.59 -razor_package_iterator_create(struct razor_set *set);
32.60 -struct razor_package_iterator *
32.61 -razor_package_iterator_create_for_property(struct razor_set *set,
32.62 - struct razor_property *property);
32.63 -struct razor_package_iterator *
32.64 -razor_package_iterator_create_for_file(struct razor_set *set,
32.65 - const char *filename);
32.66 -
32.67 -int razor_package_iterator_next(struct razor_package_iterator *pi,
32.68 - struct razor_package **package,
32.69 - const char **name,
32.70 - const char **version,
32.71 - const char **arch);
32.72 -void razor_package_iterator_destroy(struct razor_package_iterator *pi);
32.73 -
32.74 -struct razor_package_query *
32.75 -razor_package_query_create(struct razor_set *set);
32.76 -void
32.77 -razor_package_query_add_package(struct razor_package_query *pq,
32.78 - struct razor_package *p);
32.79 -void
32.80 -razor_package_query_add_iterator(struct razor_package_query *pq,
32.81 - struct razor_package_iterator *pi);
32.82 -struct razor_package_iterator *
32.83 -razor_package_query_finish(struct razor_package_query *pq);
32.84 -
32.85 -struct razor_property_iterator;
32.86 -struct razor_property_iterator *
32.87 -razor_property_iterator_create(struct razor_set *set,
32.88 - struct razor_package *package);
32.89 -int razor_property_iterator_next(struct razor_property_iterator *pi,
32.90 - struct razor_property **property,
32.91 - const char **name,
32.92 - enum razor_version_relation *relation,
32.93 - const char **version,
32.94 - enum razor_property_type *type);
32.95 -void
32.96 -razor_property_iterator_destroy(struct razor_property_iterator *pi);
32.97 -
32.98 -void razor_set_list_files(struct razor_set *set, const char *prefix);
32.99 -void razor_set_list_package_files(struct razor_set *set, const char *name);
32.100 -
32.101 -void razor_set_list_unsatisfied(struct razor_set *set);
32.102 -
32.103 -typedef void (*razor_package_callback_t)(const char *name,
32.104 - const char *old_version,
32.105 - const char *new_version,
32.106 - const char *arch,
32.107 - void *data);
32.108 -void
32.109 -razor_set_diff(struct razor_set *set, struct razor_set *upstream,
32.110 - razor_package_callback_t callback, void *data);
32.111 -
32.112 -/* Package transactions */
32.113 -
32.114 -struct razor_transaction *
32.115 -razor_transaction_create(struct razor_set *system, struct razor_set *upstream);
32.116 -void razor_transaction_install_package(struct razor_transaction *transaction,
32.117 - struct razor_package *package);
32.118 -void razor_transaction_remove_package(struct razor_transaction *transaction,
32.119 - struct razor_package *package);
32.120 -void razor_transaction_update_package(struct razor_transaction *trans,
32.121 - struct razor_package *package);
32.122 -void razor_transaction_update_all(struct razor_transaction *transaction);
32.123 -int razor_transaction_resolve(struct razor_transaction *trans);
32.124 -int razor_transaction_describe(struct razor_transaction *trans);
32.125 -struct razor_set *razor_transaction_finish(struct razor_transaction *trans);
32.126 -void razor_transaction_destroy(struct razor_transaction *trans);
32.127 -
32.128 -/* Temporary helper for test suite. */
32.129 -int razor_transaction_unsatisfied_property(struct razor_transaction *trans,
32.130 - const char *name,
32.131 - enum razor_version_relation rel,
32.132 - const char *version,
32.133 - enum razor_property_type type);
32.134 -
32.135 -/* Importer interface; for building a razor set from external sources,
32.136 - * like yum, rpmdb or razor package files. */
32.137 -
32.138 -struct razor_importer;
32.139 -struct razor_rpm;
32.140 -
32.141 -struct razor_importer *razor_importer_new(void);
32.142 -void razor_importer_destroy(struct razor_importer *importer);
32.143 -void razor_importer_begin_package(struct razor_importer *importer,
32.144 - const char *name,
32.145 - const char *version,
32.146 - const char *arch);
32.147 -void razor_importer_add_property(struct razor_importer *importer,
32.148 - const char *name,
32.149 - enum razor_version_relation relation,
32.150 - const char *version,
32.151 - enum razor_property_type type);
32.152 -void razor_importer_add_file(struct razor_importer *importer,
32.153 - const char *name);
32.154 -void razor_importer_finish_package(struct razor_importer *importer);
32.155 -
32.156 -int razor_importer_add_rpm(struct razor_importer *importer,
32.157 - struct razor_rpm *rpm);
32.158 -
32.159 -struct razor_set *razor_importer_finish(struct razor_importer *importer);
32.160 -
32.161 -void razor_build_evr(char *evr_buf, int size, const char *epoch,
32.162 - const char *version, const char *release);
32.163 -
32.164 -struct razor_set *razor_set_create_from_yum(void);
32.165 -struct razor_set *razor_set_create_from_rpmdb(void);
32.166 -
32.167 -/* RPM functions */
32.168 -
32.169 -struct razor_rpm *razor_rpm_open(const char *filename);
32.170 -int razor_rpm_install(struct razor_rpm *rpm, const char *root);
32.171 -int razor_rpm_close(struct razor_rpm *rpm);
32.172 -
32.173 -
32.174 -/* Razor root functions. The root data struct encapsulates filesystem
32.175 - * conventions and the locking protocol. */
32.176 -
32.177 -struct razor_root;
32.178 -#define RAZOR_ROOT_OPEN_WRITE 0x01
32.179 -
32.180 -int razor_root_create(const char *root);
32.181 -struct razor_root *razor_root_open(const char *root, int flags);
32.182 -struct razor_set *razor_root_open_read_only(const char *root);
32.183 -struct razor_transaction *
32.184 -razor_root_create_transaction(struct razor_root *image,
32.185 - struct razor_set *upstream);
32.186 -int razor_root_close(struct razor_root *image);
32.187 -void razor_root_update(struct razor_root *image, struct razor_set *next);
32.188 -int razor_root_commit(struct razor_root *image);
32.189 -void razor_root_diff(struct razor_root *root,
32.190 - razor_package_callback_t callback, void *data);
32.191 -
32.192 -#endif /* _RAZOR_H_ */
33.1 --- a/rpm-razor.c Sun Jun 15 23:15:59 2008 -0400
33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
33.3 @@ -1,897 +0,0 @@
33.4 -/*
33.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
33.6 - * Copyright (C) 2008 Red Hat, Inc
33.7 - *
33.8 - * This program is free software; you can redistribute it and/or modify
33.9 - * it under the terms of the GNU General Public License as published by
33.10 - * the Free Software Foundation; either version 2 of the License, or
33.11 - * (at your option) any later version.
33.12 - *
33.13 - * This program is distributed in the hope that it will be useful,
33.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
33.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33.16 - * GNU General Public License for more details.
33.17 - *
33.18 - * You should have received a copy of the GNU General Public License along
33.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
33.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33.21 - */
33.22 -
33.23 -#include <stdlib.h>
33.24 -#include <string.h>
33.25 -#include <stdio.h>
33.26 -#include <dirent.h>
33.27 -#include "razor.h"
33.28 -
33.29 -enum option_type {
33.30 - OPTION_LAST,
33.31 - OPTION_GROUP,
33.32 - OPTION_BOOL,
33.33 - OPTION_STRING
33.34 -};
33.35 -
33.36 -struct option {
33.37 - enum option_type type;
33.38 - const char *name;
33.39 - char short_name;
33.40 - const char *arg_name;
33.41 - const char *description;
33.42 - void *data;
33.43 -};
33.44 -
33.45 -/* A note about all these options: rpm allows options to mean
33.46 - * different things depending on what other options are present on the
33.47 - * command line. For example, if -q or --query is present, -i no
33.48 - * longer means install, but info. The way we handle this is by
33.49 - * setting all the options that may match (ie if -i is given we set
33.50 - * install and info), and then look at the relevent one depending on
33.51 - * what else in on the command line. */
33.52 -
33.53 -static int option_all, option_whatrequires, option_whatprovides;
33.54 -static int option_package;
33.55 -
33.56 -static const struct option query_options[] = {
33.57 - { OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
33.58 - { OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
33.59 - { OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
33.60 - { OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
33.61 - { OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
33.62 - { OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
33.63 - { OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
33.64 - { OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
33.65 - { OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
33.66 - { OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
33.67 - { OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
33.68 - { OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
33.69 - { OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
33.70 - { OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
33.71 - { OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
33.72 - { OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
33.73 - { OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
33.74 - { OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
33.75 - { OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
33.76 - { }
33.77 -};
33.78 -
33.79 -static int option_nodeps;
33.80 -
33.81 -static const struct option verify_options[] = {
33.82 - { OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
33.83 - { OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
33.84 - { OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", &option_nodeps },
33.85 - { OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
33.86 - { OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
33.87 - { OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
33.88 - { OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
33.89 - { OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
33.90 - { OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
33.91 - { OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
33.92 - { OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
33.93 - { OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
33.94 - { OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
33.95 - { OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
33.96 - { OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
33.97 - { OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
33.98 - { OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
33.99 - { }
33.100 -};
33.101 -
33.102 -static const struct option ftw_options[] = {
33.103 - { OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
33.104 - { OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
33.105 - { OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
33.106 - { OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
33.107 - { OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
33.108 - { OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
33.109 - { OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
33.110 - { OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
33.111 - { }
33.112 -};
33.113 -
33.114 -static const struct option signature_options[] = {
33.115 - { OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
33.116 - { OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
33.117 - { OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
33.118 - { OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
33.119 - { OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
33.120 - { OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
33.121 - { OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
33.122 - { }
33.123 -};
33.124 -
33.125 -static int option_initdb;
33.126 -
33.127 -static const struct option database_options[] = {
33.128 - { OPTION_BOOL, "initdb", 0, NULL, "initialize database", &option_initdb },
33.129 - { OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
33.130 - { }
33.131 -};
33.132 -
33.133 -static int option_erase, option_install, option_upgrade, option_justdb;
33.134 -static int option_test;
33.135 -
33.136 -static const struct option install_options[] = {
33.137 - { OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
33.138 - { OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
33.139 - { OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
33.140 - { OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
33.141 - { OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
33.142 - { OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
33.143 - { OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
33.144 - { OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
33.145 - { OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
33.146 - { OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
33.147 - { OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
33.148 - { OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
33.149 - { OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
33.150 - { OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
33.151 - { OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
33.152 - { OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", &option_justdb, },
33.153 - { OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", &option_nodeps, },
33.154 - { OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
33.155 - { OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
33.156 - { OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
33.157 - { OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
33.158 - { OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
33.159 - { OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
33.160 - { OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
33.161 - { OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
33.162 - { OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
33.163 - { OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
33.164 - { OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
33.165 - { OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
33.166 - { OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
33.167 - { OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", &option_test },
33.168 - { OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
33.169 - { }
33.170 -};
33.171 -
33.172 -static int option_version;
33.173 -static const char *option_root = "install";
33.174 -
33.175 -static const struct option common_options[] = {
33.176 - { OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
33.177 - { OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
33.178 - { OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
33.179 - { OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
33.180 - { OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
33.181 - { OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
33.182 - { OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", &option_root },
33.183 - { OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
33.184 - { OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
33.185 - { OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
33.186 - { OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
33.187 - { OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
33.188 - { }
33.189 -};
33.190 -
33.191 -static int option_conflicts, option_obsoletes, option_requires;
33.192 -static int option_provides, option_info, option_changelog;
33.193 -
33.194 -static const struct option alias_options[] = {
33.195 - { OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
33.196 - { OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
33.197 - { OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
33.198 - { OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
33.199 - { OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
33.200 - { OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
33.201 - { OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
33.202 - { OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
33.203 - { OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
33.204 - { OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
33.205 - { OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
33.206 - { OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
33.207 - { OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
33.208 - { OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
33.209 - { OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
33.210 - { OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
33.211 - { OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
33.212 - { OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
33.213 - { OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
33.214 - { OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
33.215 - { OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
33.216 - { OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
33.217 - { OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
33.218 - { OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
33.219 - { OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
33.220 - { OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
33.221 - { }
33.222 -};
33.223 -
33.224 -static int option_help, option_usage;
33.225 -
33.226 -static const struct option help_options[] = {
33.227 - { OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
33.228 - { OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
33.229 - { }
33.230 -};
33.231 -
33.232 -static int option_query, option_verify;
33.233 -
33.234 -static const struct option rpm_options[] = {
33.235 - { OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
33.236 - { OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
33.237 - { OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
33.238 - { OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
33.239 - { OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
33.240 - { OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
33.241 - { OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
33.242 - { OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
33.243 - { OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
33.244 - { OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
33.245 - { OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
33.246 - { }
33.247 -};
33.248 -
33.249 -static const char system_repo_filename[] = "system.repo";
33.250 -static const char *repo_filename = system_repo_filename;
33.251 -
33.252 -static void
33.253 -command_initdb(int argc, const char *argv[])
33.254 -{
33.255 - razor_root_create(option_root);
33.256 -}
33.257 -
33.258 -static struct razor_property *
33.259 -add_property_packages(struct razor_set *set,
33.260 - struct razor_package_query *query,
33.261 - const char *ref_name,
33.262 - const char *ref_version,
33.263 - enum razor_property_type ref_type)
33.264 -{
33.265 - struct razor_property *property;
33.266 - struct razor_property_iterator *pi;
33.267 - struct razor_package_iterator *pkgi;
33.268 - const char *name, *version;
33.269 - enum razor_property_type type;
33.270 - enum razor_version_relation relation;
33.271 -
33.272 - pi = razor_property_iterator_create(set, NULL);
33.273 - while (razor_property_iterator_next(pi, &property, &name,
33.274 - &relation, &version, &type)) {
33.275 - if (strcmp(ref_name, name) != 0)
33.276 - continue;
33.277 - if (ref_version && relation == RAZOR_VERSION_EQUAL &&
33.278 - strcmp(ref_version, version) != 0)
33.279 - continue;
33.280 - if (ref_type != type)
33.281 - continue;
33.282 -
33.283 - pkgi = razor_package_iterator_create_for_property(set,
33.284 - property);
33.285 - razor_package_query_add_iterator(query, pkgi);
33.286 - razor_package_iterator_destroy(pkgi);
33.287 - }
33.288 - razor_property_iterator_destroy(pi);
33.289 -
33.290 - return property;
33.291 -}
33.292 -
33.293 -static int
33.294 -strcmpp(const void *p1, const void *p2)
33.295 -{
33.296 - return strcmp(*(char * const *) p1, *(char * const *) p2);
33.297 -}
33.298 -
33.299 -static void
33.300 -add_command_line_packages(struct razor_set *set,
33.301 - struct razor_package_query *query,
33.302 - int argc, const char **argv)
33.303 -{
33.304 - struct razor_package *package;
33.305 - struct razor_package_iterator *pi;
33.306 - const char *name, *version, *arch;
33.307 - int i, cmp, errors;
33.308 -
33.309 - qsort(argv, argc, sizeof(*argv), strcmpp);
33.310 - i = 0;
33.311 - errors = 0;
33.312 -
33.313 - pi = razor_package_iterator_create(set);
33.314 -
33.315 - while (razor_package_iterator_next(pi, &package,
33.316 - &name, &version, &arch)) {
33.317 - while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
33.318 - fprintf(stderr, "error: package %s is not installed\n",
33.319 - argv[i]);
33.320 - errors++;
33.321 - i++;
33.322 - }
33.323 -
33.324 - if (cmp == 0) {
33.325 - razor_package_query_add_package(query, package);
33.326 - i++;
33.327 - }
33.328 - }
33.329 -
33.330 - razor_package_iterator_destroy(pi);
33.331 -
33.332 - if (errors)
33.333 - exit(1);
33.334 -}
33.335 -
33.336 -static struct razor_package_iterator *
33.337 -get_query_packages(struct razor_set *set, int argc, const char *argv[])
33.338 -{
33.339 - struct razor_package_query *query;
33.340 - struct razor_package_iterator *pi;
33.341 - int i;
33.342 -
33.343 - if (option_all + option_whatprovides + option_whatrequires > 1) {
33.344 - printf("only one type of query/verify "
33.345 - "may be performed at a time\n");
33.346 - exit(1);
33.347 - }
33.348 -
33.349 - query = razor_package_query_create(set);
33.350 -
33.351 - if (option_all) {
33.352 - pi = razor_package_iterator_create(set);
33.353 - razor_package_query_add_iterator(query, pi);
33.354 - razor_package_iterator_destroy(pi);
33.355 - } else if (option_whatrequires) {
33.356 - for (i = 0; i < argc; i++)
33.357 - add_property_packages(set, query,
33.358 - argv[i], NULL,
33.359 - RAZOR_PROPERTY_REQUIRES);
33.360 - } else if (option_whatprovides) {
33.361 - for (i = 0; i < argc; i++)
33.362 - add_property_packages(set, query,
33.363 - argv[i], NULL,
33.364 - RAZOR_PROPERTY_PROVIDES);
33.365 - } else if (argc > 0) {
33.366 - add_command_line_packages(set, query, argc, argv);
33.367 - } else {
33.368 - printf("no arguments given for query/verify\n");
33.369 - exit(1);
33.370 - }
33.371 -
33.372 - return razor_package_query_finish(query);
33.373 -}
33.374 -
33.375 -static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
33.376 -
33.377 -static void
33.378 -print_package_properties(struct razor_set *set,
33.379 - struct razor_package *package,
33.380 - enum razor_property_type ref_type)
33.381 -{
33.382 - struct razor_property *property;
33.383 - struct razor_property_iterator *pi;
33.384 - const char *name, *version;
33.385 - enum razor_property_type type;
33.386 - enum razor_version_relation relation;
33.387 -
33.388 - pi = razor_property_iterator_create(set, package);
33.389 - while (razor_property_iterator_next(pi, &property,
33.390 - &name, &relation, &version,
33.391 - &type)) {
33.392 - if (type != ref_type)
33.393 - continue;
33.394 - if (version[0] == '\0')
33.395 - printf("%s\n", name);
33.396 - else
33.397 - printf("%s %s %s\n", name,
33.398 - relation_string[relation], version);
33.399 - }
33.400 - razor_property_iterator_destroy(pi);
33.401 -}
33.402 -
33.403 -static void
33.404 -print_package_info(struct razor_set *set, struct razor_package *package)
33.405 -{
33.406 - printf("FIXME: Package info not tracked.\n");
33.407 -}
33.408 -
33.409 -static void
33.410 -print_package_changelog(struct razor_set *set, struct razor_package *package)
33.411 -{
33.412 - printf("FIXME: Package changelog not tracked.\n");
33.413 -}
33.414 -
33.415 -static struct razor_set *
33.416 -create_set_from_command_line(int argc, const char *argv[])
33.417 -{
33.418 - struct razor_importer *importer;
33.419 - struct razor_rpm *rpm;
33.420 - int i;
33.421 -
33.422 - importer = razor_importer_new();
33.423 -
33.424 - for (i = 0; i < argc; i++) {
33.425 - rpm = razor_rpm_open(argv[i]);
33.426 - if (rpm == NULL)
33.427 - continue;
33.428 - if (razor_importer_add_rpm(importer, rpm))
33.429 - printf("couldn't import %s\n", argv[i]);
33.430 -
33.431 - razor_rpm_close(rpm);
33.432 - }
33.433 -
33.434 - return razor_importer_finish(importer);
33.435 -}
33.436 -
33.437 -static void
33.438 -command_query(int argc, const char *argv[])
33.439 -{
33.440 - struct razor_set *set;
33.441 - struct razor_package_iterator *pi;
33.442 - struct razor_package *package;
33.443 - const char *name, *version, *arch;
33.444 -
33.445 - if (option_package) {
33.446 - set = create_set_from_command_line(argc, argv);
33.447 - argc = 0;
33.448 - option_all = 1;
33.449 - } else {
33.450 - set = razor_root_open_read_only(option_root);
33.451 - }
33.452 -
33.453 - pi = get_query_packages(set, argc, argv);
33.454 -
33.455 - while (razor_package_iterator_next(pi, &package,
33.456 - &name, &version, &arch)) {
33.457 - if (option_conflicts)
33.458 - print_package_properties(set, package,
33.459 - RAZOR_PROPERTY_CONFLICTS);
33.460 - if (option_obsoletes)
33.461 - print_package_properties(set, package,
33.462 - RAZOR_PROPERTY_OBSOLETES);
33.463 - if (option_requires)
33.464 - print_package_properties(set, package,
33.465 - RAZOR_PROPERTY_REQUIRES);
33.466 - if (option_provides)
33.467 - print_package_properties(set, package,
33.468 - RAZOR_PROPERTY_PROVIDES);
33.469 - if (option_info)
33.470 - print_package_info(set, package);
33.471 - if (option_changelog)
33.472 - print_package_changelog(set, package);
33.473 -
33.474 - if (option_conflicts + option_obsoletes +
33.475 - option_requires + option_provides +
33.476 - option_info + option_changelog == 0)
33.477 - printf("%s-%s.%s\n", name, version, arch);
33.478 - }
33.479 -
33.480 - razor_package_iterator_destroy(pi);
33.481 -
33.482 - razor_set_destroy(set);
33.483 -
33.484 - return;
33.485 -}
33.486 -
33.487 -static void
33.488 -command_verify(int argc, const char *argv[])
33.489 -{
33.490 - struct razor_set *set;
33.491 - struct razor_package_iterator *pi;
33.492 - struct razor_package *package;
33.493 - const char *name, *version, *arch;
33.494 -
33.495 - if (option_package) {
33.496 - set = create_set_from_command_line(argc, argv);
33.497 - argc = 0;
33.498 - option_all = 1;
33.499 - } else {
33.500 - set = razor_root_open_read_only(option_root);
33.501 - }
33.502 -
33.503 - pi = get_query_packages(set, argc, argv);
33.504 -
33.505 - while (razor_package_iterator_next(pi, &package,
33.506 - &name, &version, &arch)) {
33.507 - printf("verify %s-%s.%s - not implemented\n",
33.508 - name, version, arch);
33.509 - }
33.510 -
33.511 - razor_package_iterator_destroy(pi);
33.512 -}
33.513 -
33.514 -static void
33.515 -remove_package(const char *name,
33.516 - const char *old_version, const char *new_version,
33.517 - const char *arch, void *data)
33.518 -{
33.519 - if (old_version)
33.520 - printf("remove %s-%s.%s\n", name, old_version, arch);
33.521 -}
33.522 -
33.523 -static void
33.524 -command_erase(int argc, const char *argv[])
33.525 -{
33.526 - struct razor_set *set, *upstream, *next;
33.527 - struct razor_transaction *trans;
33.528 - struct razor_package_query *query;
33.529 - struct razor_package_iterator *pi;
33.530 - struct razor_package *package;
33.531 - const char *name, *version, *arch;
33.532 -
33.533 - if (argc == 0) {
33.534 - printf("no packages given for erase\n");
33.535 - exit(1);
33.536 - }
33.537 -
33.538 - set = razor_set_open(repo_filename);
33.539 - upstream = razor_set_create();
33.540 -
33.541 - trans = razor_transaction_create(set, upstream);
33.542 -
33.543 - query = razor_package_query_create(set);
33.544 - add_command_line_packages(set, query, argc, argv);
33.545 -
33.546 - pi = razor_package_query_finish(query);
33.547 - while (razor_package_iterator_next(pi, &package,
33.548 - &name, &version, &arch))
33.549 - razor_transaction_remove_package(trans, package);
33.550 - razor_package_iterator_destroy(pi);
33.551 -
33.552 - if (!option_nodeps && razor_transaction_describe(trans) > 0) {
33.553 - printf("unsatisfied dependencies.\n");
33.554 - exit(1);
33.555 - }
33.556 -
33.557 - if (option_test)
33.558 - exit(0);
33.559 -
33.560 - next = razor_transaction_finish(trans);
33.561 -
33.562 - if (!option_justdb)
33.563 - razor_set_diff(set, next, remove_package, NULL);
33.564 -
33.565 - razor_set_destroy(set);
33.566 - razor_set_destroy(upstream);
33.567 -
33.568 - razor_set_destroy(next);
33.569 -}
33.570 -
33.571 -static void
33.572 -install_package(const char *name,
33.573 - const char *old_version, const char *new_version,
33.574 - const char *arch, void *data)
33.575 -{
33.576 - if (new_version)
33.577 - printf("install %s-%s.%s\n", name, new_version, arch);
33.578 -}
33.579 -
33.580 -static void
33.581 -command_install(int argc, const char *argv[])
33.582 -{
33.583 - struct razor_set *set, *upstream, *next;
33.584 - struct razor_transaction *trans;
33.585 - struct razor_package_iterator *pi;
33.586 - struct razor_package *package;
33.587 - const char *name, *version, *arch;
33.588 -
33.589 - if (argc == 0) {
33.590 - printf("no packages given for install\n");
33.591 - exit(1);
33.592 - }
33.593 -
33.594 - set = razor_set_open(repo_filename);
33.595 - upstream = create_set_from_command_line(argc, argv);
33.596 -
33.597 - trans = razor_transaction_create(set, upstream);
33.598 -
33.599 - pi = razor_package_iterator_create(upstream);
33.600 - while (razor_package_iterator_next(pi, &package,
33.601 - &name, &version, &arch))
33.602 - razor_transaction_install_package(trans, package);
33.603 - razor_package_iterator_destroy(pi);
33.604 -
33.605 - if (!option_nodeps && razor_transaction_describe(trans) > 0) {
33.606 - printf("unsatisfied dependencies.\n");
33.607 - exit(1);
33.608 - }
33.609 -
33.610 - if (option_test)
33.611 - exit(0);
33.612 -
33.613 - next = razor_transaction_finish(trans);
33.614 -
33.615 - if (!option_justdb)
33.616 - razor_set_diff(set, next, install_package, NULL);
33.617 -
33.618 - razor_set_destroy(set);
33.619 - razor_set_destroy(upstream);
33.620 -
33.621 - razor_set_destroy(next);
33.622 -}
33.623 -
33.624 -static void
33.625 -update_package(const char *name,
33.626 - const char *old_version, const char *new_version,
33.627 - const char *arch, void *data)
33.628 -{
33.629 - if (old_version)
33.630 - printf("remove %s-%s.%s\n", name, old_version, arch);
33.631 - if (new_version)
33.632 - printf("install %s-%s.%s\n", name, new_version, arch);
33.633 -}
33.634 -
33.635 -static void
33.636 -command_update(int argc, const char *argv[])
33.637 -{
33.638 - struct razor_set *set, *upstream, *next;
33.639 - struct razor_transaction *trans;
33.640 - struct razor_package_iterator *pi;
33.641 - struct razor_package *package;
33.642 - const char *name, *version, *arch;
33.643 -
33.644 - if (argc == 0) {
33.645 - printf("no packages given for update\n");
33.646 - exit(1);
33.647 - }
33.648 -
33.649 - set = razor_set_open(repo_filename);
33.650 - upstream = create_set_from_command_line(argc, argv);
33.651 -
33.652 - trans = razor_transaction_create(set, upstream);
33.653 -
33.654 - pi = razor_package_iterator_create(upstream);
33.655 - while (razor_package_iterator_next(pi, &package,
33.656 - &name, &version, &arch))
33.657 - razor_transaction_update_package(trans, package);
33.658 - razor_package_iterator_destroy(pi);
33.659 -
33.660 - if (!option_nodeps && razor_transaction_describe(trans) > 0) {
33.661 - printf("unsatisfied dependencies.\n");
33.662 - exit(1);
33.663 - }
33.664 -
33.665 - if (option_test)
33.666 - exit(0);
33.667 -
33.668 - next = razor_transaction_finish(trans);
33.669 -
33.670 - if (!option_justdb)
33.671 - razor_set_diff(set, next, update_package, NULL);
33.672 -
33.673 - razor_set_destroy(set);
33.674 - razor_set_destroy(upstream);
33.675 -
33.676 - razor_set_destroy(next);
33.677 -}
33.678 -
33.679 -static int
33.680 -for_each_option(const struct option *options,
33.681 - const char *name, char short_name,
33.682 - void (*fn)(const struct option *o,
33.683 - const char *name, char short_name,
33.684 - void *data), void *data)
33.685 -{
33.686 - int i, count = 0;
33.687 -
33.688 - for (i = 0; options[i].type != OPTION_LAST; i++) {
33.689 - switch (options[i].type) {
33.690 - case OPTION_GROUP:
33.691 - count += for_each_option(options[i].data,
33.692 - name, short_name, fn, data);
33.693 - break;
33.694 -
33.695 - case OPTION_BOOL:
33.696 - case OPTION_STRING:
33.697 - if (name && strcmp(options[i].name, name) == 0) {
33.698 - fn(&options[i], name, 0, data);
33.699 - count++;
33.700 - break;
33.701 - }
33.702 -
33.703 - if (short_name &&
33.704 - short_name == options[i].short_name) {
33.705 - fn(&options[i], NULL, short_name, data);
33.706 - count++;
33.707 - break;
33.708 - }
33.709 - break;
33.710 -
33.711 - case OPTION_LAST:
33.712 - break;
33.713 - }
33.714 - }
33.715 -
33.716 - return count;
33.717 -}
33.718 -
33.719 -static void
33.720 -handle_option(const struct option *o,
33.721 - const char *name, char short_name, void *data)
33.722 -{
33.723 - if (o->data == NULL) {
33.724 - if (name)
33.725 - printf("option --%s not supported\n", name);
33.726 - else
33.727 - printf("option -%c not supported\n", short_name);
33.728 - return;
33.729 - }
33.730 -
33.731 - switch (o->type) {
33.732 - case OPTION_BOOL:
33.733 - *(int *) o->data = 1;
33.734 - break;
33.735 -
33.736 - case OPTION_STRING:
33.737 - *(const char **) o->data = name + strlen(o->name) + 1;
33.738 - break;
33.739 -
33.740 - case OPTION_LAST:
33.741 - case OPTION_GROUP:
33.742 - /* Shouldn't happen. */
33.743 - break;
33.744 - }
33.745 -}
33.746 -
33.747 -static int
33.748 -parse_options(const struct option *options, int argc, const char **argv)
33.749 -{
33.750 - int i, j, k;
33.751 -
33.752 - for (i = 1, j = 0; i < argc; i++) {
33.753 - if (argv[i][0] != '-') {
33.754 - argv[j++] = argv[i];
33.755 - continue;
33.756 - }
33.757 -
33.758 - if (argv[i][1] == '-') {
33.759 - if (for_each_option(options, &argv[i][2], 0,
33.760 - handle_option, NULL) == 0) {
33.761 - printf("unknown option: %s\n", argv[i]);
33.762 - exit(1);
33.763 - }
33.764 - continue;
33.765 - }
33.766 -
33.767 - for (k = 1; argv[i][k]; k++) {
33.768 - if (for_each_option(options, NULL, argv[i][k],
33.769 - handle_option, NULL) == 0) {
33.770 - printf("unknown option: -%c\n", argv[i][k]);
33.771 - exit(1);
33.772 - }
33.773 - }
33.774 - }
33.775 -
33.776 - return j;
33.777 -}
33.778 -
33.779 -static void
33.780 -print_options_help(const struct option *options)
33.781 -{
33.782 - int i;
33.783 -
33.784 - for (i = 0; options[i].type != OPTION_LAST; i++) {
33.785 - switch (options[i].type) {
33.786 - case OPTION_GROUP:
33.787 - printf("%s\n", options[i].description);
33.788 - print_options_help(options[i].data);
33.789 - printf("\n");
33.790 - break;
33.791 -
33.792 - case OPTION_BOOL:
33.793 - case OPTION_STRING:
33.794 - printf(" ");
33.795 - if (options[i].short_name)
33.796 - printf("-%c", options[i].short_name);
33.797 - if (options[i].short_name && options[i].name)
33.798 - printf(", ");
33.799 - if (options[i].name)
33.800 - printf("--%s", options[i].name);
33.801 - if (options[i].arg_name)
33.802 - printf("=%s", options[i].arg_name);
33.803 - if (options[i].description)
33.804 - printf("\t\t%s", options[i].description);
33.805 - printf("\n");
33.806 - break;
33.807 -
33.808 - case OPTION_LAST:
33.809 - break;
33.810 - }
33.811 - }
33.812 -}
33.813 -
33.814 -static void
33.815 -print_options_usage(const struct option *options)
33.816 -{
33.817 - int i;
33.818 -
33.819 - for (i = 0; options[i].type != OPTION_LAST; i++) {
33.820 - switch (options[i].type) {
33.821 - case OPTION_GROUP:
33.822 - print_options_usage(options[i].data);
33.823 - break;
33.824 -
33.825 - case OPTION_BOOL:
33.826 - printf("[");
33.827 - if (options[i].short_name)
33.828 - printf("-%c", options[i].short_name);
33.829 - if (options[i].short_name && options[i].name)
33.830 - printf("|");
33.831 - if (options[i].name)
33.832 - printf("--%s", options[i].name);
33.833 - printf("] ");
33.834 - break;
33.835 -
33.836 - case OPTION_STRING:
33.837 - printf("[");
33.838 - if (options[i].short_name)
33.839 - printf("-%c", options[i].short_name);
33.840 - if (options[i].short_name && options[i].name)
33.841 - printf("|");
33.842 - if (options[i].name)
33.843 - printf("--%s", options[i].name);
33.844 - if (options[i].arg_name)
33.845 - printf("=%s", options[i].arg_name);
33.846 - printf("] ");
33.847 - break;
33.848 -
33.849 -
33.850 - break;
33.851 -
33.852 - case OPTION_LAST:
33.853 - break;
33.854 - }
33.855 - }
33.856 -}
33.857 -
33.858 -int
33.859 -main(int argc, const char *argv[])
33.860 -{
33.861 - argc = parse_options(rpm_options, argc, argv);
33.862 -
33.863 - if (option_version) {
33.864 - printf("razor rpm version hoopla.\n");
33.865 - exit(0);
33.866 - }
33.867 -
33.868 - if (option_help) {
33.869 - printf("Usage: rpm [OPTION...]\n");
33.870 - print_options_help(rpm_options);
33.871 - exit(0);
33.872 - }
33.873 -
33.874 - if (option_usage) {
33.875 - printf("Usage: rpm [OPTION...]\n");
33.876 - print_options_usage(rpm_options);
33.877 - printf("\n");
33.878 - exit(0);
33.879 - }
33.880 -
33.881 - if (option_initdb) {
33.882 - command_initdb(argc, argv);
33.883 - } else if (option_verify) {
33.884 - command_verify(argc, argv);
33.885 - } else if (option_query) {
33.886 - command_query(argc, argv);
33.887 - } else if (option_install) {
33.888 - command_install(argc, argv);
33.889 - } else if (option_upgrade) {
33.890 - command_update(argc, argv);
33.891 - } else if (option_erase) {
33.892 - command_erase(argc, argv);
33.893 - } else {
33.894 - print_options_usage(rpm_options);
33.895 - printf("\n");
33.896 - exit(0);
33.897 - }
33.898 -
33.899 - return 0;
33.900 -}
34.1 --- a/rpm.c Sun Jun 15 23:15:59 2008 -0400
34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
34.3 @@ -1,748 +0,0 @@
34.4 -/*
34.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
34.6 - * Copyright (C) 2008 Red Hat, Inc
34.7 - *
34.8 - * This program is free software; you can redistribute it and/or modify
34.9 - * it under the terms of the GNU General Public License as published by
34.10 - * the Free Software Foundation; either version 2 of the License, or
34.11 - * (at your option) any later version.
34.12 - *
34.13 - * This program is distributed in the hope that it will be useful,
34.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
34.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34.16 - * GNU General Public License for more details.
34.17 - *
34.18 - * You should have received a copy of the GNU General Public License along
34.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
34.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34.21 - */
34.22 -
34.23 -#include <stdio.h>
34.24 -#include <stddef.h>
34.25 -#include <string.h>
34.26 -#include <errno.h>
34.27 -#include <sys/stat.h>
34.28 -#include <sys/mman.h>
34.29 -#include <sys/types.h>
34.30 -#include <sys/wait.h>
34.31 -#include <fcntl.h>
34.32 -#include <unistd.h>
34.33 -#include <arpa/inet.h>
34.34 -#include <rpm/rpmlib.h>
34.35 -#include <rpm/rpmdb.h>
34.36 -#include <zlib.h>
34.37 -
34.38 -#include "razor.h"
34.39 -#include "razor-internal.h"
34.40 -
34.41 -#define RPM_LEAD_SIZE 96
34.42 -
34.43 -struct rpm_header {
34.44 - unsigned char magic[4];
34.45 - unsigned char reserved[4];
34.46 - int nindex;
34.47 - int hsize;
34.48 -};
34.49 -
34.50 -struct rpm_header_index {
34.51 - int tag;
34.52 - int type;
34.53 - int offset;
34.54 - int count;
34.55 -};
34.56 -
34.57 -struct razor_rpm {
34.58 - struct rpm_header *signature;
34.59 - struct rpm_header *header;
34.60 - const char **dirs;
34.61 - const char *pool;
34.62 - void *map;
34.63 - size_t size;
34.64 - void *payload;
34.65 -};
34.66 -
34.67 -static struct rpm_header_index *
34.68 -razor_rpm_get_header(struct razor_rpm *rpm, unsigned int tag)
34.69 -{
34.70 - struct rpm_header_index *index, *end;
34.71 -
34.72 - index = (struct rpm_header_index *) (rpm->header + 1);
34.73 - end = index + ntohl(rpm->header->nindex);
34.74 - while (index < end) {
34.75 - if (ntohl(index->tag) == tag)
34.76 - return index;
34.77 - index++;
34.78 - }
34.79 -
34.80 - return NULL;
34.81 -}
34.82 -
34.83 -static const void *
34.84 -razor_rpm_get_indirect(struct razor_rpm *rpm,
34.85 - unsigned int tag, unsigned int *count)
34.86 -{
34.87 - struct rpm_header_index *index;
34.88 -
34.89 - index = razor_rpm_get_header(rpm, tag);
34.90 - if (index != NULL) {
34.91 - if (count)
34.92 - *count = ntohl(index->count);
34.93 -
34.94 - return rpm->pool + ntohl(index->offset);
34.95 - }
34.96 -
34.97 - return NULL;
34.98 -}
34.99 -
34.100 -static enum razor_version_relation
34.101 -rpm_to_razor_flags (uint_32 flags)
34.102 -{
34.103 - switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
34.104 - case RPMSENSE_LESS:
34.105 - return RAZOR_VERSION_LESS;
34.106 - case RPMSENSE_LESS|RPMSENSE_EQUAL:
34.107 - return RAZOR_VERSION_LESS_OR_EQUAL;
34.108 - case RPMSENSE_EQUAL:
34.109 - return RAZOR_VERSION_EQUAL;
34.110 - case RPMSENSE_GREATER|RPMSENSE_EQUAL:
34.111 - return RAZOR_VERSION_GREATER_OR_EQUAL;
34.112 - case RPMSENSE_GREATER:
34.113 - return RAZOR_VERSION_GREATER;
34.114 - }
34.115 -
34.116 - /* FIXME? */
34.117 - return RAZOR_VERSION_EQUAL;
34.118 -}
34.119 -
34.120 -static void
34.121 -import_properties(struct razor_importer *importer, unsigned long type,
34.122 - struct razor_rpm *rpm,
34.123 - int name_tag, int version_tag, int flags_tag)
34.124 -{
34.125 - const char *name, *version;
34.126 - const uint_32 *flags;
34.127 - uint_32 f;
34.128 - unsigned int i, count;
34.129 -
34.130 - name = razor_rpm_get_indirect(rpm, name_tag, &count);
34.131 - if (name == NULL)
34.132 - return;
34.133 -
34.134 - flags = razor_rpm_get_indirect(rpm, flags_tag, &count);
34.135 -
34.136 - version = razor_rpm_get_indirect(rpm, version_tag, &count);
34.137 - for (i = 0; i < count; i++) {
34.138 - f = rpm_to_razor_flags(ntohl(flags[i]));
34.139 - razor_importer_add_property(importer, name, f, version, type);
34.140 - name += strlen(name) + 1;
34.141 - version += strlen(version) + 1;
34.142 - }
34.143 -}
34.144 -
34.145 -static void
34.146 -import_files(struct razor_importer *importer, struct razor_rpm *rpm)
34.147 -{
34.148 - const char *name;
34.149 - const uint32_t *index;
34.150 - unsigned int i, count;
34.151 - char buffer[256];
34.152 -
34.153 - /* assert: count is the same for all arrays */
34.154 -
34.155 - index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
34.156 - name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
34.157 - for (i = 0; i < count; i++) {
34.158 - snprintf(buffer, sizeof buffer,
34.159 - "%s%s", rpm->dirs[ntohl(*index)], name);
34.160 - razor_importer_add_file(importer, buffer);
34.161 - name += strlen(name) + 1;
34.162 - index++;
34.163 - }
34.164 -}
34.165 -
34.166 -struct razor_rpm *
34.167 -razor_rpm_open(const char *filename)
34.168 -{
34.169 - struct razor_rpm *rpm;
34.170 - struct rpm_header_index *base, *index;
34.171 - struct stat buf;
34.172 - unsigned int count, i, nindex, hsize;
34.173 - const char *name;
34.174 - int fd;
34.175 -
34.176 - rpm = malloc(sizeof *rpm);
34.177 - memset(rpm, 0, sizeof *rpm);
34.178 -
34.179 - fd = open(filename, O_RDONLY);
34.180 - if (fd < 0) {
34.181 - fprintf(stderr, "couldn't open %s\n", filename);
34.182 - return NULL;
34.183 - }
34.184 -
34.185 - if (fstat(fd, &buf) < 0) {
34.186 - fprintf(stderr, "failed to stat %s (%m)\n", filename);
34.187 - return NULL;
34.188 - }
34.189 -
34.190 - rpm->size = buf.st_size;
34.191 - rpm->map = mmap(NULL, rpm->size, PROT_READ, MAP_PRIVATE, fd, 0);
34.192 - if (rpm->map == MAP_FAILED) {
34.193 - fprintf(stderr, "couldn't mmap %s\n", filename);
34.194 - return NULL;
34.195 - }
34.196 - close(fd);
34.197 -
34.198 - rpm->signature = rpm->map + RPM_LEAD_SIZE;
34.199 - nindex = ntohl(rpm->signature->nindex);
34.200 - hsize = ntohl(rpm->signature->hsize);
34.201 - rpm->header = (void *) (rpm->signature + 1) +
34.202 - ALIGN(nindex * sizeof *index + hsize, 8);
34.203 - nindex = ntohl(rpm->header->nindex);
34.204 - hsize = ntohl(rpm->header->hsize);
34.205 - rpm->payload = (void *) (rpm->header + 1) +
34.206 - nindex * sizeof *index + hsize;
34.207 -
34.208 - base = (struct rpm_header_index *) (rpm->header + 1);
34.209 - rpm->pool = (void *) base + nindex * sizeof *index;
34.210 -
34.211 - /* Look up dir names now so we can index them directly. */
34.212 - name = razor_rpm_get_indirect(rpm, RPMTAG_DIRNAMES, &count);
34.213 - if (name) {
34.214 - rpm->dirs = calloc(count, sizeof *rpm->dirs);
34.215 - for (i = 0; i < count; i++) {
34.216 - rpm->dirs[i] = name;
34.217 - name += strlen(name) + 1;
34.218 - }
34.219 - } else {
34.220 - name = razor_rpm_get_indirect(rpm, RPMTAG_OLDFILENAMES,
34.221 - &count);
34.222 - if (name) {
34.223 - fprintf(stderr, "old filenames not supported\n");
34.224 - return NULL;
34.225 - }
34.226 - }
34.227 -
34.228 - return rpm;
34.229 -}
34.230 -
34.231 -struct cpio_file_header {
34.232 - char magic[6];
34.233 - char inode[8];
34.234 - char mode[8];
34.235 - char uid[8];
34.236 - char gid[8];
34.237 - char nlink[8];
34.238 - char mtime[8];
34.239 - char filesize[8];
34.240 - char devmajor[8];
34.241 - char devminor[8];
34.242 - char rdevmajor[8];
34.243 - char rdevminor[8];
34.244 - char namesize[8];
34.245 - char checksum[8];
34.246 - char filename[0];
34.247 -};
34.248 -
34.249 -/* gzip flags */
34.250 -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
34.251 -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
34.252 -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
34.253 -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
34.254 -#define COMMENT 0x10 /* bit 4 set: file comment present */
34.255 -#define RESERVED 0xE0 /* bits 5..7: reserved */
34.256 -
34.257 -struct installer {
34.258 - const char *root;
34.259 - struct razor_rpm *rpm;
34.260 - z_stream stream;
34.261 - unsigned char buffer[32768];
34.262 - size_t rest, length;
34.263 -};
34.264 -
34.265 -static int
34.266 -installer_inflate(struct installer *installer)
34.267 -{
34.268 - size_t length;
34.269 - int err;
34.270 -
34.271 - if (installer->rest > sizeof installer->buffer)
34.272 - length = sizeof installer->buffer;
34.273 - else
34.274 - length = installer->rest;
34.275 -
34.276 - installer->stream.next_out = installer->buffer;
34.277 - installer->stream.avail_out = length;
34.278 - err = inflate(&installer->stream, Z_SYNC_FLUSH);
34.279 - if (err != Z_OK && err != Z_STREAM_END) {
34.280 - fprintf(stderr, "inflate error: %d (%m)\n", err);
34.281 - return -1;
34.282 - }
34.283 -
34.284 - installer->rest -= length;
34.285 - installer->length = length;
34.286 -
34.287 - return 0;
34.288 -}
34.289 -
34.290 -static int
34.291 -installer_align(struct installer *installer, size_t size)
34.292 -{
34.293 - unsigned char buffer[4];
34.294 - int err;
34.295 -
34.296 - installer->stream.next_out = buffer;
34.297 - installer->stream.avail_out =
34.298 - (size - installer->stream.total_out) & (size - 1);
34.299 -
34.300 - if (installer->stream.avail_out == 0)
34.301 - return 0;
34.302 -
34.303 - err = inflate(&installer->stream, Z_SYNC_FLUSH);
34.304 - if (err != Z_OK && err != Z_STREAM_END) {
34.305 - fprintf(stderr, "inflate error: %d (%m)\n", err);
34.306 - return -1;
34.307 - }
34.308 -
34.309 - return 0;
34.310 -}
34.311 -
34.312 -static int
34.313 -create_path(struct installer *installer, const char *path, unsigned int mode)
34.314 -{
34.315 - char buffer[PATH_MAX];
34.316 - struct stat buf;
34.317 - int fd, ret;
34.318 -
34.319 - if (razor_create_dir(installer->root, path) < 0)
34.320 - return -1;
34.321 -
34.322 - snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
34.323 -
34.324 - switch (mode >> 12) {
34.325 - case REG:
34.326 - /* FIXME: handle the case where a file is already there. */
34.327 - fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, mode & 0x1ff);
34.328 - if (fd < 0){
34.329 - fprintf(stderr, "failed to create file %s\n", buffer);
34.330 - return -1;
34.331 - }
34.332 - while (installer->rest > 0) {
34.333 - if (installer_inflate(installer)) {
34.334 - fprintf(stderr, "failed to inflate\n");
34.335 - return -1;
34.336 - }
34.337 - if (razor_write(fd, installer->buffer,
34.338 - installer->length)) {
34.339 - fprintf(stderr, "failed to write payload\n");
34.340 - return -1;
34.341 - }
34.342 - }
34.343 - if (close(fd) < 0) {
34.344 - fprintf(stderr, "failed to close %s: %m\n", buffer);
34.345 - return -1;
34.346 - }
34.347 - return 0;
34.348 - case XDIR:
34.349 - ret = mkdir(buffer, mode & 0x1ff);
34.350 - if (ret == 0 || errno != EEXIST)
34.351 - return ret;
34.352 - if (stat(buffer, &buf) || !S_ISDIR(buf.st_mode)) {
34.353 - /* FIXME: also check that mode match. */
34.354 - fprintf(stderr,
34.355 - "%s exists but is not a directory\n", buffer);
34.356 - return -1;
34.357 - }
34.358 - return 0;
34.359 - case PIPE:
34.360 - case CDEV:
34.361 - case BDEV:
34.362 - case SOCK:
34.363 - printf("%s: unhandled file type %d\n", buffer, mode >> 12);
34.364 - return 0;
34.365 - case LINK:
34.366 - if (installer_inflate(installer)) {
34.367 - fprintf(stderr, "failed to inflate\n");
34.368 - return -1;
34.369 - }
34.370 - if (installer->length >= sizeof installer->buffer) {
34.371 - fprintf(stderr, "link name too long\n");
34.372 - return -1;
34.373 - }
34.374 - installer->buffer[installer->length] = '\0';
34.375 - if (symlink((const char *) installer->buffer, buffer)) {
34.376 - fprintf(stderr, "failed to create symlink, %m\n");
34.377 - return -1;
34.378 - }
34.379 - return 0;
34.380 - default:
34.381 - printf("%s: unknown file type %d\n", buffer, mode >> 12);
34.382 - return 0;
34.383 - }
34.384 -}
34.385 -
34.386 -static int
34.387 -run_script(struct installer *installer,
34.388 - unsigned int program_tag, unsigned int script_tag)
34.389 -{
34.390 - int pid, status, fd[2];
34.391 - const char *script = NULL, *program = NULL;
34.392 -
34.393 - program = razor_rpm_get_indirect(installer->rpm, program_tag, NULL);
34.394 - script = razor_rpm_get_indirect(installer->rpm, script_tag, NULL);
34.395 - if (program == NULL && script == NULL) {
34.396 - return 0;
34.397 - } else if (program == NULL) {
34.398 - program = "/bin/sh";
34.399 - }
34.400 -
34.401 - if (pipe(fd) < 0) {
34.402 - fprintf(stderr, "failed to create pipe\n");
34.403 - return -1;
34.404 - }
34.405 - pid = fork();
34.406 - if (pid < 0) {
34.407 - fprintf(stderr, "failed to fork, %m\n");
34.408 - } else if (pid == 0) {
34.409 - if (dup2(fd[0], STDIN_FILENO) < 0) {
34.410 - fprintf(stderr, "failed redirect stdin, %m\n");
34.411 - return -1;
34.412 - }
34.413 - if (close(fd[0]) < 0 || close(fd[1]) < 0) {
34.414 - fprintf(stderr, "failed to close pipe, %m\n");
34.415 - return -1;
34.416 - }
34.417 - if (chroot(installer->root) < 0) {
34.418 - fprintf(stderr, "failed to chroot to %s, %m\n",
34.419 - installer->root);
34.420 - return -1;
34.421 - }
34.422 - printf("executing program %s in chroot %s\n",
34.423 - program, installer->root);
34.424 - if (execl(program, program, NULL)) {
34.425 - fprintf(stderr, "failed to exec %s, %m\n", program);
34.426 - exit(-1);
34.427 - }
34.428 - } else {
34.429 - if (script && razor_write(fd[1], script, strlen(script)) < 0) {
34.430 - fprintf(stderr, "failed to pipe script, %m\n");
34.431 - return -1;
34.432 - }
34.433 - if (close(fd[0]) || close(fd[1])) {
34.434 - fprintf(stderr, "failed to close pipe, %m\n");
34.435 - return -1;
34.436 - }
34.437 - if (wait(&status) < 0) {
34.438 - fprintf(stderr, "wait for child failed, %m");
34.439 - return -1;
34.440 - }
34.441 - if (status)
34.442 - printf("script exited with status %d\n", status);
34.443 - }
34.444 -
34.445 - return 0;
34.446 -}
34.447 -
34.448 -static int
34.449 -installer_init(struct installer *installer)
34.450 -{
34.451 - unsigned char *gz_header;
34.452 - int method, flags, err;
34.453 -
34.454 - gz_header = installer->rpm->payload;
34.455 - if (gz_header[0] != 0x1f || gz_header[1] != 0x8b) {
34.456 - fprintf(stderr, "payload section doesn't have gz header\n");
34.457 - return -1;
34.458 - }
34.459 -
34.460 - method = gz_header[2];
34.461 - flags = gz_header[3];
34.462 -
34.463 - if (method != Z_DEFLATED || flags != 0) {
34.464 - fprintf(stderr,
34.465 - "unknown payload compression method or flags set\n");
34.466 - return -1;
34.467 - }
34.468 -
34.469 - installer->stream.zalloc = NULL;
34.470 - installer->stream.zfree = NULL;
34.471 - installer->stream.opaque = NULL;
34.472 -
34.473 - installer->stream.next_in = gz_header + 10;
34.474 - installer->stream.avail_in =
34.475 - (installer->rpm->map + installer->rpm->size) -
34.476 - (void *) installer->stream.next_in;
34.477 - installer->stream.next_out = NULL;
34.478 - installer->stream.avail_out = 0;
34.479 -
34.480 - err = inflateInit2(&installer->stream, -MAX_WBITS);
34.481 - if (err != Z_OK) {
34.482 - fprintf(stderr, "inflateInit error: %d\n", err);
34.483 - return -1;
34.484 - }
34.485 -
34.486 - return 0;
34.487 -}
34.488 -
34.489 -static int
34.490 -installer_finish(struct installer *installer)
34.491 -{
34.492 - int err;
34.493 -
34.494 - err = inflateEnd(&installer->stream);
34.495 -
34.496 - if (err != Z_OK) {
34.497 - fprintf(stderr, "inflateEnd error: %d\n", err);
34.498 - return -1;
34.499 - }
34.500 -
34.501 - return 0;
34.502 -}
34.503 -
34.504 -static unsigned long
34.505 -fixed_hex_to_ulong(const char *hex, int length)
34.506 -{
34.507 - long l;
34.508 - int i;
34.509 -
34.510 - for (i = 0, l = 0; i < length; i++) {
34.511 - if (hex[i] < 'a')
34.512 - l = l * 16 + hex[i] - '0';
34.513 - else
34.514 - l = l * 16 + hex[i] - 'a' + 10;
34.515 - }
34.516 -
34.517 - return l;
34.518 -}
34.519 -
34.520 -int
34.521 -razor_rpm_install(struct razor_rpm *rpm, const char *root)
34.522 -{
34.523 - struct installer installer;
34.524 - struct cpio_file_header *header;
34.525 - struct stat buf;
34.526 - unsigned int mode;
34.527 - char *path;
34.528 - size_t filesize;
34.529 -
34.530 - installer.rpm = rpm;
34.531 - installer.root = root;
34.532 -
34.533 - /* FIXME: Only do this before a transaction, not per rpm. */
34.534 - if (stat(root, &buf) < 0 || !S_ISDIR(buf.st_mode)) {
34.535 - fprintf(stderr,
34.536 - "root installation directory \"%s\" does not exist\n",
34.537 - root);
34.538 - return -1;
34.539 - }
34.540 -
34.541 - if (installer_init(&installer))
34.542 - return -1;
34.543 -
34.544 - run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
34.545 -
34.546 - while (installer.stream.avail_in > 0) {
34.547 - installer.rest = sizeof *header;
34.548 - if (installer_inflate(&installer))
34.549 - return -1;
34.550 -
34.551 - header = (struct cpio_file_header *) installer.buffer;
34.552 - mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
34.553 - filesize = fixed_hex_to_ulong(header->filesize,
34.554 - sizeof header->filesize);
34.555 -
34.556 - installer.rest = fixed_hex_to_ulong(header->namesize,
34.557 - sizeof header->namesize);
34.558 -
34.559 - if (installer_inflate(&installer) ||
34.560 - installer_align(&installer, 4))
34.561 - return -1;
34.562 -
34.563 - path = (char *) installer.buffer;
34.564 - /* This convention is so lame... */
34.565 - if (strcmp(path, "TRAILER!!!") == 0)
34.566 - break;
34.567 -
34.568 - installer.rest = filesize;
34.569 - if (create_path(&installer, path + 1, mode) < 0)
34.570 - return -1;
34.571 - if (installer_align(&installer, 4))
34.572 - return -1;
34.573 - }
34.574 -
34.575 - if (installer_finish(&installer))
34.576 - return -1;
34.577 -
34.578 - run_script(&installer, RPMTAG_POSTINPROG, RPMTAG_POSTIN);
34.579 -
34.580 - return 0;
34.581 -}
34.582 -
34.583 -int
34.584 -razor_rpm_close(struct razor_rpm *rpm)
34.585 -{
34.586 - int err;
34.587 -
34.588 - free(rpm->dirs);
34.589 - err = munmap(rpm->map, rpm->size);
34.590 - free(rpm);
34.591 -
34.592 - return err;
34.593 -}
34.594 -
34.595 -int
34.596 -razor_importer_add_rpm(struct razor_importer *importer, struct razor_rpm *rpm)
34.597 -{
34.598 - const char *name, *version, *release, *arch;
34.599 - const uint_32 *epoch;
34.600 - char evr[128], buf[16];
34.601 -
34.602 - name = razor_rpm_get_indirect(rpm, RPMTAG_NAME, NULL);
34.603 - epoch = razor_rpm_get_indirect(rpm, RPMTAG_EPOCH, NULL);
34.604 - version = razor_rpm_get_indirect(rpm, RPMTAG_VERSION, NULL);
34.605 - release = razor_rpm_get_indirect(rpm, RPMTAG_RELEASE, NULL);
34.606 - arch = razor_rpm_get_indirect(rpm, RPMTAG_ARCH, NULL);
34.607 -
34.608 - if (epoch) {
34.609 - snprintf(buf, sizeof buf, "%u", ntohl(*epoch));
34.610 - razor_build_evr(evr, sizeof evr, buf, version, release);
34.611 - } else {
34.612 - razor_build_evr(evr, sizeof evr, NULL, version, release);
34.613 - }
34.614 - razor_importer_begin_package(importer, name, evr, arch);
34.615 -
34.616 - import_properties(importer, RAZOR_PROPERTY_REQUIRES, rpm,
34.617 - RPMTAG_REQUIRENAME,
34.618 - RPMTAG_REQUIREVERSION,
34.619 - RPMTAG_REQUIREFLAGS);
34.620 -
34.621 - import_properties(importer, RAZOR_PROPERTY_PROVIDES, rpm,
34.622 - RPMTAG_PROVIDENAME,
34.623 - RPMTAG_PROVIDEVERSION,
34.624 - RPMTAG_PROVIDEFLAGS);
34.625 -
34.626 - import_properties(importer, RAZOR_PROPERTY_OBSOLETES, rpm,
34.627 - RPMTAG_OBSOLETENAME,
34.628 - RPMTAG_OBSOLETEVERSION,
34.629 - RPMTAG_OBSOLETEFLAGS);
34.630 -
34.631 - import_properties(importer, RAZOR_PROPERTY_CONFLICTS, rpm,
34.632 - RPMTAG_CONFLICTNAME,
34.633 - RPMTAG_CONFLICTVERSION,
34.634 - RPMTAG_CONFLICTFLAGS);
34.635 -
34.636 - import_files(importer, rpm);
34.637 -
34.638 - razor_importer_finish_package(importer);
34.639 -
34.640 - return 0;
34.641 -}
34.642 -
34.643 -union rpm_entry {
34.644 - void *p;
34.645 - char *string;
34.646 - char **list;
34.647 - uint_32 *flags;
34.648 - uint_32 integer;
34.649 -};
34.650 -
34.651 -static void
34.652 -add_properties(struct razor_importer *importer,
34.653 - enum razor_property_type property_type,
34.654 - Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
34.655 -{
34.656 - union rpm_entry names, versions, flags;
34.657 - int_32 i, type, count;
34.658 -
34.659 - headerGetEntry(h, name_tag, &type, &names.p, &count);
34.660 - headerGetEntry(h, version_tag, &type, &versions.p, &count);
34.661 - headerGetEntry(h, flags_tag, &type, &flags.p, &count);
34.662 -
34.663 - for (i = 0; i < count; i++)
34.664 - razor_importer_add_property(importer,
34.665 - names.list[i],
34.666 - rpm_to_razor_flags (flags.flags[i]),
34.667 - versions.list[i],
34.668 - property_type);
34.669 -}
34.670 -
34.671 -struct razor_set *
34.672 -razor_set_create_from_rpmdb(void)
34.673 -{
34.674 - struct razor_importer *importer;
34.675 - rpmdbMatchIterator iter;
34.676 - Header h;
34.677 - int_32 type, count, i;
34.678 - union rpm_entry name, epoch, version, release, arch;
34.679 - union rpm_entry basenames, dirnames, dirindexes;
34.680 - char filename[PATH_MAX], evr[128], buf[16];
34.681 - rpmdb db;
34.682 -
34.683 - rpmReadConfigFiles(NULL, NULL);
34.684 -
34.685 - if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
34.686 - fprintf(stderr, "cannot open rpm database\n");
34.687 - exit(1);
34.688 - }
34.689 -
34.690 - importer = razor_importer_new();
34.691 -
34.692 - iter = rpmdbInitIterator(db, 0, NULL, 0);
34.693 - while (h = rpmdbNextIterator(iter), h != NULL) {
34.694 - headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
34.695 - headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
34.696 - headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
34.697 - headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
34.698 - headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
34.699 -
34.700 - if (epoch.flags != NULL) {
34.701 - snprintf(buf, sizeof buf, "%u", *epoch.flags);
34.702 - razor_build_evr(evr, sizeof evr,
34.703 - buf, version.string, release.string);
34.704 - } else {
34.705 - razor_build_evr(evr, sizeof evr,
34.706 - NULL, version.string, release.string);
34.707 - }
34.708 -
34.709 - razor_importer_begin_package(importer,
34.710 - name.string, evr, arch.string);
34.711 -
34.712 - add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
34.713 - RPMTAG_REQUIRENAME,
34.714 - RPMTAG_REQUIREVERSION,
34.715 - RPMTAG_REQUIREFLAGS);
34.716 -
34.717 - add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
34.718 - RPMTAG_PROVIDENAME,
34.719 - RPMTAG_PROVIDEVERSION,
34.720 - RPMTAG_PROVIDEFLAGS);
34.721 -
34.722 - add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
34.723 - RPMTAG_OBSOLETENAME,
34.724 - RPMTAG_OBSOLETEVERSION,
34.725 - RPMTAG_OBSOLETEFLAGS);
34.726 -
34.727 - add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
34.728 - RPMTAG_CONFLICTNAME,
34.729 - RPMTAG_CONFLICTVERSION,
34.730 - RPMTAG_CONFLICTFLAGS);
34.731 -
34.732 - headerGetEntry(h, RPMTAG_BASENAMES, &type,
34.733 - &basenames.p, &count);
34.734 - headerGetEntry(h, RPMTAG_DIRNAMES, &type,
34.735 - &dirnames.p, &count);
34.736 - headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
34.737 - &dirindexes.p, &count);
34.738 - for (i = 0; i < count; i++) {
34.739 - snprintf(filename, sizeof filename, "%s%s",
34.740 - dirnames.list[dirindexes.flags[i]],
34.741 - basenames.list[i]);
34.742 - razor_importer_add_file(importer, filename);
34.743 - }
34.744 -
34.745 - razor_importer_finish_package(importer);
34.746 - }
34.747 -
34.748 - rpmdbClose(db);
34.749 -
34.750 - return razor_importer_finish(importer);
34.751 -}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/src/.gitignore Mon Jun 16 15:40:30 2008 -0400
35.3 @@ -0,0 +1,5 @@
35.4 +.deps
35.5 +.libs
35.6 +razor
35.7 +rpm-razor
35.8 +
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/src/Makefile.am Mon Jun 16 15:40:30 2008 -0400
36.3 @@ -0,0 +1,26 @@
36.4 +## Process this file with automake to produce Makefile.in
36.5 +
36.6 +INCLUDES = \
36.7 + $(CURL_CFLAGS) \
36.8 + $(EXPAT_CFLAGS) \
36.9 + $(RPM_CFLAGS) \
36.10 + -I$(top_builddir)/src -I$(top_srcdir)/src \
36.11 + -I$(top_srcdir)/librazor \
36.12 + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
36.13 + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
36.14 + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
36.15 + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \
36.16 + -DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
36.17 + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\"
36.18 +
36.19 +bin_PROGRAMS = razor rpm
36.20 +
36.21 +razor_SOURCES = main.c import-rpmdb.c import-yum.c
36.22 +razor_LDADD = $(RPM_LIBS) $(EXPAT_LIBS) $(CURL_LIBS) $(top_builddir)/librazor/librazor.la
36.23 +
36.24 +rpm_SOURCES = rpm.c
36.25 +rpm_LDADD = $(top_builddir)/librazor/librazor.la
36.26 +
36.27 +clean-local :
36.28 + rm -f *~
36.29 +
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/src/import-rpmdb.c Mon Jun 16 15:40:30 2008 -0400
37.3 @@ -0,0 +1,157 @@
37.4 +/*
37.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
37.6 + * Copyright (C) 2008 Red Hat, Inc
37.7 + *
37.8 + * This program is free software; you can redistribute it and/or modify
37.9 + * it under the terms of the GNU General Public License as published by
37.10 + * the Free Software Foundation; either version 2 of the License, or
37.11 + * (at your option) any later version.
37.12 + *
37.13 + * This program is distributed in the hope that it will be useful,
37.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
37.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37.16 + * GNU General Public License for more details.
37.17 + *
37.18 + * You should have received a copy of the GNU General Public License along
37.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
37.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37.21 + */
37.22 +
37.23 +#include <stdio.h>
37.24 +#include <stddef.h>
37.25 +#include <string.h>
37.26 +#include <fcntl.h>
37.27 +#include <rpm/rpmlib.h>
37.28 +#include <rpm/rpmdb.h>
37.29 +
37.30 +#include "razor.h"
37.31 +
37.32 +union rpm_entry {
37.33 + void *p;
37.34 + char *string;
37.35 + char **list;
37.36 + uint_32 *flags;
37.37 + uint_32 integer;
37.38 +};
37.39 +
37.40 +static enum razor_version_relation
37.41 +rpm_to_razor_flags (uint_32 flags)
37.42 +{
37.43 + switch (flags & (RPMSENSE_LESS | RPMSENSE_EQUAL | RPMSENSE_GREATER)) {
37.44 + case RPMSENSE_LESS:
37.45 + return RAZOR_VERSION_LESS;
37.46 + case RPMSENSE_LESS|RPMSENSE_EQUAL:
37.47 + return RAZOR_VERSION_LESS_OR_EQUAL;
37.48 + case RPMSENSE_EQUAL:
37.49 + return RAZOR_VERSION_EQUAL;
37.50 + case RPMSENSE_GREATER|RPMSENSE_EQUAL:
37.51 + return RAZOR_VERSION_GREATER_OR_EQUAL;
37.52 + case RPMSENSE_GREATER:
37.53 + return RAZOR_VERSION_GREATER;
37.54 + }
37.55 +
37.56 + /* FIXME? */
37.57 + return RAZOR_VERSION_EQUAL;
37.58 +}
37.59 +
37.60 +static void
37.61 +add_properties(struct razor_importer *importer,
37.62 + enum razor_property_type property_type,
37.63 + Header h, int_32 name_tag, int_32 version_tag, int_32 flags_tag)
37.64 +{
37.65 + union rpm_entry names, versions, flags;
37.66 + int_32 i, type, count;
37.67 +
37.68 + headerGetEntry(h, name_tag, &type, &names.p, &count);
37.69 + headerGetEntry(h, version_tag, &type, &versions.p, &count);
37.70 + headerGetEntry(h, flags_tag, &type, &flags.p, &count);
37.71 +
37.72 + for (i = 0; i < count; i++)
37.73 + razor_importer_add_property(importer,
37.74 + names.list[i],
37.75 + rpm_to_razor_flags (flags.flags[i]),
37.76 + versions.list[i],
37.77 + property_type);
37.78 +}
37.79 +
37.80 +struct razor_set *
37.81 +razor_set_create_from_rpmdb(void)
37.82 +{
37.83 + struct razor_importer *importer;
37.84 + rpmdbMatchIterator iter;
37.85 + Header h;
37.86 + int_32 type, count, i;
37.87 + union rpm_entry name, epoch, version, release, arch;
37.88 + union rpm_entry basenames, dirnames, dirindexes;
37.89 + char filename[PATH_MAX], evr[128], buf[16];
37.90 + rpmdb db;
37.91 +
37.92 + rpmReadConfigFiles(NULL, NULL);
37.93 +
37.94 + if (rpmdbOpen("", &db, O_RDONLY, 0644) != 0) {
37.95 + fprintf(stderr, "cannot open rpm database\n");
37.96 + exit(1);
37.97 + }
37.98 +
37.99 + importer = razor_importer_new();
37.100 +
37.101 + iter = rpmdbInitIterator(db, 0, NULL, 0);
37.102 + while (h = rpmdbNextIterator(iter), h != NULL) {
37.103 + headerGetEntry(h, RPMTAG_NAME, &type, &name.p, &count);
37.104 + headerGetEntry(h, RPMTAG_EPOCH, &type, &epoch.p, &count);
37.105 + headerGetEntry(h, RPMTAG_VERSION, &type, &version.p, &count);
37.106 + headerGetEntry(h, RPMTAG_RELEASE, &type, &release.p, &count);
37.107 + headerGetEntry(h, RPMTAG_ARCH, &type, &arch.p, &count);
37.108 +
37.109 + if (epoch.flags != NULL) {
37.110 + snprintf(buf, sizeof buf, "%u", *epoch.flags);
37.111 + razor_build_evr(evr, sizeof evr,
37.112 + buf, version.string, release.string);
37.113 + } else {
37.114 + razor_build_evr(evr, sizeof evr,
37.115 + NULL, version.string, release.string);
37.116 + }
37.117 +
37.118 + razor_importer_begin_package(importer,
37.119 + name.string, evr, arch.string);
37.120 +
37.121 + add_properties(importer, RAZOR_PROPERTY_REQUIRES, h,
37.122 + RPMTAG_REQUIRENAME,
37.123 + RPMTAG_REQUIREVERSION,
37.124 + RPMTAG_REQUIREFLAGS);
37.125 +
37.126 + add_properties(importer, RAZOR_PROPERTY_PROVIDES, h,
37.127 + RPMTAG_PROVIDENAME,
37.128 + RPMTAG_PROVIDEVERSION,
37.129 + RPMTAG_PROVIDEFLAGS);
37.130 +
37.131 + add_properties(importer, RAZOR_PROPERTY_OBSOLETES, h,
37.132 + RPMTAG_OBSOLETENAME,
37.133 + RPMTAG_OBSOLETEVERSION,
37.134 + RPMTAG_OBSOLETEFLAGS);
37.135 +
37.136 + add_properties(importer, RAZOR_PROPERTY_CONFLICTS, h,
37.137 + RPMTAG_CONFLICTNAME,
37.138 + RPMTAG_CONFLICTVERSION,
37.139 + RPMTAG_CONFLICTFLAGS);
37.140 +
37.141 + headerGetEntry(h, RPMTAG_BASENAMES, &type,
37.142 + &basenames.p, &count);
37.143 + headerGetEntry(h, RPMTAG_DIRNAMES, &type,
37.144 + &dirnames.p, &count);
37.145 + headerGetEntry(h, RPMTAG_DIRINDEXES, &type,
37.146 + &dirindexes.p, &count);
37.147 + for (i = 0; i < count; i++) {
37.148 + snprintf(filename, sizeof filename, "%s%s",
37.149 + dirnames.list[dirindexes.flags[i]],
37.150 + basenames.list[i]);
37.151 + razor_importer_add_file(importer, filename);
37.152 + }
37.153 +
37.154 + razor_importer_finish_package(importer);
37.155 + }
37.156 +
37.157 + rpmdbClose(db);
37.158 +
37.159 + return razor_importer_finish(importer);
37.160 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/src/import-yum.c Mon Jun 16 15:40:30 2008 -0400
38.3 @@ -0,0 +1,337 @@
38.4 +/*
38.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
38.6 + * Copyright (C) 2008 Red Hat, Inc
38.7 + *
38.8 + * This program is free software; you can redistribute it and/or modify
38.9 + * it under the terms of the GNU General Public License as published by
38.10 + * the Free Software Foundation; either version 2 of the License, or
38.11 + * (at your option) any later version.
38.12 + *
38.13 + * This program is distributed in the hope that it will be useful,
38.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
38.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38.16 + * GNU General Public License for more details.
38.17 + *
38.18 + * You should have received a copy of the GNU General Public License along
38.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
38.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38.21 + */
38.22 +
38.23 +#define _GNU_SOURCE
38.24 +
38.25 +#include <string.h>
38.26 +#include <stdio.h>
38.27 +#include <sys/stat.h>
38.28 +#include <sys/mman.h>
38.29 +#include <unistd.h>
38.30 +#include <fcntl.h>
38.31 +#include <errno.h>
38.32 +
38.33 +#include <expat.h>
38.34 +#include <zlib.h>
38.35 +#include "razor.h"
38.36 +
38.37 +/* Import a yum filelist as a razor package set. */
38.38 +
38.39 +enum {
38.40 + YUM_STATE_BEGIN,
38.41 + YUM_STATE_PACKAGE_NAME,
38.42 + YUM_STATE_PACKAGE_ARCH,
38.43 + YUM_STATE_CHECKSUM,
38.44 + YUM_STATE_REQUIRES,
38.45 + YUM_STATE_PROVIDES,
38.46 + YUM_STATE_OBSOLETES,
38.47 + YUM_STATE_CONFLICTS,
38.48 + YUM_STATE_FILE
38.49 +};
38.50 +
38.51 +struct yum_context {
38.52 + XML_Parser primary_parser;
38.53 + XML_Parser filelists_parser;
38.54 + XML_Parser current_parser;
38.55 +
38.56 + struct razor_importer *importer;
38.57 + struct import_property_context *current_property_context;
38.58 + char name[256], arch[64], buffer[512], *p;
38.59 + char pkgid[128];
38.60 + int state;
38.61 +};
38.62 +
38.63 +static enum razor_version_relation
38.64 +yum_to_razor_flags (const char *flags)
38.65 +{
38.66 + /* FIXME? */
38.67 + if (!flags)
38.68 + return RAZOR_VERSION_EQUAL;
38.69 +
38.70 + if (flags[0] == 'L') {
38.71 + if (flags[1] == 'T')
38.72 + return RAZOR_VERSION_LESS;
38.73 + else
38.74 + return RAZOR_VERSION_LESS_OR_EQUAL;
38.75 + } else if (flags[0] == 'G') {
38.76 + if (flags[1] == 'T')
38.77 + return RAZOR_VERSION_GREATER;
38.78 + else
38.79 + return RAZOR_VERSION_GREATER_OR_EQUAL;
38.80 + } else
38.81 + return RAZOR_VERSION_EQUAL;
38.82 +}
38.83 +
38.84 +static void
38.85 +yum_primary_start_element(void *data, const char *name, const char **atts)
38.86 +{
38.87 + struct yum_context *ctx = data;
38.88 + const char *n, *epoch, *version, *release, *flags;
38.89 + char buffer[128];
38.90 + int i;
38.91 +
38.92 + if (strcmp(name, "name") == 0) {
38.93 + ctx->state = YUM_STATE_PACKAGE_NAME;
38.94 + ctx->p = ctx->name;
38.95 + } else if (strcmp(name, "arch") == 0) {
38.96 + ctx->state = YUM_STATE_PACKAGE_ARCH;
38.97 + ctx->p = ctx->arch;
38.98 + } else if (strcmp(name, "version") == 0) {
38.99 + epoch = NULL;
38.100 + version = NULL;
38.101 + release = NULL;
38.102 + for (i = 0; atts[i]; i += 2) {
38.103 + if (strcmp(atts[i], "epoch") == 0)
38.104 + epoch = atts[i + 1];
38.105 + else if (strcmp(atts[i], "ver") == 0)
38.106 + version = atts[i + 1];
38.107 + else if (strcmp(atts[i], "rel") == 0)
38.108 + release = atts[i + 1];
38.109 + }
38.110 + if (version == NULL || release == NULL) {
38.111 + fprintf(stderr, "invalid version tag, "
38.112 + "missing version or release attribute\n");
38.113 + return;
38.114 + }
38.115 +
38.116 + razor_build_evr(buffer, sizeof buffer, epoch, version, release);
38.117 + razor_importer_begin_package(ctx->importer,
38.118 + ctx->name, buffer, ctx->arch);
38.119 + } else if (strcmp(name, "checksum") == 0) {
38.120 + ctx->p = ctx->pkgid;
38.121 + ctx->state = YUM_STATE_CHECKSUM;
38.122 + } else if (strcmp(name, "rpm:requires") == 0) {
38.123 + ctx->state = YUM_STATE_REQUIRES;
38.124 + } else if (strcmp(name, "rpm:provides") == 0) {
38.125 + ctx->state = YUM_STATE_PROVIDES;
38.126 + } else if (strcmp(name, "rpm:obsoletes") == 0) {
38.127 + ctx->state = YUM_STATE_OBSOLETES;
38.128 + } else if (strcmp(name, "rpm:conflicts") == 0) {
38.129 + ctx->state = YUM_STATE_CONFLICTS;
38.130 + } else if (strcmp(name, "rpm:entry") == 0 &&
38.131 + ctx->state != YUM_STATE_BEGIN) {
38.132 + n = NULL;
38.133 + epoch = NULL;
38.134 + version = NULL;
38.135 + release = NULL;
38.136 + flags = NULL;
38.137 + for (i = 0; atts[i]; i += 2) {
38.138 + if (strcmp(atts[i], "name") == 0)
38.139 + n = atts[i + 1];
38.140 + else if (strcmp(atts[i], "epoch") == 0)
38.141 + epoch = atts[i + 1];
38.142 + else if (strcmp(atts[i], "ver") == 0)
38.143 + version = atts[i + 1];
38.144 + else if (strcmp(atts[i], "rel") == 0)
38.145 + release = atts[i + 1];
38.146 + else if (strcmp(atts[i], "flags") == 0)
38.147 + flags = atts[i + 1];
38.148 + }
38.149 +
38.150 + if (n == NULL) {
38.151 + fprintf(stderr, "invalid rpm:entry, "
38.152 + "missing name or version attributes\n");
38.153 + return;
38.154 + }
38.155 +
38.156 + razor_build_evr(buffer, sizeof buffer, epoch, version, release);
38.157 + switch (ctx->state) {
38.158 + case YUM_STATE_REQUIRES:
38.159 + razor_importer_add_property(ctx->importer, n,
38.160 + yum_to_razor_flags (flags),
38.161 + buffer,
38.162 + RAZOR_PROPERTY_REQUIRES);
38.163 + break;
38.164 + case YUM_STATE_PROVIDES:
38.165 + razor_importer_add_property(ctx->importer, n,
38.166 + yum_to_razor_flags (flags),
38.167 + buffer,
38.168 + RAZOR_PROPERTY_PROVIDES);
38.169 + break;
38.170 + case YUM_STATE_OBSOLETES:
38.171 + razor_importer_add_property(ctx->importer, n,
38.172 + yum_to_razor_flags (flags),
38.173 + buffer,
38.174 + RAZOR_PROPERTY_OBSOLETES);
38.175 + break;
38.176 + case YUM_STATE_CONFLICTS:
38.177 + razor_importer_add_property(ctx->importer, n,
38.178 + yum_to_razor_flags (flags),
38.179 + buffer,
38.180 + RAZOR_PROPERTY_CONFLICTS);
38.181 + break;
38.182 + }
38.183 + }
38.184 +}
38.185 +
38.186 +static void
38.187 +yum_primary_end_element (void *data, const char *name)
38.188 +{
38.189 + struct yum_context *ctx = data;
38.190 +
38.191 + switch (ctx->state) {
38.192 + case YUM_STATE_PACKAGE_NAME:
38.193 + case YUM_STATE_PACKAGE_ARCH:
38.194 + case YUM_STATE_CHECKSUM:
38.195 + case YUM_STATE_FILE:
38.196 + ctx->state = YUM_STATE_BEGIN;
38.197 + break;
38.198 + }
38.199 +
38.200 + if (strcmp(name, "package") == 0) {
38.201 + XML_StopParser(ctx->current_parser, XML_TRUE);
38.202 + ctx->current_parser = ctx->filelists_parser;
38.203 + }
38.204 +}
38.205 +
38.206 +static void
38.207 +yum_character_data (void *data, const XML_Char *s, int len)
38.208 +{
38.209 + struct yum_context *ctx = data;
38.210 +
38.211 + switch (ctx->state) {
38.212 + case YUM_STATE_PACKAGE_NAME:
38.213 + case YUM_STATE_PACKAGE_ARCH:
38.214 + case YUM_STATE_CHECKSUM:
38.215 + case YUM_STATE_FILE:
38.216 + memcpy(ctx->p, s, len);
38.217 + ctx->p += len;
38.218 + *ctx->p = '\0';
38.219 + break;
38.220 + }
38.221 +}
38.222 +
38.223 +static void
38.224 +yum_filelists_start_element(void *data, const char *name, const char **atts)
38.225 +{
38.226 + struct yum_context *ctx = data;
38.227 + const char *pkg, *pkgid;
38.228 + int i;
38.229 +
38.230 + if (strcmp(name, "package") == 0) {
38.231 + pkg = NULL;
38.232 + pkgid = NULL;
38.233 + for (i = 0; atts[i]; i += 2) {
38.234 + if (strcmp(atts[i], "name") == 0)
38.235 + pkg = atts[i + 1];
38.236 + else if (strcmp(atts[i], "pkgid") == 0)
38.237 + pkgid = atts[i + 1];
38.238 + }
38.239 + if (strcmp(pkgid, ctx->pkgid) != 0)
38.240 + fprintf(stderr, "primary.xml and filelists.xml "
38.241 + "mismatch for %s: %s vs %s",
38.242 + pkg, pkgid, ctx->pkgid);
38.243 + } else if (strcmp(name, "file") == 0) {
38.244 + ctx->state = YUM_STATE_FILE;
38.245 + ctx->p = ctx->buffer;
38.246 + }
38.247 +}
38.248 +
38.249 +
38.250 +static void
38.251 +yum_filelists_end_element (void *data, const char *name)
38.252 +{
38.253 + struct yum_context *ctx = data;
38.254 +
38.255 + ctx->state = YUM_STATE_BEGIN;
38.256 + if (strcmp(name, "package") == 0) {
38.257 + XML_StopParser(ctx->current_parser, XML_TRUE);
38.258 + ctx->current_parser = ctx->primary_parser;
38.259 + razor_importer_finish_package(ctx->importer);
38.260 + } else if (strcmp(name, "file") == 0)
38.261 + razor_importer_add_file(ctx->importer, ctx->buffer);
38.262 +
38.263 +}
38.264 +
38.265 +#define XML_BUFFER_SIZE 4096
38.266 +
38.267 +struct razor_set *
38.268 +razor_set_create_from_yum(void)
38.269 +{
38.270 + struct yum_context ctx;
38.271 + void *buf;
38.272 + int len, ret;
38.273 + gzFile primary, filelists;
38.274 + XML_ParsingStatus status;
38.275 +
38.276 + ctx.importer = razor_importer_new();
38.277 + ctx.state = YUM_STATE_BEGIN;
38.278 +
38.279 + ctx.primary_parser = XML_ParserCreate(NULL);
38.280 + XML_SetUserData(ctx.primary_parser, &ctx);
38.281 + XML_SetElementHandler(ctx.primary_parser,
38.282 + yum_primary_start_element,
38.283 + yum_primary_end_element);
38.284 + XML_SetCharacterDataHandler(ctx.primary_parser,
38.285 + yum_character_data);
38.286 +
38.287 + ctx.filelists_parser = XML_ParserCreate(NULL);
38.288 + XML_SetUserData(ctx.filelists_parser, &ctx);
38.289 + XML_SetElementHandler(ctx.filelists_parser,
38.290 + yum_filelists_start_element,
38.291 + yum_filelists_end_element);
38.292 + XML_SetCharacterDataHandler(ctx.filelists_parser,
38.293 + yum_character_data);
38.294 +
38.295 + primary = gzopen("primary.xml.gz", "rb");
38.296 + if (primary == NULL)
38.297 + return NULL;
38.298 + filelists = gzopen("filelists.xml.gz", "rb");
38.299 + if (filelists == NULL)
38.300 + return NULL;
38.301 +
38.302 + ctx.current_parser = ctx.primary_parser;
38.303 +
38.304 + do {
38.305 + XML_GetParsingStatus(ctx.current_parser, &status);
38.306 + switch (status.parsing) {
38.307 + case XML_SUSPENDED:
38.308 + ret = XML_ResumeParser(ctx.current_parser);
38.309 + break;
38.310 + case XML_PARSING:
38.311 + case XML_INITIALIZED:
38.312 + buf = XML_GetBuffer(ctx.current_parser,
38.313 + XML_BUFFER_SIZE);
38.314 + if (ctx.current_parser == ctx.primary_parser)
38.315 + len = gzread(primary, buf, XML_BUFFER_SIZE);
38.316 + else
38.317 + len = gzread(filelists, buf, XML_BUFFER_SIZE);
38.318 + if (len < 0) {
38.319 + fprintf(stderr,
38.320 + "couldn't read input: %s\n",
38.321 + strerror(errno));
38.322 + return NULL;
38.323 + }
38.324 +
38.325 + XML_ParseBuffer(ctx.current_parser, len, len == 0);
38.326 + break;
38.327 + case XML_FINISHED:
38.328 + break;
38.329 + }
38.330 + } while (status.parsing != XML_FINISHED);
38.331 +
38.332 +
38.333 + XML_ParserFree(ctx.primary_parser);
38.334 + XML_ParserFree(ctx.filelists_parser);
38.335 +
38.336 + gzclose(primary);
38.337 + gzclose(filelists);
38.338 +
38.339 + return razor_importer_finish(ctx.importer);
38.340 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/src/main.c Mon Jun 16 15:40:30 2008 -0400
39.3 @@ -0,0 +1,804 @@
39.4 +/*
39.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
39.6 + * Copyright (C) 2008 Red Hat, Inc
39.7 + *
39.8 + * This program is free software; you can redistribute it and/or modify
39.9 + * it under the terms of the GNU General Public License as published by
39.10 + * the Free Software Foundation; either version 2 of the License, or
39.11 + * (at your option) any later version.
39.12 + *
39.13 + * This program is distributed in the hope that it will be useful,
39.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
39.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39.16 + * GNU General Public License for more details.
39.17 + *
39.18 + * You should have received a copy of the GNU General Public License along
39.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
39.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39.21 + */
39.22 +
39.23 +#include <stdlib.h>
39.24 +#include <stddef.h>
39.25 +#include <stdio.h>
39.26 +#include <stdint.h>
39.27 +#include <string.h>
39.28 +#include <sys/stat.h>
39.29 +#include <unistd.h>
39.30 +#include <fcntl.h>
39.31 +#include <dirent.h>
39.32 +#include <curl/curl.h>
39.33 +#include <fnmatch.h>
39.34 +#include <errno.h>
39.35 +#include "razor.h"
39.36 +
39.37 +static const char system_repo_filename[] = "system.repo";
39.38 +static const char next_repo_filename[] = "system-next.repo";
39.39 +static const char rawhide_repo_filename[] = "rawhide.repo";
39.40 +static const char updated_repo_filename[] = "system-updated.repo";
39.41 +static const char install_root[] = "install";
39.42 +static const char *repo_filename = system_repo_filename;
39.43 +static const char *yum_url;
39.44 +
39.45 +static int
39.46 +command_list(int argc, const char *argv[])
39.47 +{
39.48 + struct razor_set *set;
39.49 + struct razor_package_iterator *pi;
39.50 + struct razor_package *package;
39.51 + const char *pattern, *name, *version, *arch;
39.52 + int only_names = 0, i = 0;
39.53 +
39.54 + if (i < argc && strcmp(argv[i], "--only-names") == 0) {
39.55 + only_names = 1;
39.56 + i++;
39.57 + }
39.58 +
39.59 + pattern = argv[i];
39.60 + set = razor_set_open(repo_filename);
39.61 + pi = razor_package_iterator_create(set);
39.62 + while (razor_package_iterator_next(pi, &package,
39.63 + &name, &version, &arch)) {
39.64 + if (pattern && fnmatch(pattern, name, 0) != 0)
39.65 + continue;
39.66 +
39.67 + if (only_names)
39.68 + printf("%s\n", name);
39.69 + else
39.70 + printf("%s-%s.%s\n", name, version, arch);
39.71 + }
39.72 + razor_package_iterator_destroy(pi);
39.73 + razor_set_destroy(set);
39.74 +
39.75 + return 0;
39.76 +}
39.77 +
39.78 +static int
39.79 +list_properties(const char *package_name,
39.80 + enum razor_property_type required_type)
39.81 +{
39.82 + static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
39.83 + struct razor_set *set;
39.84 + struct razor_property *property;
39.85 + struct razor_package *package;
39.86 + struct razor_property_iterator *pi;
39.87 + const char *name, *version;
39.88 + enum razor_property_type type;
39.89 + enum razor_version_relation relation;
39.90 +
39.91 + set = razor_set_open(repo_filename);
39.92 + if (package_name)
39.93 + package = razor_set_get_package(set, package_name);
39.94 + else
39.95 + package = NULL;
39.96 +
39.97 + pi = razor_property_iterator_create(set, package);
39.98 + while (razor_property_iterator_next(pi, &property,
39.99 + &name, &relation, &version,
39.100 + &type)) {
39.101 + if (type != required_type)
39.102 + continue;
39.103 + if (version[0] == '\0')
39.104 + printf("%s\n", name);
39.105 + else
39.106 + printf("%s %s %s\n", name,
39.107 + relation_string[relation], version);
39.108 + }
39.109 + razor_property_iterator_destroy(pi);
39.110 +
39.111 + razor_set_destroy(set);
39.112 +
39.113 + return 0;
39.114 +}
39.115 +
39.116 +static int
39.117 +command_list_requires(int argc, const char *argv[])
39.118 +{
39.119 + return list_properties(argv[0], RAZOR_PROPERTY_REQUIRES);
39.120 +}
39.121 +
39.122 +static int
39.123 +command_list_provides(int argc, const char *argv[])
39.124 +{
39.125 + return list_properties(argv[0], RAZOR_PROPERTY_PROVIDES);
39.126 +}
39.127 +
39.128 +static int
39.129 +command_list_obsoletes(int argc, const char *argv[])
39.130 +{
39.131 + return list_properties(argv[0], RAZOR_PROPERTY_OBSOLETES);
39.132 +}
39.133 +
39.134 +static int
39.135 +command_list_conflicts(int argc, const char *argv[])
39.136 +{
39.137 + return list_properties(argv[0], RAZOR_PROPERTY_CONFLICTS);
39.138 +}
39.139 +
39.140 +static int
39.141 +command_list_files(int argc, const char *argv[])
39.142 +{
39.143 + struct razor_set *set;
39.144 +
39.145 + set = razor_set_open(repo_filename);
39.146 + if (set == NULL)
39.147 + return 1;
39.148 + razor_set_list_files(set, argv[0]);
39.149 + razor_set_destroy(set);
39.150 +
39.151 + return 0;
39.152 +}
39.153 +
39.154 +static int
39.155 +command_list_file_packages(int argc, const char *argv[])
39.156 +{
39.157 + struct razor_set *set;
39.158 + struct razor_package_iterator *pi;
39.159 + struct razor_package *package;
39.160 + const char *name, *version, *arch;
39.161 +
39.162 + set = razor_set_open(repo_filename);
39.163 + if (set == NULL)
39.164 + return 1;
39.165 +
39.166 + pi = razor_package_iterator_create_for_file(set, argv[0]);
39.167 + while (razor_package_iterator_next(pi, &package,
39.168 + &name, &version, &arch))
39.169 + printf("%s-%s\n", name, version);
39.170 + razor_package_iterator_destroy(pi);
39.171 +
39.172 + razor_set_destroy(set);
39.173 +
39.174 + return 0;
39.175 +}
39.176 +
39.177 +static int
39.178 +command_list_package_files(int argc, const char *argv[])
39.179 +{
39.180 + struct razor_set *set;
39.181 +
39.182 + set = razor_set_open(repo_filename);
39.183 + if (set == NULL)
39.184 + return 1;
39.185 + razor_set_list_package_files(set, argv[0]);
39.186 + razor_set_destroy(set);
39.187 +
39.188 + return 0;
39.189 +}
39.190 +
39.191 +static void
39.192 +list_packages_for_property(struct razor_set *set,
39.193 + struct razor_property *property)
39.194 +{
39.195 + struct razor_package_iterator *pi;
39.196 + struct razor_package *package;
39.197 + const char *name, *version, *arch;
39.198 +
39.199 + pi = razor_package_iterator_create_for_property(set, property);
39.200 + while (razor_package_iterator_next(pi, &package,
39.201 + &name, &version, &arch))
39.202 + printf("%s-%s.%s\n", name, version, arch);
39.203 + razor_package_iterator_destroy(pi);
39.204 +}
39.205 +
39.206 +static int
39.207 +list_property_packages(const char *ref_name,
39.208 + const char *ref_version,
39.209 + enum razor_property_type ref_type)
39.210 +{
39.211 + struct razor_set *set;
39.212 + struct razor_property *property;
39.213 + struct razor_property_iterator *pi;
39.214 + const char *name, *version;
39.215 + enum razor_property_type type;
39.216 + enum razor_version_relation relation;
39.217 +
39.218 + if (ref_name == NULL)
39.219 + return 0;
39.220 +
39.221 + set = razor_set_open(repo_filename);
39.222 + if (set == NULL)
39.223 + return 1;
39.224 +
39.225 + pi = razor_property_iterator_create(set, NULL);
39.226 + while (razor_property_iterator_next(pi, &property,
39.227 + &name, &relation, &version,
39.228 + &type)) {
39.229 + if (strcmp(ref_name, name) != 0)
39.230 + continue;
39.231 + if (ref_version && relation == RAZOR_VERSION_EQUAL &&
39.232 + strcmp(ref_version, version) != 0)
39.233 + continue;
39.234 + if (ref_type != type)
39.235 + continue;
39.236 +
39.237 + list_packages_for_property(set, property);
39.238 + }
39.239 + razor_property_iterator_destroy(pi);
39.240 +
39.241 + return 0;
39.242 +}
39.243 +
39.244 +static int
39.245 +command_what_requires(int argc, const char *argv[])
39.246 +{
39.247 + return list_property_packages(argv[0], argv[1],
39.248 + RAZOR_PROPERTY_REQUIRES);
39.249 +}
39.250 +
39.251 +static int
39.252 +command_what_provides(int argc, const char *argv[])
39.253 +{
39.254 + return list_property_packages(argv[0], argv[1],
39.255 + RAZOR_PROPERTY_PROVIDES);
39.256 +}
39.257 +
39.258 +static int
39.259 +show_progress(void *clientp,
39.260 + double dltotal, double dlnow, double ultotal, double ulnow)
39.261 +{
39.262 + const char *file = clientp;
39.263 +
39.264 + if (!dlnow < dltotal)
39.265 + fprintf(stderr, "\rdownloading %s, %dkB/%dkB",
39.266 + file, (int) dlnow / 1024, (int) dltotal / 1024);
39.267 +
39.268 + return 0;
39.269 +}
39.270 +
39.271 +static int
39.272 +download_if_missing(const char *url, const char *file)
39.273 +{
39.274 + CURL *curl;
39.275 + struct stat buf;
39.276 + char error[256];
39.277 + FILE *fp;
39.278 + CURLcode res;
39.279 + long response;
39.280 +
39.281 + curl = curl_easy_init();
39.282 + if (curl == NULL)
39.283 + return 1;
39.284 +
39.285 + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
39.286 + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
39.287 + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, show_progress);
39.288 + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, file);
39.289 +
39.290 + if (stat(file, &buf) < 0) {
39.291 + fp = fopen(file, "w");
39.292 + if (fp == NULL) {
39.293 + fprintf(stderr,
39.294 + "failed to open %s for writing\n", file);
39.295 + return -1;
39.296 + }
39.297 + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
39.298 + curl_easy_setopt(curl, CURLOPT_URL, url);
39.299 + res = curl_easy_perform(curl);
39.300 + fclose(fp);
39.301 + if (res != CURLE_OK) {
39.302 + fprintf(stderr, "curl error: %s\n", error);
39.303 + unlink(file);
39.304 + return -1;
39.305 + }
39.306 + res = curl_easy_getinfo(curl,
39.307 + CURLINFO_RESPONSE_CODE, &response);
39.308 + if (res != CURLE_OK) {
39.309 + fprintf(stderr, "curl error: %s\n", error);
39.310 + unlink(file);
39.311 + return -1;
39.312 + }
39.313 + if (response != 200) {
39.314 + fprintf(stderr, " - failed %ld\n", response);
39.315 + unlink(file);
39.316 + return -1;
39.317 + }
39.318 + fprintf(stderr, "\n");
39.319 + }
39.320 +
39.321 + curl_easy_cleanup(curl);
39.322 +
39.323 + return 0;
39.324 +}
39.325 +
39.326 +#define YUM_URL "http://download.fedora.redhat.com" \
39.327 + "/pub/fedora/linux/development/i386/os"
39.328 +
39.329 +static int
39.330 +command_import_yum(int argc, const char *argv[])
39.331 +{
39.332 + struct razor_set *set;
39.333 + char buffer[512];
39.334 +
39.335 + printf("downloading from %s.\n", yum_url);
39.336 + snprintf(buffer, sizeof buffer,
39.337 + "%s/repodata/primary.xml.gz", yum_url);
39.338 + if (download_if_missing(buffer, "primary.xml.gz") < 0)
39.339 + return -1;
39.340 + snprintf(buffer, sizeof buffer,
39.341 + "%s/repodata/filelists.xml.gz", yum_url);
39.342 + if (download_if_missing(buffer, "filelists.xml.gz") < 0)
39.343 + return -1;
39.344 +
39.345 + set = razor_set_create_from_yum();
39.346 + if (set == NULL)
39.347 + return 1;
39.348 + razor_set_write(set, rawhide_repo_filename);
39.349 + razor_set_destroy(set);
39.350 + printf("wrote %s\n", rawhide_repo_filename);
39.351 +
39.352 + return 0;
39.353 +}
39.354 +
39.355 +static int
39.356 +command_import_rpmdb(int argc, const char *argv[])
39.357 +{
39.358 + struct razor_set *set;
39.359 +
39.360 + set = razor_set_create_from_rpmdb();
39.361 + if (set == NULL)
39.362 + return 1;
39.363 + razor_set_write(set, repo_filename);
39.364 + razor_set_destroy(set);
39.365 + printf("wrote %s\n", repo_filename);
39.366 +
39.367 + return 0;
39.368 +}
39.369 +
39.370 +static int
39.371 +mark_packages_for_update(struct razor_transaction *trans,
39.372 + struct razor_set *set, const char *pattern)
39.373 +{
39.374 + struct razor_package_iterator *pi;
39.375 + struct razor_package *package;
39.376 + const char *name, *version, *arch;
39.377 + int matches = 0;
39.378 +
39.379 + pi = razor_package_iterator_create(set);
39.380 + while (razor_package_iterator_next(pi, &package,
39.381 + &name, &version, &arch)) {
39.382 + if (pattern && fnmatch(pattern, name, 0) == 0) {
39.383 + razor_transaction_update_package(trans, package);
39.384 + matches++;
39.385 + }
39.386 + }
39.387 + razor_package_iterator_destroy(pi);
39.388 +
39.389 + return matches;
39.390 +}
39.391 +
39.392 +static int
39.393 +mark_packages_for_removal(struct razor_transaction *trans,
39.394 + struct razor_set *set, const char *pattern)
39.395 +{
39.396 + struct razor_package_iterator *pi;
39.397 + struct razor_package *package;
39.398 + const char *name, *version, *arch;
39.399 + int matches = 0;
39.400 +
39.401 + pi = razor_package_iterator_create(set);
39.402 + while (razor_package_iterator_next(pi, &package,
39.403 + &name, &version, &arch)) {
39.404 + if (pattern && fnmatch(pattern, name, 0) == 0) {
39.405 + razor_transaction_remove_package(trans, package);
39.406 + matches++;
39.407 + }
39.408 + }
39.409 + razor_package_iterator_destroy(pi);
39.410 +
39.411 + return matches;
39.412 +}
39.413 +
39.414 +static int
39.415 +command_update(int argc, const char *argv[])
39.416 +{
39.417 + struct razor_set *set, *upstream;
39.418 + struct razor_transaction *trans;
39.419 + int i, errors;
39.420 +
39.421 + set = razor_set_open(repo_filename);
39.422 + upstream = razor_set_open(rawhide_repo_filename);
39.423 + if (set == NULL || upstream == NULL)
39.424 + return 1;
39.425 +
39.426 + trans = razor_transaction_create(set, upstream);
39.427 + if (argc == 0)
39.428 + razor_transaction_update_all(trans);
39.429 + for (i = 0; i < argc; i++) {
39.430 + if (mark_packages_for_update(trans, set, argv[i]) == 0) {
39.431 + fprintf(stderr, "no match for %s\n", argv[i]);
39.432 + return 1;
39.433 + }
39.434 + }
39.435 +
39.436 + errors = razor_transaction_resolve(trans);
39.437 + if (errors)
39.438 + return 1;
39.439 +
39.440 + set = razor_transaction_finish(trans);
39.441 + razor_set_write(set, updated_repo_filename);
39.442 + razor_set_destroy(set);
39.443 + razor_set_destroy(upstream);
39.444 + printf("wrote system-updated.repo\n");
39.445 +
39.446 + return 0;
39.447 +}
39.448 +
39.449 +static int
39.450 +command_remove(int argc, const char *argv[])
39.451 +{
39.452 + struct razor_set *set, *upstream;
39.453 + struct razor_transaction *trans;
39.454 + int i, errors;
39.455 +
39.456 + set = razor_set_open(repo_filename);
39.457 + if (set == NULL)
39.458 + return 1;
39.459 +
39.460 + upstream = razor_set_create();
39.461 + trans = razor_transaction_create(set, upstream);
39.462 + for (i = 0; i < argc; i++) {
39.463 + if (mark_packages_for_removal(trans, set, argv[i]) == 0) {
39.464 + fprintf(stderr, "no match for %s\n", argv[i]);
39.465 + return 1;
39.466 + }
39.467 + }
39.468 +
39.469 + errors = razor_transaction_resolve(trans);
39.470 + if (errors)
39.471 + return 1;
39.472 +
39.473 + set = razor_transaction_finish(trans);
39.474 + razor_set_write(set, updated_repo_filename);
39.475 + razor_set_destroy(set);
39.476 + razor_set_destroy(upstream);
39.477 + printf("wrote system-updated.repo\n");
39.478 +
39.479 + return 0;
39.480 +}
39.481 +
39.482 +static void
39.483 +print_diff(const char *name,
39.484 + const char *old_version, const char *new_version, const char *arch,
39.485 + void *data)
39.486 +{
39.487 + if (old_version)
39.488 + printf("removing %s %s\n", name, old_version);
39.489 + else
39.490 + printf("install %s %s\n", name, new_version);
39.491 +}
39.492 +
39.493 +static int
39.494 +command_diff(int argc, const char *argv[])
39.495 +{
39.496 + struct razor_set *set, *updated;
39.497 +
39.498 + set = razor_set_open(repo_filename);
39.499 + updated = razor_set_open(updated_repo_filename);
39.500 + if (set == NULL || updated == NULL)
39.501 + return 1;
39.502 +
39.503 + razor_set_diff(set, updated, print_diff, NULL);
39.504 +
39.505 + razor_set_destroy(set);
39.506 + razor_set_destroy(updated);
39.507 +
39.508 + return 0;
39.509 +}
39.510 +
39.511 +static int
39.512 +command_import_rpms(int argc, const char *argv[])
39.513 +{
39.514 + DIR *dir;
39.515 + struct dirent *de;
39.516 + struct razor_importer *importer;
39.517 + struct razor_set *set;
39.518 + struct razor_rpm *rpm;
39.519 + int len;
39.520 + char filename[256];
39.521 + const char *dirname = argv[0];
39.522 +
39.523 + if (dirname == NULL) {
39.524 + fprintf(stderr, "usage: razor import-rpms DIR\n");
39.525 + return -1;
39.526 + }
39.527 +
39.528 + dir = opendir(dirname);
39.529 + if (dir == NULL) {
39.530 + fprintf(stderr, "couldn't read dir %s\n", dirname);
39.531 + return -1;
39.532 + }
39.533 +
39.534 + importer = razor_importer_new();
39.535 +
39.536 + while (de = readdir(dir), de != NULL) {
39.537 + len = strlen(de->d_name);
39.538 + if (len < 5 || strcmp(de->d_name + len - 4, ".rpm") != 0)
39.539 + continue;
39.540 + snprintf(filename, sizeof filename,
39.541 + "%s/%s", dirname, de->d_name);
39.542 + rpm = razor_rpm_open(filename);
39.543 + if (rpm == NULL) {
39.544 + fprintf(stderr,
39.545 + "failed to open rpm \"%s\"\n", filename);
39.546 + continue;
39.547 + }
39.548 + if (razor_importer_add_rpm(importer, rpm)) {
39.549 + fprintf(stderr, "couldn't import %s\n", filename);
39.550 + break;
39.551 + }
39.552 + razor_rpm_close(rpm);
39.553 + }
39.554 +
39.555 + if (de != NULL) {
39.556 + razor_importer_destroy(importer);
39.557 + return -1;
39.558 + }
39.559 +
39.560 + set = razor_importer_finish(importer);
39.561 +
39.562 + razor_set_write(set, repo_filename);
39.563 + razor_set_destroy(set);
39.564 + printf("wrote %s\n", repo_filename);
39.565 +
39.566 + return 0;
39.567 +}
39.568 +
39.569 +static void
39.570 +download_package(const char *name,
39.571 + const char *old_version,
39.572 + const char *new_version,
39.573 + const char *arch,
39.574 + void *data)
39.575 +{
39.576 + char file[PATH_MAX], url[256];
39.577 + const char *v;
39.578 + int *errors = data;
39.579 +
39.580 + if (old_version)
39.581 + return;
39.582 +
39.583 + /* Skip epoch */
39.584 + v = strchr(new_version, ':');
39.585 + if (v != NULL)
39.586 + v = v + 1;
39.587 + else
39.588 + v = new_version;
39.589 +
39.590 + snprintf(url, sizeof url,
39.591 + "%s/Packages/%s-%s.%s.rpm", yum_url, name, v, arch);
39.592 + snprintf(file, sizeof file,
39.593 + "rpms/%s-%s.%s.rpm", name, v, arch);
39.594 + if (download_if_missing(url, file) < 0)
39.595 + (*errors)++;
39.596 +}
39.597 +
39.598 +static void
39.599 +install_package(const char *name,
39.600 + const char *old_version,
39.601 + const char *new_version,
39.602 + const char *arch,
39.603 + void *data)
39.604 +{
39.605 + const char *v, *root = data;
39.606 + char file[PATH_MAX];
39.607 + struct razor_rpm *rpm;
39.608 +
39.609 + if (old_version) {
39.610 + printf("removing %s %s not handled\n", name, old_version);
39.611 + return;
39.612 + }
39.613 +
39.614 + /* Skip epoch */
39.615 + v = strchr(new_version, ':');
39.616 + if (v != NULL)
39.617 + v = v + 1;
39.618 + else
39.619 + v = new_version;
39.620 +
39.621 + printf("install %s %s\n", name, v);
39.622 + snprintf(file, sizeof file, "rpms/%s-%s.%s.rpm", name, v, arch);
39.623 +
39.624 + rpm = razor_rpm_open(file);
39.625 + if (rpm == NULL) {
39.626 + fprintf(stderr, "failed to open rpm %s\n", file);
39.627 + return;
39.628 + }
39.629 + if (razor_rpm_install(rpm, root) < 0) {
39.630 + fprintf(stderr,
39.631 + "failed to install rpm %s\n", file);
39.632 + return;
39.633 + }
39.634 + razor_rpm_close(rpm);
39.635 +}
39.636 +
39.637 +static int
39.638 +command_install(int argc, const char *argv[])
39.639 +{
39.640 + struct razor_root *root;
39.641 + struct razor_set *upstream, *next;
39.642 + struct razor_transaction *trans;
39.643 + int i = 0, errors, dependencies = 1;
39.644 +
39.645 + if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
39.646 + dependencies = 0;
39.647 + i++;
39.648 + }
39.649 +
39.650 + root = razor_root_open(install_root, RAZOR_ROOT_OPEN_WRITE);
39.651 + upstream = razor_set_open(rawhide_repo_filename);
39.652 + trans = razor_root_create_transaction(root, upstream);
39.653 +
39.654 + for (; i < argc; i++) {
39.655 + if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
39.656 + fprintf(stderr, "no package matched %s\n", argv[i]);
39.657 + razor_root_close(root);
39.658 + return 1;
39.659 + }
39.660 + }
39.661 +
39.662 + if (dependencies) {
39.663 + errors = razor_transaction_resolve(trans);
39.664 + if (errors) {
39.665 + razor_root_close(root);
39.666 + return 1;
39.667 + }
39.668 + }
39.669 +
39.670 + next = razor_transaction_finish(trans);
39.671 +
39.672 + razor_root_update(root, next);
39.673 +
39.674 + if (mkdir("rpms", 0777) && errno != EEXIST) {
39.675 + fprintf(stderr, "failed to create rpms directory.\n");
39.676 + razor_root_close(root);
39.677 + return 1;
39.678 + }
39.679 +
39.680 + razor_root_diff(root, download_package, &errors);
39.681 + if (errors > 0) {
39.682 + fprintf(stderr, "failed to download %d packages\n", errors);
39.683 + razor_root_close(root);
39.684 + return 1;
39.685 + }
39.686 +
39.687 + /* FIXME: We need to figure out the right install order here,
39.688 + * so the post and pre scripts can run. */
39.689 + razor_root_diff(root, install_package, (void *) root);
39.690 +
39.691 + razor_set_destroy(next);
39.692 + razor_set_destroy(upstream);
39.693 +
39.694 + return razor_root_commit(root);
39.695 +}
39.696 +
39.697 +static int
39.698 +command_init(int argc, const char *argv[])
39.699 +{
39.700 + return razor_root_create(install_root);
39.701 +}
39.702 +
39.703 +static int
39.704 +command_download(int argc, const char *argv[])
39.705 +{
39.706 + struct razor_set *set;
39.707 + struct razor_package_iterator *pi;
39.708 + struct razor_package *package;
39.709 + const char *pattern = argv[0], *name, *version, *arch;
39.710 + char url[256], file[256];
39.711 + int matches = 0;
39.712 +
39.713 + if (mkdir("rpms", 0777) && errno != EEXIST) {
39.714 + fprintf(stderr, "failed to create rpms directory.\n");
39.715 + return 1;
39.716 + }
39.717 +
39.718 + set = razor_set_open(rawhide_repo_filename);
39.719 + pi = razor_package_iterator_create(set);
39.720 + while (razor_package_iterator_next(pi, &package,
39.721 + &name, &version, &arch)) {
39.722 + if (pattern && fnmatch(pattern, name, 0) != 0)
39.723 + continue;
39.724 +
39.725 + matches++;
39.726 + snprintf(url, sizeof url,
39.727 + "%s/Packages/%s-%s.%s.rpm",
39.728 + yum_url, name, version, arch);
39.729 + snprintf(file, sizeof file,
39.730 + "rpms/%s-%s.%s.rpm", name, version, arch);
39.731 + download_if_missing(url, file);
39.732 + }
39.733 + razor_package_iterator_destroy(pi);
39.734 + razor_set_destroy(set);
39.735 +
39.736 + if (matches == 0)
39.737 + fprintf(stderr, "no packages matched \"%s\"\n", pattern);
39.738 + else if (matches == 1)
39.739 + fprintf(stderr, "downloaded 1 package\n");
39.740 + else
39.741 + fprintf(stderr, "downloaded %d packages\n", matches);
39.742 +
39.743 + return 0;
39.744 +}
39.745 +
39.746 +static struct {
39.747 + const char *name;
39.748 + const char *description;
39.749 + int (*func)(int argc, const char *argv[]);
39.750 +} razor_commands[] = {
39.751 + { "list", "list all packages", command_list },
39.752 + { "list-requires", "list all requires for the given package", command_list_requires },
39.753 + { "list-provides", "list all provides for the given package", command_list_provides },
39.754 + { "list-obsoletes", "list all obsoletes for the given package", command_list_obsoletes },
39.755 + { "list-conflicts", "list all conflicts for the given package", command_list_conflicts },
39.756 + { "list-files", "list files for package set", command_list_files },
39.757 + { "list-file-packages", "list packages owning file", command_list_file_packages },
39.758 + { "list-package-files", "list files in package", command_list_package_files },
39.759 + { "what-requires", "list the packages that have the given requires", command_what_requires },
39.760 + { "what-provides", "list the packages that have the given provides", command_what_provides },
39.761 + { "import-yum", "import yum metadata files", command_import_yum },
39.762 + { "import-rpmdb", "import the system rpm database", command_import_rpmdb },
39.763 + { "import-rpms", "import rpms from the given directory", command_import_rpms },
39.764 + { "update", "update all or specified packages", command_update },
39.765 + { "remove", "remove specified packages", command_remove },
39.766 + { "diff", "show diff between two package sets", command_diff },
39.767 + { "install", "install rpm", command_install },
39.768 + { "init", "init razor root", command_init },
39.769 + { "download", "download packages", command_download }
39.770 +};
39.771 +
39.772 +static int
39.773 +usage(void)
39.774 +{
39.775 + int i;
39.776 +
39.777 + printf("usage:\n");
39.778 + for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
39.779 + printf(" %-20s%s\n",
39.780 + razor_commands[i].name, razor_commands[i].description);
39.781 +
39.782 + return 1;
39.783 +}
39.784 +
39.785 +int
39.786 +main(int argc, const char *argv[])
39.787 +{
39.788 + char *repo;
39.789 + int i;
39.790 +
39.791 + repo = getenv("RAZOR_REPO");
39.792 + if (repo != NULL)
39.793 + repo_filename = repo;
39.794 +
39.795 + yum_url = getenv("YUM_URL");
39.796 + if (yum_url == NULL)
39.797 + yum_url = YUM_URL;
39.798 +
39.799 + if (argc < 2)
39.800 + return usage();
39.801 +
39.802 + for (i = 0; i < ARRAY_SIZE(razor_commands); i++)
39.803 + if (strcmp(razor_commands[i].name, argv[1]) == 0)
39.804 + return razor_commands[i].func(argc - 2, argv + 2);
39.805 +
39.806 + return usage();
39.807 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/src/rpm.c Mon Jun 16 15:40:30 2008 -0400
40.3 @@ -0,0 +1,897 @@
40.4 +/*
40.5 + * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
40.6 + * Copyright (C) 2008 Red Hat, Inc
40.7 + *
40.8 + * This program is free software; you can redistribute it and/or modify
40.9 + * it under the terms of the GNU General Public License as published by
40.10 + * the Free Software Foundation; either version 2 of the License, or
40.11 + * (at your option) any later version.
40.12 + *
40.13 + * This program is distributed in the hope that it will be useful,
40.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
40.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40.16 + * GNU General Public License for more details.
40.17 + *
40.18 + * You should have received a copy of the GNU General Public License along
40.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
40.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40.21 + */
40.22 +
40.23 +#include <stdlib.h>
40.24 +#include <string.h>
40.25 +#include <stdio.h>
40.26 +#include <dirent.h>
40.27 +#include "razor.h"
40.28 +
40.29 +enum option_type {
40.30 + OPTION_LAST,
40.31 + OPTION_GROUP,
40.32 + OPTION_BOOL,
40.33 + OPTION_STRING
40.34 +};
40.35 +
40.36 +struct option {
40.37 + enum option_type type;
40.38 + const char *name;
40.39 + char short_name;
40.40 + const char *arg_name;
40.41 + const char *description;
40.42 + void *data;
40.43 +};
40.44 +
40.45 +/* A note about all these options: rpm allows options to mean
40.46 + * different things depending on what other options are present on the
40.47 + * command line. For example, if -q or --query is present, -i no
40.48 + * longer means install, but info. The way we handle this is by
40.49 + * setting all the options that may match (ie if -i is given we set
40.50 + * install and info), and then look at the relevent one depending on
40.51 + * what else in on the command line. */
40.52 +
40.53 +static int option_all, option_whatrequires, option_whatprovides;
40.54 +static int option_package;
40.55 +
40.56 +static const struct option query_options[] = {
40.57 + { OPTION_BOOL, "configfiles", 'c', NULL, "list all configuration files", NULL },
40.58 + { OPTION_BOOL, "docfiles", 'd', NULL, "list all documentation files", NULL },
40.59 + { OPTION_BOOL, "dump", 0, NULL, "dump basic file information", NULL },
40.60 + { OPTION_BOOL, "list", 0, NULL, "list files in package", NULL },
40.61 + { OPTION_STRING, "queryformat", 0, "QUERYFORMAT", "use the following query format", NULL },
40.62 + { OPTION_BOOL, "state", 's', NULL, "display the states of the listed files", NULL },
40.63 + { OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
40.64 + { OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
40.65 + { OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
40.66 + { OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
40.67 + { OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
40.68 + { OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
40.69 + { OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
40.70 + { OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
40.71 + { OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL, },
40.72 + { OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
40.73 + { OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
40.74 + { OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
40.75 + { OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
40.76 + { }
40.77 +};
40.78 +
40.79 +static int option_nodeps;
40.80 +
40.81 +static const struct option verify_options[] = {
40.82 + { OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL },
40.83 + { OPTION_BOOL, "nofiles", 0, NULL, "don't verify files in package", NULL },
40.84 + { OPTION_BOOL, "nodeps", 0, NULL, "don't verify package dependencies", &option_nodeps },
40.85 + { OPTION_BOOL, "noscript", 0, NULL, "don't execute verify script(s)", NULL, },
40.86 + { OPTION_BOOL, "all", 'a', NULL, "query/verify all packages", &option_all },
40.87 + { OPTION_BOOL, "file", 'f', NULL, "query/verify package(s) owning file", NULL },
40.88 + { OPTION_BOOL, "group", 'g', NULL, "query/verify package(s) in group", NULL },
40.89 + { OPTION_BOOL, "package", 'p', NULL, "query/verify a package file", &option_package },
40.90 + { OPTION_BOOL, "ftswalk", 'W', NULL, "query/verify package(s) from TOP file tree walk", NULL },
40.91 + { OPTION_BOOL, "pkgid", 0, NULL, "query/verify package(s) with package identifier", NULL },
40.92 + { OPTION_BOOL, "hdrid", 0, NULL, "query/verify package(s) with header identifier", NULL },
40.93 + { OPTION_BOOL, "fileid", 0, NULL, "query/verify package(s) with file identifier", NULL },
40.94 + { OPTION_BOOL, "specfile", 0, NULL, "query a spec file", NULL },
40.95 + { OPTION_BOOL, "triggeredby", 0, NULL, "query the package(s) triggered by the package", NULL },
40.96 + { OPTION_BOOL, "whatrequires", 0, NULL, "query/verify the package(s) which require a dependency", &option_whatrequires },
40.97 + { OPTION_BOOL, "whatprovides", 0, NULL, "query/verify the package(s) which provide a dependency", &option_whatprovides },
40.98 + { OPTION_BOOL, "nomanifest", 0, NULL, "do not process non-package files as manifests", NULL },
40.99 + { }
40.100 +};
40.101 +
40.102 +static const struct option ftw_options[] = {
40.103 + { OPTION_BOOL, "comfollow", 0, NULL, "FTS_COMFOLLOW: follow command line symlinks", NULL },
40.104 + { OPTION_BOOL, "logical", 0, NULL, "FTS_LOGICAL: logical walk", NULL },
40.105 + { OPTION_BOOL, "nochdir", 0, NULL, "FTS_NOCHDIR: don't change directories", NULL },
40.106 + { OPTION_BOOL, "nostat", 0, NULL, "FTS_NOSTAT: don't get stat info", NULL },
40.107 + { OPTION_BOOL, "physical", 0, NULL, "FTS_PHYSICAL: physical walk", NULL },
40.108 + { OPTION_BOOL, "seedot", 0, NULL, "FTS_SEEDOT: return dot and dot-dot", NULL },
40.109 + { OPTION_BOOL, "xdev", 0, NULL, "FTS_XDEV: don't cross devices", NULL },
40.110 + { OPTION_BOOL, "whiteout", 0, NULL, "FTS_WHITEOUT: return whiteout information", NULL },
40.111 + { }
40.112 +};
40.113 +
40.114 +static const struct option signature_options[] = {
40.115 + { OPTION_BOOL, "addsign", 0, NULL, "sign package(s) (identical to --resign)", NULL, },
40.116 + { OPTION_BOOL, "checksig", 'K', NULL, "verify package signature(s)", NULL, },
40.117 + { OPTION_BOOL, "delsign", 0, NULL, "delete package signatures", NULL, },
40.118 + { OPTION_BOOL, "import", 0, NULL, "import an armored public key", NULL, },
40.119 + { OPTION_BOOL, "resign", 0, NULL, "sign package(s) (identical to --addsign)", NULL, },
40.120 + { OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
40.121 + { OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL },
40.122 + { }
40.123 +};
40.124 +
40.125 +static int option_initdb;
40.126 +
40.127 +static const struct option database_options[] = {
40.128 + { OPTION_BOOL, "initdb", 0, NULL, "initialize database", &option_initdb },
40.129 + { OPTION_BOOL, "rebuilddb", 0, NULL, "rebuild database inverted lists from installed package headers", NULL },
40.130 + { }
40.131 +};
40.132 +
40.133 +static int option_erase, option_install, option_upgrade, option_justdb;
40.134 +static int option_test;
40.135 +
40.136 +static const struct option install_options[] = {
40.137 + { OPTION_BOOL, "aid", 0, NULL, "add suggested packages to transaction", NULL, },
40.138 + { OPTION_BOOL, "allfiles", 0, NULL, "install all files, even configurations which might otherwise be skipped", NULL, },
40.139 + { OPTION_BOOL, "allmatches", 0, NULL, "remove all packages which match <package> (normally an error is generated if <package> specified multiple packages)", NULL, },
40.140 + { OPTION_BOOL, "badreloc", 0, NULL, "relocate files in non-relocatable package", NULL },
40.141 + { OPTION_BOOL, "erase", 'e', "<package>", "erase (uninstall) package", &option_erase },
40.142 + { OPTION_BOOL, "excludedocs", 0, NULL, "do not install documentation", NULL, },
40.143 + { OPTION_BOOL, "excludepath", 0, "<path>", "skip files with leading component <path> ", NULL, },
40.144 + { OPTION_BOOL, "fileconflicts", 0, NULL, "detect file conflicts between packages", NULL, },
40.145 + { OPTION_BOOL, "force", 0, NULL, "short hand for --replacepkgs --replacefiles", NULL },
40.146 + { OPTION_BOOL, "freshen", 'F', "<packagefile>+", "upgrade package(s) if already installed", NULL },
40.147 + { OPTION_BOOL, "hash", 'h', NULL, "print hash marks as package installs (good with -v)", NULL },
40.148 + { OPTION_BOOL, "ignorearch", 0, NULL, "don't verify package architecture", NULL, },
40.149 + { OPTION_BOOL, "ignoreos", 0, NULL, "don't verify package operating system", NULL, },
40.150 + { OPTION_BOOL, "ignoresize", 0, NULL, "don't check disk space before installing", NULL },
40.151 + { OPTION_BOOL, "install", 'i', NULL, "install package(s)", &option_install },
40.152 + { OPTION_BOOL, "justdb", 0, NULL, "update the database, but do not modify the filesystem", &option_justdb, },
40.153 + { OPTION_BOOL, "nodeps", 0, NULL, "do not verify package dependencies", &option_nodeps, },
40.154 + { OPTION_BOOL, "nomd5", 0, NULL, "don't verify MD5 digest of files", NULL, },
40.155 + { OPTION_BOOL, "nocontexts", 0, NULL, "don't install file security contexts", NULL, },
40.156 + { OPTION_BOOL, "noorder", 0, NULL, "do not reorder package installation to satisfy dependencies", NULL, },
40.157 + { OPTION_BOOL, "nosuggest", 0, NULL, "do not suggest missing dependency resolution(s)", NULL, },
40.158 + { OPTION_BOOL, "noscripts", 0, NULL, "do not execute package scriptlet(s)", NULL, },
40.159 + { OPTION_BOOL, "notriggers", 0, NULL, "do not execute any scriptlet(s) triggered by this package", NULL, },
40.160 + { OPTION_BOOL, "oldpackage", 0, NULL, "upgrade to an old version of the package (--force on upgrades does this automatically)", NULL },
40.161 + { OPTION_BOOL, "percent", 0, NULL, "print percentages as package installs", NULL, },
40.162 + { OPTION_STRING, "prefix", 0, "<dir>", "relocate the package to <dir>, if relocatable", NULL, },
40.163 + { OPTION_STRING, "relocate", 0, "<old>=<new>", "relocate files from path <old> to <new>", NULL, },
40.164 + { OPTION_BOOL, "repackage", 0, NULL, "save erased package files by repackaging", NULL, },
40.165 + { OPTION_BOOL, "replacefiles", 0, NULL, "ignore file conflicts between packages", NULL, },
40.166 + { OPTION_BOOL, "replacepkgs", 0, NULL, "reinstall if the package is already present", NULL, },
40.167 + { OPTION_BOOL, "test", 0, NULL, "don't install, but tell if it would work or not", &option_test },
40.168 + { OPTION_BOOL, "upgrade", 'U', "<packagefile>+", "upgrade package(s)", &option_upgrade },
40.169 + { }
40.170 +};
40.171 +
40.172 +static int option_version;
40.173 +static const char *option_root = "install";
40.174 +
40.175 +static const struct option common_options[] = {
40.176 + { OPTION_STRING, "define", 'D', "MACRO EXPR", "define MACRO with value EXPR", NULL, },
40.177 + { OPTION_STRING, "eval", 'E', "EXPR", "print macro expansion of EXPR", NULL },
40.178 + { OPTION_STRING, "macros", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
40.179 + { OPTION_BOOL, "nodigest", 0, NULL, "don't verify package digest(s)", NULL, },
40.180 + { OPTION_BOOL, "nosignature", 0, NULL, "don't verify package signature(s)", NULL, },
40.181 + { OPTION_STRING, "rcfile", 0, "<FILE:...>", "read <FILE:...> instead of default file(s)", NULL },
40.182 + { OPTION_STRING, "root", 'r', "ROOT", "use ROOT as top level directory (default: \"/\")", &option_root },
40.183 + { OPTION_BOOL, "querytags", 0, NULL, "display known query tags", NULL, },
40.184 + { OPTION_BOOL, "showrc", 0, NULL, "display final rpmrc and macro configuration", NULL, },
40.185 + { OPTION_BOOL, "quiet", 0, NULL, "provide less detailed output", NULL },
40.186 + { OPTION_BOOL, "verbose", 'v', NULL, "provide more detailed output", NULL },
40.187 + { OPTION_BOOL, "version", 0, NULL, "print the version of rpm being used", &option_version },
40.188 + { }
40.189 +};
40.190 +
40.191 +static int option_conflicts, option_obsoletes, option_requires;
40.192 +static int option_provides, option_info, option_changelog;
40.193 +
40.194 +static const struct option alias_options[] = {
40.195 + { OPTION_BOOL, "scripts", 0, NULL, "list install/erase scriptlets from package(s)", NULL, },
40.196 + { OPTION_BOOL, "setperms", 0, NULL, "set permissions of files in a package", NULL, },
40.197 + { OPTION_BOOL, "setugids", 0, NULL, "set user/group ownership of files in a package", NULL, },
40.198 + { OPTION_BOOL, "conflicts", 0, NULL, "list capabilities this package conflicts with", &option_conflicts, },
40.199 + { OPTION_BOOL, "obsoletes", 0, NULL, "list other packages removed by installing this package", &option_obsoletes, },
40.200 + { OPTION_BOOL, "provides", 0, NULL, "list capabilities that this package provides", &option_provides, },
40.201 + { OPTION_BOOL, "requires", 0, NULL, "list capabilities required by package(s)", &option_requires, },
40.202 + { OPTION_BOOL, "info", 'i', NULL, "list descriptive information from package(s)", &option_info, },
40.203 + { OPTION_BOOL, "changelog", 0, NULL, "list change logs for this package", &option_changelog, },
40.204 + { OPTION_BOOL, "xml", 0, NULL, "list metadata in xml", NULL, },
40.205 + { OPTION_BOOL, "triggers", 0, NULL, "list trigger scriptlets from package(s)", NULL, },
40.206 + { OPTION_BOOL, "last", 0, NULL, "list package(s) by install time, most recent first", NULL, },
40.207 + { OPTION_BOOL, "dupes", 0, NULL, "list duplicated packages", NULL, },
40.208 + { OPTION_BOOL, "filesbypkg", 0, NULL, "list all files from each package", NULL, },
40.209 + { OPTION_BOOL, "fileclass", 0, NULL, "list file names with classes", NULL, },
40.210 + { OPTION_BOOL, "filecolor", 0, NULL, "list file names with colors", NULL, },
40.211 + { OPTION_BOOL, "filecontext", 0, NULL, "list file names with security context from header", NULL, },
40.212 + { OPTION_BOOL, "fscontext", 0, NULL, "list file names with security context from file system", NULL, },
40.213 + { OPTION_BOOL, "recontext", 0, NULL, "list file names with security context from policy RE", NULL, },
40.214 + { OPTION_BOOL, "fileprovide", 0, NULL, "list file names with provides", NULL, },
40.215 + { OPTION_BOOL, "filerequire", 0, NULL, "list file names with requires", NULL, },
40.216 + { OPTION_BOOL, "redhatprovides", 0, NULL, "find package name that contains a provided capability (needs rpmdb-redhat package installed)", NULL, },
40.217 + { OPTION_BOOL, "redhatrequires", 0, NULL, "find package name that contains a required capability (needs rpmdb-redhat package installed)", NULL, },
40.218 + { OPTION_STRING, "buildpolicy", 0, "<policy>", "set buildroot <policy> (e.g. compress man pages)", NULL, },
40.219 + { OPTION_BOOL, "with", 0, "<option>", "enable configure <option> for build", NULL, },
40.220 + { OPTION_BOOL, "without", 0, "<option>", "disable configure <option> for build", NULL },
40.221 + { }
40.222 +};
40.223 +
40.224 +static int option_help, option_usage;
40.225 +
40.226 +static const struct option help_options[] = {
40.227 + { OPTION_BOOL, "help", '?', NULL, "Show this help message", &option_help },
40.228 + { OPTION_BOOL, "usage", 0, NULL, "Display brief usage message", &option_usage},
40.229 + { }
40.230 +};
40.231 +
40.232 +static int option_query, option_verify;
40.233 +
40.234 +static const struct option rpm_options[] = {
40.235 + { OPTION_BOOL, "query", 'q', NULL, "Query rpm database", &option_query },
40.236 + { OPTION_BOOL, "verify", 'V', NULL, "Verify rpm database", &option_verify },
40.237 + { OPTION_GROUP, NULL, 0, NULL, "Query options (with -q or --query):", &query_options },
40.238 + { OPTION_GROUP, NULL, 0, NULL, "Verify options (with -V or --verify):", &verify_options },
40.239 + { OPTION_GROUP, NULL, 0, NULL, "File tree walk options (with --ftswalk):", &ftw_options },
40.240 + { OPTION_GROUP, NULL, 0, NULL, "Signature options:", &signature_options },
40.241 + { OPTION_GROUP, NULL, 0, NULL, "Database options:", &database_options },
40.242 + { OPTION_GROUP, NULL, 0, NULL, "Install/Upgrade/Erase options:", &install_options },
40.243 + { OPTION_GROUP, NULL, 0, NULL, "Common options for all rpm modes and executables:", &common_options },
40.244 + { OPTION_GROUP, NULL, 0, NULL, "Options implemented via popt alias/exec:", &alias_options },
40.245 + { OPTION_GROUP, NULL, 0, NULL, "Help options", &help_options },
40.246 + { }
40.247 +};
40.248 +
40.249 +static const char system_repo_filename[] = "system.repo";
40.250 +static const char *repo_filename = system_repo_filename;
40.251 +
40.252 +static void
40.253 +command_initdb(int argc, const char *argv[])
40.254 +{
40.255 + razor_root_create(option_root);
40.256 +}
40.257 +
40.258 +static struct razor_property *
40.259 +add_property_packages(struct razor_set *set,
40.260 + struct razor_package_query *query,
40.261 + const char *ref_name,
40.262 + const char *ref_version,
40.263 + enum razor_property_type ref_type)
40.264 +{
40.265 + struct razor_property *property;
40.266 + struct razor_property_iterator *pi;
40.267 + struct razor_package_iterator *pkgi;
40.268 + const char *name, *version;
40.269 + enum razor_property_type type;
40.270 + enum razor_version_relation relation;
40.271 +
40.272 + pi = razor_property_iterator_create(set, NULL);
40.273 + while (razor_property_iterator_next(pi, &property, &name,
40.274 + &relation, &version, &type)) {
40.275 + if (strcmp(ref_name, name) != 0)
40.276 + continue;
40.277 + if (ref_version && relation == RAZOR_VERSION_EQUAL &&
40.278 + strcmp(ref_version, version) != 0)
40.279 + continue;
40.280 + if (ref_type != type)
40.281 + continue;
40.282 +
40.283 + pkgi = razor_package_iterator_create_for_property(set,
40.284 + property);
40.285 + razor_package_query_add_iterator(query, pkgi);
40.286 + razor_package_iterator_destroy(pkgi);
40.287 + }
40.288 + razor_property_iterator_destroy(pi);
40.289 +
40.290 + return property;
40.291 +}
40.292 +
40.293 +static int
40.294 +strcmpp(const void *p1, const void *p2)
40.295 +{
40.296 + return strcmp(*(char * const *) p1, *(char * const *) p2);
40.297 +}
40.298 +
40.299 +static void
40.300 +add_command_line_packages(struct razor_set *set,
40.301 + struct razor_package_query *query,
40.302 + int argc, const char **argv)
40.303 +{
40.304 + struct razor_package *package;
40.305 + struct razor_package_iterator *pi;
40.306 + const char *name, *version, *arch;
40.307 + int i, cmp, errors;
40.308 +
40.309 + qsort(argv, argc, sizeof(*argv), strcmpp);
40.310 + i = 0;
40.311 + errors = 0;
40.312 +
40.313 + pi = razor_package_iterator_create(set);
40.314 +
40.315 + while (razor_package_iterator_next(pi, &package,
40.316 + &name, &version, &arch)) {
40.317 + while (cmp = strcmp(argv[i], name), cmp < 0 && i < argc) {
40.318 + fprintf(stderr, "error: package %s is not installed\n",
40.319 + argv[i]);
40.320 + errors++;
40.321 + i++;
40.322 + }
40.323 +
40.324 + if (cmp == 0) {
40.325 + razor_package_query_add_package(query, package);
40.326 + i++;
40.327 + }
40.328 + }
40.329 +
40.330 + razor_package_iterator_destroy(pi);
40.331 +
40.332 + if (errors)
40.333 + exit(1);
40.334 +}
40.335 +
40.336 +static struct razor_package_iterator *
40.337 +get_query_packages(struct razor_set *set, int argc, const char *argv[])
40.338 +{
40.339 + struct razor_package_query *query;
40.340 + struct razor_package_iterator *pi;
40.341 + int i;
40.342 +
40.343 + if (option_all + option_whatprovides + option_whatrequires > 1) {
40.344 + printf("only one type of query/verify "
40.345 + "may be performed at a time\n");
40.346 + exit(1);
40.347 + }
40.348 +
40.349 + query = razor_package_query_create(set);
40.350 +
40.351 + if (option_all) {
40.352 + pi = razor_package_iterator_create(set);
40.353 + razor_package_query_add_iterator(query, pi);
40.354 + razor_package_iterator_destroy(pi);
40.355 + } else if (option_whatrequires) {
40.356 + for (i = 0; i < argc; i++)
40.357 + add_property_packages(set, query,
40.358 + argv[i], NULL,
40.359 + RAZOR_PROPERTY_REQUIRES);
40.360 + } else if (option_whatprovides) {
40.361 + for (i = 0; i < argc; i++)
40.362 + add_property_packages(set, query,
40.363 + argv[i], NULL,
40.364 + RAZOR_PROPERTY_PROVIDES);
40.365 + } else if (argc > 0) {
40.366 + add_command_line_packages(set, query, argc, argv);
40.367 + } else {
40.368 + printf("no arguments given for query/verify\n");
40.369 + exit(1);
40.370 + }
40.371 +
40.372 + return razor_package_query_finish(query);
40.373 +}
40.374 +
40.375 +static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
40.376 +
40.377 +static void
40.378 +print_package_properties(struct razor_set *set,
40.379 + struct razor_package *package,
40.380 + enum razor_property_type ref_type)
40.381 +{
40.382 + struct razor_property *property;
40.383 + struct razor_property_iterator *pi;
40.384 + const char *name, *version;
40.385 + enum razor_property_type type;
40.386 + enum razor_version_relation relation;
40.387 +
40.388 + pi = razor_property_iterator_create(set, package);
40.389 + while (razor_property_iterator_next(pi, &property,
40.390 + &name, &relation, &version,
40.391 + &type)) {
40.392 + if (type != ref_type)
40.393 + continue;
40.394 + if (version[0] == '\0')
40.395 + printf("%s\n", name);
40.396 + else
40.397 + printf("%s %s %s\n", name,
40.398 + relation_string[relation], version);
40.399 + }
40.400 + razor_property_iterator_destroy(pi);
40.401 +}
40.402 +
40.403 +static void
40.404 +print_package_info(struct razor_set *set, struct razor_package *package)
40.405 +{
40.406 + printf("FIXME: Package info not tracked.\n");
40.407 +}
40.408 +
40.409 +static void
40.410 +print_package_changelog(struct razor_set *set, struct razor_package *package)
40.411 +{
40.412 + printf("FIXME: Package changelog not tracked.\n");
40.413 +}
40.414 +
40.415 +static struct razor_set *
40.416 +create_set_from_command_line(int argc, const char *argv[])
40.417 +{
40.418 + struct razor_importer *importer;
40.419 + struct razor_rpm *rpm;
40.420 + int i;
40.421 +
40.422 + importer = razor_importer_new();
40.423 +
40.424 + for (i = 0; i < argc; i++) {
40.425 + rpm = razor_rpm_open(argv[i]);
40.426 + if (rpm == NULL)
40.427 + continue;
40.428 + if (razor_importer_add_rpm(importer, rpm))
40.429 + printf("couldn't import %s\n", argv[i]);
40.430 +
40.431 + razor_rpm_close(rpm);
40.432 + }
40.433 +
40.434 + return razor_importer_finish(importer);
40.435 +}
40.436 +
40.437 +static void
40.438 +command_query(int argc, const char *argv[])
40.439 +{
40.440 + struct razor_set *set;
40.441 + struct razor_package_iterator *pi;
40.442 + struct razor_package *package;
40.443 + const char *name, *version, *arch;
40.444 +
40.445 + if (option_package) {
40.446 + set = create_set_from_command_line(argc, argv);
40.447 + argc = 0;
40.448 + option_all = 1;
40.449 + } else {
40.450 + set = razor_root_open_read_only(option_root);
40.451 + }
40.452 +
40.453 + pi = get_query_packages(set, argc, argv);
40.454 +
40.455 + while (razor_package_iterator_next(pi, &package,
40.456 + &name, &version, &arch)) {
40.457 + if (option_conflicts)
40.458 + print_package_properties(set, package,
40.459 + RAZOR_PROPERTY_CONFLICTS);
40.460 + if (option_obsoletes)
40.461 + print_package_properties(set, package,
40.462 + RAZOR_PROPERTY_OBSOLETES);
40.463 + if (option_requires)
40.464 + print_package_properties(set, package,
40.465 + RAZOR_PROPERTY_REQUIRES);
40.466 + if (option_provides)
40.467 + print_package_properties(set, package,
40.468 + RAZOR_PROPERTY_PROVIDES);
40.469 + if (option_info)
40.470 + print_package_info(set, package);
40.471 + if (option_changelog)
40.472 + print_package_changelog(set, package);
40.473 +
40.474 + if (option_conflicts + option_obsoletes +
40.475 + option_requires + option_provides +
40.476 + option_info + option_changelog == 0)
40.477 + printf("%s-%s.%s\n", name, version, arch);
40.478 + }
40.479 +
40.480 + razor_package_iterator_destroy(pi);
40.481 +
40.482 + razor_set_destroy(set);
40.483 +
40.484 + return;
40.485 +}
40.486 +
40.487 +static void
40.488 +command_verify(int argc, const char *argv[])
40.489 +{
40.490 + struct razor_set *set;
40.491 + struct razor_package_iterator *pi;
40.492 + struct razor_package *package;
40.493 + const char *name, *version, *arch;
40.494 +
40.495 + if (option_package) {
40.496 + set = create_set_from_command_line(argc, argv);
40.497 + argc = 0;
40.498 + option_all = 1;
40.499 + } else {
40.500 + set = razor_root_open_read_only(option_root);
40.501 + }
40.502 +
40.503 + pi = get_query_packages(set, argc, argv);
40.504 +
40.505 + while (razor_package_iterator_next(pi, &package,
40.506 + &name, &version, &arch)) {
40.507 + printf("verify %s-%s.%s - not implemented\n",
40.508 + name, version, arch);
40.509 + }
40.510 +
40.511 + razor_package_iterator_destroy(pi);
40.512 +}
40.513 +
40.514 +static void
40.515 +remove_package(const char *name,
40.516 + const char *old_version, const char *new_version,
40.517 + const char *arch, void *data)
40.518 +{
40.519 + if (old_version)
40.520 + printf("remove %s-%s.%s\n", name, old_version, arch);
40.521 +}
40.522 +
40.523 +static void
40.524 +command_erase(int argc, const char *argv[])
40.525 +{
40.526 + struct razor_set *set, *upstream, *next;
40.527 + struct razor_transaction *trans;
40.528 + struct razor_package_query *query;
40.529 + struct razor_package_iterator *pi;
40.530 + struct razor_package *package;
40.531 + const char *name, *version, *arch;
40.532 +
40.533 + if (argc == 0) {
40.534 + printf("no packages given for erase\n");
40.535 + exit(1);
40.536 + }
40.537 +
40.538 + set = razor_set_open(repo_filename);
40.539 + upstream = razor_set_create();
40.540 +
40.541 + trans = razor_transaction_create(set, upstream);
40.542 +
40.543 + query = razor_package_query_create(set);
40.544 + add_command_line_packages(set, query, argc, argv);
40.545 +
40.546 + pi = razor_package_query_finish(query);
40.547 + while (razor_package_iterator_next(pi, &package,
40.548 + &name, &version, &arch))
40.549 + razor_transaction_remove_package(trans, package);
40.550 + razor_package_iterator_destroy(pi);
40.551 +
40.552 + if (!option_nodeps && razor_transaction_describe(trans) > 0) {
40.553 + printf("unsatisfied dependencies.\n");
40.554 + exit(1);
40.555 + }
40.556 +
40.557 + if (option_test)
40.558 + exit(0);
40.559 +
40.560 + next = razor_transaction_finish(trans);
40.561 +
40.562 + if (!option_justdb)
40.563 + razor_set_diff(set, next, remove_package, NULL);
40.564 +
40.565 + razor_set_destroy(set);
40.566 + razor_set_destroy(upstream);
40.567 +
40.568 + razor_set_destroy(next);
40.569 +}
40.570 +
40.571 +static void
40.572 +install_package(const char *name,
40.573 + const char *old_version, const char *new_version,
40.574 + const char *arch, void *data)
40.575 +{
40.576 + if (new_version)
40.577 + printf("install %s-%s.%s\n", name, new_version, arch);
40.578 +}
40.579 +
40.580 +static void
40.581 +command_install(int argc, const char *argv[])
40.582 +{
40.583 + struct razor_set *set, *upstream, *next;
40.584 + struct razor_transaction *trans;
40.585 + struct razor_package_iterator *pi;
40.586 + struct razor_package *package;
40.587 + const char *name, *version, *arch;
40.588 +
40.589 + if (argc == 0) {
40.590 + printf("no packages given for install\n");
40.591 + exit(1);
40.592 + }
40.593 +
40.594 + set = razor_set_open(repo_filename);
40.595 + upstream = create_set_from_command_line(argc, argv);
40.596 +
40.597 + trans = razor_transaction_create(set, upstream);
40.598 +
40.599 + pi = razor_package_iterator_create(upstream);
40.600 + while (razor_package_iterator_next(pi, &package,
40.601 + &name, &version, &arch))
40.602 + razor_transaction_install_package(trans, package);
40.603 + razor_package_iterator_destroy(pi);
40.604 +
40.605 + if (!option_nodeps && razor_transaction_describe(trans) > 0) {
40.606 + printf("unsatisfied dependencies.\n");
40.607 + exit(1);
40.608 + }
40.609 +
40.610 + if (option_test)
40.611 + exit(0);
40.612 +
40.613 + next = razor_transaction_finish(trans);
40.614 +
40.615 + if (!option_justdb)
40.616 + razor_set_diff(set, next, install_package, NULL);
40.617 +
40.618 + razor_set_destroy(set);
40.619 + razor_set_destroy(upstream);
40.620 +
40.621 + razor_set_destroy(next);
40.622 +}
40.623 +
40.624 +static void
40.625 +update_package(const char *name,
40.626 + const char *old_version, const char *new_version,
40.627 + const char *arch, void *data)
40.628 +{
40.629 + if (old_version)
40.630 + printf("remove %s-%s.%s\n", name, old_version, arch);
40.631 + if (new_version)
40.632 + printf("install %s-%s.%s\n", name, new_version, arch);
40.633 +}
40.634 +
40.635 +static void
40.636 +command_update(int argc, const char *argv[])
40.637 +{
40.638 + struct razor_set *set, *upstream, *next;
40.639 + struct razor_transaction *trans;
40.640 + struct razor_package_iterator *pi;
40.641 + struct razor_package *package;
40.642 + const char *name, *version, *arch;
40.643 +
40.644 + if (argc == 0) {
40.645 + printf("no packages given for update\n");
40.646 + exit(1);
40.647 + }
40.648 +
40.649 + set = razor_set_open(repo_filename);
40.650 + upstream = create_set_from_command_line(argc, argv);
40.651 +
40.652 + trans = razor_transaction_create(set, upstream);
40.653 +
40.654 + pi = razor_package_iterator_create(upstream);
40.655 + while (razor_package_iterator_next(pi, &package,
40.656 + &name, &version, &arch))
40.657 + razor_transaction_update_package(trans, package);
40.658 + razor_package_iterator_destroy(pi);
40.659 +
40.660 + if (!option_nodeps && razor_transaction_describe(trans) > 0) {
40.661 + printf("unsatisfied dependencies.\n");
40.662 + exit(1);
40.663 + }
40.664 +
40.665 + if (option_test)
40.666 + exit(0);
40.667 +
40.668 + next = razor_transaction_finish(trans);
40.669 +
40.670 + if (!option_justdb)
40.671 + razor_set_diff(set, next, update_package, NULL);
40.672 +
40.673 + razor_set_destroy(set);
40.674 + razor_set_destroy(upstream);
40.675 +
40.676 + razor_set_destroy(next);
40.677 +}
40.678 +
40.679 +static int
40.680 +for_each_option(const struct option *options,
40.681 + const char *name, char short_name,
40.682 + void (*fn)(const struct option *o,
40.683 + const char *name, char short_name,
40.684 + void *data), void *data)
40.685 +{
40.686 + int i, count = 0;
40.687 +
40.688 + for (i = 0; options[i].type != OPTION_LAST; i++) {
40.689 + switch (options[i].type) {
40.690 + case OPTION_GROUP:
40.691 + count += for_each_option(options[i].data,
40.692 + name, short_name, fn, data);
40.693 + break;
40.694 +
40.695 + case OPTION_BOOL:
40.696 + case OPTION_STRING:
40.697 + if (name && strcmp(options[i].name, name) == 0) {
40.698 + fn(&options[i], name, 0, data);
40.699 + count++;
40.700 + break;
40.701 + }
40.702 +
40.703 + if (short_name &&
40.704 + short_name == options[i].short_name) {
40.705 + fn(&options[i], NULL, short_name, data);
40.706 + count++;
40.707 + break;
40.708 + }
40.709 + break;
40.710 +
40.711 + case OPTION_LAST:
40.712 + break;
40.713 + }
40.714 + }
40.715 +
40.716 + return count;
40.717 +}
40.718 +
40.719 +static void
40.720 +handle_option(const struct option *o,
40.721 + const char *name, char short_name, void *data)
40.722 +{
40.723 + if (o->data == NULL) {
40.724 + if (name)
40.725 + printf("option --%s not supported\n", name);
40.726 + else
40.727 + printf("option -%c not supported\n", short_name);
40.728 + return;
40.729 + }
40.730 +
40.731 + switch (o->type) {
40.732 + case OPTION_BOOL:
40.733 + *(int *) o->data = 1;
40.734 + break;
40.735 +
40.736 + case OPTION_STRING:
40.737 + *(const char **) o->data = name + strlen(o->name) + 1;
40.738 + break;
40.739 +
40.740 + case OPTION_LAST:
40.741 + case OPTION_GROUP:
40.742 + /* Shouldn't happen. */
40.743 + break;
40.744 + }
40.745 +}
40.746 +
40.747 +static int
40.748 +parse_options(const struct option *options, int argc, const char **argv)
40.749 +{
40.750 + int i, j, k;
40.751 +
40.752 + for (i = 1, j = 0; i < argc; i++) {
40.753 + if (argv[i][0] != '-') {
40.754 + argv[j++] = argv[i];
40.755 + continue;
40.756 + }
40.757 +
40.758 + if (argv[i][1] == '-') {
40.759 + if (for_each_option(options, &argv[i][2], 0,
40.760 + handle_option, NULL) == 0) {
40.761 + printf("unknown option: %s\n", argv[i]);
40.762 + exit(1);
40.763 + }
40.764 + continue;
40.765 + }
40.766 +
40.767 + for (k = 1; argv[i][k]; k++) {
40.768 + if (for_each_option(options, NULL, argv[i][k],
40.769 + handle_option, NULL) == 0) {
40.770 + printf("unknown option: -%c\n", argv[i][k]);
40.771 + exit(1);
40.772 + }
40.773 + }
40.774 + }
40.775 +
40.776 + return j;
40.777 +}
40.778 +
40.779 +static void
40.780 +print_options_help(const struct option *options)
40.781 +{
40.782 + int i;
40.783 +
40.784 + for (i = 0; options[i].type != OPTION_LAST; i++) {
40.785 + switch (options[i].type) {
40.786 + case OPTION_GROUP:
40.787 + printf("%s\n", options[i].description);
40.788 + print_options_help(options[i].data);
40.789 + printf("\n");
40.790 + break;
40.791 +
40.792 + case OPTION_BOOL:
40.793 + case OPTION_STRING:
40.794 + printf(" ");
40.795 + if (options[i].short_name)
40.796 + printf("-%c", options[i].short_name);
40.797 + if (options[i].short_name && options[i].name)
40.798 + printf(", ");
40.799 + if (options[i].name)
40.800 + printf("--%s", options[i].name);
40.801 + if (options[i].arg_name)
40.802 + printf("=%s", options[i].arg_name);
40.803 + if (options[i].description)
40.804 + printf("\t\t%s", options[i].description);
40.805 + printf("\n");
40.806 + break;
40.807 +
40.808 + case OPTION_LAST:
40.809 + break;
40.810 + }
40.811 + }
40.812 +}
40.813 +
40.814 +static void
40.815 +print_options_usage(const struct option *options)
40.816 +{
40.817 + int i;
40.818 +
40.819 + for (i = 0; options[i].type != OPTION_LAST; i++) {
40.820 + switch (options[i].type) {
40.821 + case OPTION_GROUP:
40.822 + print_options_usage(options[i].data);
40.823 + break;
40.824 +
40.825 + case OPTION_BOOL:
40.826 + printf("[");
40.827 + if (options[i].short_name)
40.828 + printf("-%c", options[i].short_name);
40.829 + if (options[i].short_name && options[i].name)
40.830 + printf("|");
40.831 + if (options[i].name)
40.832 + printf("--%s", options[i].name);
40.833 + printf("] ");
40.834 + break;
40.835 +
40.836 + case OPTION_STRING:
40.837 + printf("[");
40.838 + if (options[i].short_name)
40.839 + printf("-%c", options[i].short_name);
40.840 + if (options[i].short_name && options[i].name)
40.841 + printf("|");
40.842 + if (options[i].name)
40.843 + printf("--%s", options[i].name);
40.844 + if (options[i].arg_name)
40.845 + printf("=%s", options[i].arg_name);
40.846 + printf("] ");
40.847 + break;
40.848 +
40.849 +
40.850 + break;
40.851 +
40.852 + case OPTION_LAST:
40.853 + break;
40.854 + }
40.855 + }
40.856 +}
40.857 +
40.858 +int
40.859 +main(int argc, const char *argv[])
40.860 +{
40.861 + argc = parse_options(rpm_options, argc, argv);
40.862 +
40.863 + if (option_version) {
40.864 + printf("razor rpm version hoopla.\n");
40.865 + exit(0);
40.866 + }
40.867 +
40.868 + if (option_help) {
40.869 + printf("Usage: rpm [OPTION...]\n");
40.870 + print_options_help(rpm_options);
40.871 + exit(0);
40.872 + }
40.873 +
40.874 + if (option_usage) {
40.875 + printf("Usage: rpm [OPTION...]\n");
40.876 + print_options_usage(rpm_options);
40.877 + printf("\n");
40.878 + exit(0);
40.879 + }
40.880 +
40.881 + if (option_initdb) {
40.882 + command_initdb(argc, argv);
40.883 + } else if (option_verify) {
40.884 + command_verify(argc, argv);
40.885 + } else if (option_query) {
40.886 + command_query(argc, argv);
40.887 + } else if (option_install) {
40.888 + command_install(argc, argv);
40.889 + } else if (option_upgrade) {
40.890 + command_update(argc, argv);
40.891 + } else if (option_erase) {
40.892 + command_erase(argc, argv);
40.893 + } else {
40.894 + print_options_usage(rpm_options);
40.895 + printf("\n");
40.896 + exit(0);
40.897 + }
40.898 +
40.899 + return 0;
40.900 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/src/test-driver.c Mon Jun 16 15:40:30 2008 -0400
41.3 @@ -0,0 +1,458 @@
41.4 +#include <stdio.h>
41.5 +#include <string.h>
41.6 +#include <stdarg.h>
41.7 +#include <unistd.h>
41.8 +#include <fcntl.h>
41.9 +#include <errno.h>
41.10 +#include <expat.h>
41.11 +
41.12 +#include "razor.h"
41.13 +
41.14 +#define XML_BUFFER_SIZE 4096
41.15 +
41.16 +static void
41.17 +parse_xml_file(const char *filename,
41.18 + XML_StartElementHandler start,
41.19 + XML_EndElementHandler end,
41.20 + void *data)
41.21 +{
41.22 + XML_Parser parser;
41.23 + char *buffer;
41.24 + int fd, len, err;
41.25 +
41.26 + parser = XML_ParserCreate(NULL);
41.27 + XML_SetElementHandler(parser, start, end);
41.28 + XML_SetUserData(parser, data);
41.29 +
41.30 + fd = open(filename, O_RDONLY);
41.31 + if (fd < 0) {
41.32 + fprintf(stderr, "failed to open %s: %m\n", filename);
41.33 + exit(-1);
41.34 + }
41.35 +
41.36 + while (1) {
41.37 + buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
41.38 + len = read(fd, buffer, XML_BUFFER_SIZE);
41.39 + if (len == 0)
41.40 + break;
41.41 + err = XML_ParseBuffer(parser, len, len == 0);
41.42 + if (err == XML_STATUS_ERROR) {
41.43 + fprintf(stderr, "parse error at line %lu:\n%s\n",
41.44 + XML_GetCurrentLineNumber(parser),
41.45 + XML_ErrorString(XML_GetErrorCode(parser)));
41.46 + exit(-1);
41.47 + }
41.48 + }
41.49 +
41.50 + if (fd < 0) {
41.51 + fprintf(stderr, "read: %m\n");
41.52 + exit(-1);
41.53 + }
41.54 +
41.55 + close(fd);
41.56 +}
41.57 +
41.58 +struct test_context {
41.59 + struct razor_set *system_set, *repo_set, *result_set;
41.60 +
41.61 + struct razor_importer *importer;
41.62 + struct razor_set **importer_set;
41.63 +
41.64 + struct razor_transaction *trans;
41.65 +
41.66 + char *install_pkgs[3], *remove_pkgs[3];
41.67 + int n_install_pkgs, n_remove_pkgs;
41.68 +
41.69 + int unsat;
41.70 + int in_result;
41.71 +
41.72 + int debug, errors;
41.73 +};
41.74 +
41.75 +static void
41.76 +get_atts(const char **atts, ...)
41.77 +{
41.78 + va_list ap;
41.79 + const char *name, **ptr;
41.80 + int i;
41.81 +
41.82 + va_start(ap, atts);
41.83 + while (name = va_arg(ap, const char *), name != NULL) {
41.84 + ptr = va_arg(ap, const char **);
41.85 + *ptr = NULL;
41.86 + for (i = 0; atts[i]; i += 2) {
41.87 + if (strcmp(atts[i], name) == 0)
41.88 + *ptr = atts[i + 1];
41.89 + }
41.90 + }
41.91 + va_end(ap);
41.92 +}
41.93 +
41.94 +static enum razor_version_relation
41.95 +parse_relation (const char *rel_str)
41.96 +{
41.97 + if (!rel_str)
41.98 + return -1;
41.99 + if (rel_str[0] == 'L')
41.100 + return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
41.101 + else if (rel_str[0] == 'G')
41.102 + return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
41.103 + else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
41.104 + return RAZOR_VERSION_EQUAL;
41.105 + else
41.106 + return -1;
41.107 +}
41.108 +
41.109 +static void
41.110 +start_test(struct test_context *ctx, const char **atts)
41.111 +{
41.112 + const char *name = NULL;
41.113 +
41.114 + get_atts(atts, "name", &name, NULL);
41.115 + if (!name) {
41.116 + fprintf(stderr, "Test with no name\n");
41.117 + exit(1);
41.118 + }
41.119 + printf("%s\n", name);
41.120 +}
41.121 +
41.122 +static void
41.123 +end_test(struct test_context *ctx)
41.124 +{
41.125 + if (ctx->system_set) {
41.126 + razor_set_destroy(ctx->system_set);
41.127 + ctx->system_set = NULL;
41.128 + }
41.129 + if (ctx->repo_set) {
41.130 + razor_set_destroy(ctx->repo_set);
41.131 + ctx->repo_set = NULL;
41.132 + }
41.133 + if (ctx->result_set) {
41.134 + razor_set_destroy(ctx->result_set);
41.135 + ctx->result_set = NULL;
41.136 + }
41.137 + if (ctx->trans) {
41.138 + razor_transaction_destroy(ctx->trans);
41.139 + ctx->trans = NULL;
41.140 + }
41.141 +}
41.142 +
41.143 +static void
41.144 +start_set(struct test_context *ctx, const char **atts)
41.145 +{
41.146 + const char *name = NULL;
41.147 +
41.148 + ctx->importer = razor_importer_new();
41.149 + get_atts(atts, "name", &name, NULL);
41.150 + if (!name)
41.151 + ctx->importer_set = &ctx->result_set;
41.152 + else if (!strcmp(name, "system"))
41.153 + ctx->importer_set = &ctx->system_set;
41.154 + else if (!strcmp(name, "repo"))
41.155 + ctx->importer_set = &ctx->repo_set;
41.156 + else {
41.157 + fprintf(stderr, " bad set name '%s'\n", name);
41.158 + exit(1);
41.159 + }
41.160 +}
41.161 +
41.162 +static void
41.163 +end_set(struct test_context *ctx)
41.164 +{
41.165 + *ctx->importer_set = razor_importer_finish(ctx->importer);
41.166 + ctx->importer = NULL;
41.167 +}
41.168 +
41.169 +static void
41.170 +start_package(struct test_context *ctx, const char **atts)
41.171 +{
41.172 + const char *name = NULL, *version = NULL, *arch = NULL;
41.173 +
41.174 + get_atts(atts, "name", &name,
41.175 + "version", &version,
41.176 + "arch", &arch,
41.177 + NULL);
41.178 +
41.179 + if (!name) {
41.180 + fprintf(stderr, " package with no name\n");
41.181 + exit(1);
41.182 + }
41.183 +
41.184 + razor_importer_begin_package(ctx->importer, name, version, arch);
41.185 + razor_importer_add_property(ctx->importer, name,
41.186 + RAZOR_VERSION_EQUAL, version,
41.187 + RAZOR_PROPERTY_PROVIDES);
41.188 +}
41.189 +
41.190 +static void
41.191 +end_package(struct test_context *ctx)
41.192 +{
41.193 + razor_importer_finish_package(ctx->importer);
41.194 +}
41.195 +
41.196 +static void
41.197 +add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
41.198 +{
41.199 + razor_importer_add_property(ctx->importer, name,
41.200 + rel, version, type);
41.201 +}
41.202 +
41.203 +static void
41.204 +check_unsatisfiable_property(struct test_context *ctx,
41.205 + enum razor_property_type type,
41.206 + const char *name,
41.207 + enum razor_version_relation rel,
41.208 + const char *version)
41.209 +{
41.210 + static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
41.211 +
41.212 + if (!version)
41.213 + version = "";
41.214 +
41.215 + if (razor_transaction_unsatisfied_property(ctx->trans,
41.216 + name, rel, version, type))
41.217 + return;
41.218 +
41.219 + fprintf(stderr, " didn't get unsatisfiable '%s %s %s'\n",
41.220 + name, relation_string[rel], version);
41.221 + ctx->errors++;
41.222 +}
41.223 +
41.224 +static void
41.225 +start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
41.226 +{
41.227 + const char *name = NULL, *rel_str = NULL, *version = NULL;
41.228 + enum razor_version_relation rel;
41.229 +
41.230 + get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
41.231 + if (name == NULL) {
41.232 + fprintf(stderr, " no name specified for property\n");
41.233 + exit(1);
41.234 + }
41.235 + if (version) {
41.236 + rel = parse_relation(rel_str);
41.237 + if (rel == -1) {
41.238 + fprintf(stderr, " bad or missing version relation for property %s\n", name);
41.239 + exit(1);
41.240 + }
41.241 + } else
41.242 + rel = RAZOR_VERSION_EQUAL;
41.243 +
41.244 + if (ctx->unsat)
41.245 + check_unsatisfiable_property(ctx, type, name, rel, version);
41.246 + else
41.247 + add_property(ctx, type, name, rel, version);
41.248 +}
41.249 +
41.250 +static void
41.251 +start_transaction(struct test_context *ctx, const char **atts)
41.252 +{
41.253 + ctx->n_install_pkgs = 0;
41.254 + ctx->n_remove_pkgs = 0;
41.255 +}
41.256 +
41.257 +static void
41.258 +end_transaction(struct test_context *ctx)
41.259 +{
41.260 + struct razor_package *pkg;
41.261 + int errors, i;
41.262 +
41.263 + ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
41.264 + for (i = 0; i < ctx->n_install_pkgs; i++) {
41.265 + pkg = razor_set_get_package(ctx->repo_set,
41.266 + ctx->install_pkgs[i]);
41.267 + razor_transaction_install_package(ctx->trans, pkg);
41.268 + }
41.269 + for (i = 0; i < ctx->n_remove_pkgs; i++) {
41.270 + pkg = razor_set_get_package(ctx->repo_set,
41.271 + ctx->remove_pkgs[i]);
41.272 + razor_transaction_remove_package(ctx->trans, pkg);
41.273 + }
41.274 +
41.275 + errors = razor_transaction_resolve(ctx->trans);
41.276 + printf("\n");
41.277 +
41.278 + while (ctx->n_install_pkgs--)
41.279 + free(ctx->install_pkgs[ctx->n_install_pkgs]);
41.280 + while (ctx->n_remove_pkgs--)
41.281 + free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
41.282 +
41.283 + if (!errors) {
41.284 + struct razor_set *new;
41.285 + new = razor_transaction_finish(ctx->trans);
41.286 + ctx->system_set = new;
41.287 + }
41.288 +}
41.289 +
41.290 +static void
41.291 +start_install_or_update(struct test_context *ctx, const char **atts)
41.292 +{
41.293 + const char *name = NULL;
41.294 +
41.295 + get_atts(atts, "name", &name, NULL);
41.296 + if (!name) {
41.297 + fprintf(stderr, " install/update with no name\n");
41.298 + exit(1);
41.299 + }
41.300 +
41.301 + ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
41.302 +}
41.303 +
41.304 +static void
41.305 +start_remove(struct test_context *ctx, const char **atts)
41.306 +{
41.307 + const char *name = NULL;
41.308 +
41.309 + get_atts(atts, "name", &name, NULL);
41.310 + if (!name) {
41.311 + fprintf(stderr, " remove with no name\n");
41.312 + exit(1);
41.313 + }
41.314 +
41.315 + ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
41.316 +}
41.317 +
41.318 +static void
41.319 +start_result(struct test_context *ctx, const char **atts)
41.320 +{
41.321 + ctx->in_result = 1;
41.322 +}
41.323 +
41.324 +static void
41.325 +diff_callback(const char *name,
41.326 + const char *old_version,
41.327 + const char *new_version,
41.328 + const char *arch,
41.329 + void *data)
41.330 +{
41.331 + struct test_context *ctx = data;
41.332 +
41.333 + ctx->errors++;
41.334 + if (old_version) {
41.335 + fprintf(stderr, " result set should not contain %s %s\n",
41.336 + name, old_version);
41.337 + } else {
41.338 + fprintf(stderr, " result set should contain %s %s\n",
41.339 + name, new_version);
41.340 + }
41.341 +}
41.342 +
41.343 +static void
41.344 +end_result(struct test_context *ctx)
41.345 +{
41.346 + ctx->in_result = 0;
41.347 +
41.348 + if (ctx->result_set) {
41.349 + if (!ctx->system_set)
41.350 + ctx->system_set = razor_set_create();
41.351 + razor_set_diff(ctx->system_set, ctx->result_set,
41.352 + diff_callback, ctx);
41.353 + }
41.354 +}
41.355 +
41.356 +static void
41.357 +start_unsatisfiable(struct test_context *ctx, const char **atts)
41.358 +{
41.359 + if (ctx->result_set) {
41.360 + fprintf(stderr, "Expected to fail, but didn't\n");
41.361 + exit(1);
41.362 + }
41.363 +
41.364 + ctx->unsat = 1;
41.365 +}
41.366 +
41.367 +static void
41.368 +end_unsatisfiable(struct test_context *ctx)
41.369 +{
41.370 + ctx->unsat = 0;
41.371 +}
41.372 +
41.373 +static void
41.374 +start_test_element(void *data, const char *element, const char **atts)
41.375 +{
41.376 + struct test_context *ctx = data;
41.377 +
41.378 + if (strcmp(element, "tests") == 0) {
41.379 + ;
41.380 + } else if (strcmp(element, "test") == 0) {
41.381 + start_test(ctx, atts);
41.382 + } else if (strcmp(element, "set") == 0) {
41.383 + start_set(ctx, atts);
41.384 + } else if (strcmp(element, "transaction") == 0) {
41.385 + start_transaction(ctx, atts);
41.386 + } else if (strcmp(element, "install") == 0) {
41.387 + start_install_or_update(ctx, atts);
41.388 + } else if (strcmp(element, "install") == 0) {
41.389 + start_install_or_update(ctx, atts);
41.390 + } else if (strcmp(element, "remove") == 0) {
41.391 + start_remove(ctx, atts);
41.392 + } else if (strcmp(element, "result") == 0) {
41.393 + start_result(ctx, atts);
41.394 + } else if (strcmp(element, "unsatisfiable") == 0) {
41.395 + start_unsatisfiable(ctx, atts);
41.396 + } else if (strcmp(element, "package") == 0) {
41.397 + start_package(ctx, atts);
41.398 + } else if (strcmp(element, "requires") == 0) {
41.399 + start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
41.400 + } else if (strcmp(element, "provides") == 0) {
41.401 + start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
41.402 + } else if (strcmp(element, "conflicts") == 0) {
41.403 + start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
41.404 + } else if (strcmp(element, "obsoletes") == 0) {
41.405 + start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
41.406 + } else {
41.407 + fprintf(stderr, "Unrecognized element '%s'\n", element);
41.408 + exit(1);
41.409 + }
41.410 +}
41.411 +
41.412 +static void
41.413 +end_test_element (void *data, const char *element)
41.414 +{
41.415 + struct test_context *ctx = data;
41.416 +
41.417 + if (strcmp(element, "test") == 0) {
41.418 + end_test(ctx);
41.419 + } else if (strcmp(element, "set") == 0) {
41.420 + end_set(ctx);
41.421 + } else if (strcmp(element, "package") == 0) {
41.422 + end_package(ctx);
41.423 + } else if (strcmp(element, "transaction") == 0) {
41.424 + end_transaction(ctx);
41.425 + } else if (strcmp(element, "result") == 0) {
41.426 + end_result(ctx);
41.427 + } else if (strcmp(element, "unsatisfiable") == 0) {
41.428 + end_unsatisfiable(ctx);
41.429 + }
41.430 +}
41.431 +
41.432 +int main(int argc, char *argv[])
41.433 +{
41.434 + struct test_context ctx;
41.435 + const char *test_file;
41.436 +
41.437 + memset(&ctx, 0, sizeof ctx);
41.438 +
41.439 + if (argc > 3) {
41.440 + fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
41.441 + exit(-1);
41.442 + }
41.443 +
41.444 + if (argc >= 2 && !strcmp (argv[1], "-d")) {
41.445 + ctx.debug = 1;
41.446 + argc--;
41.447 + argv++;
41.448 + }
41.449 + if (argc == 2)
41.450 + test_file = argv[1];
41.451 + else
41.452 + test_file = "test.xml";
41.453 +
41.454 + parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
41.455 +
41.456 + if (ctx.errors) {
41.457 + fprintf(stderr, "\n%d errors\n", ctx.errors);
41.458 + return 1;
41.459 + } else
41.460 + return 0;
41.461 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/src/test.xml Mon Jun 16 15:40:30 2008 -0400
42.3 @@ -0,0 +1,858 @@
42.4 +<tests>
42.5 +
42.6 + <test name="testEmpty">
42.7 + <set name="system"/>
42.8 + <set name="repo">
42.9 + <package name="zsh" version="1-1" arch="i386"/>
42.10 + </set>
42.11 + <transaction>
42.12 + <install name="zsh"/>
42.13 + <remove name="zsh"/>
42.14 + </transaction>
42.15 + <result>
42.16 + <set/>
42.17 + </result>
42.18 + </test>
42.19 +
42.20 + <test name="testInstallSinglePackageNoRequires">
42.21 + <set name="system"/>
42.22 + <set name="repo">
42.23 + <package name="zsh" version="1-1" arch="i386"/>
42.24 + </set>
42.25 + <transaction>
42.26 + <install name="zsh"/>
42.27 + </transaction>
42.28 + <result>
42.29 + <set>
42.30 + <package name="zsh" version="1-1" arch="i386"/>
42.31 + </set>
42.32 + </result>
42.33 + </test>
42.34 +
42.35 + <test name="testInstallSinglePackageRequireNotProvided">
42.36 + <set name="system"/>
42.37 + <set name="repo">
42.38 + <package name="zsh" version="1-1" arch="i386">
42.39 + <requires name="zip"/>
42.40 + </package>
42.41 + </set>
42.42 + <transaction>
42.43 + <install name="zsh"/>
42.44 + </transaction>
42.45 + <result>
42.46 + <unsatisfiable>
42.47 + <requires name="zip"/>
42.48 + </unsatisfiable>
42.49 + </result>
42.50 + </test>
42.51 +
42.52 + <test name="testInstallSinglePackageRequireInstalled">
42.53 + <set name="system">
42.54 + <package name="zip" version="1-1" arch="i386"/>
42.55 + </set>
42.56 + <set name="repo">
42.57 + <package name="zsh" version="1-1" arch="i386">
42.58 + <requires name="zip"/>
42.59 + </package>
42.60 + </set>
42.61 + <transaction>
42.62 + <install name="zsh"/>
42.63 + </transaction>
42.64 + <result>
42.65 + <set>
42.66 + <package name="zip" version="1-1" arch="i386"/>
42.67 + <package name="zsh" version="1-1" arch="i386"/>
42.68 + </set>
42.69 + </result>
42.70 + </test>
42.71 +
42.72 + <test name="testInstallSinglePackageRequireInstalledRequireNotProvided">
42.73 + <set name="system">
42.74 + <package name="zip" version="1-2" arch="i386"/>
42.75 + </set>
42.76 + <set name="repo">
42.77 + <package name="zsh" version="1-1" arch="i386">
42.78 + <requires name="zip"/>
42.79 + <!-- This may be a bug in the python test: it looks
42.80 + like they meant to have zip require zap, not zsh.
42.81 + But the install succeeds if you do that...
42.82 + -->
42.83 + <requires name="zap"/>
42.84 + </package>
42.85 + </set>
42.86 + <transaction>
42.87 + <install name="zsh"/>
42.88 + </transaction>
42.89 + <result>
42.90 + <unsatisfiable>
42.91 + <requires name="zap"/>
42.92 + </unsatisfiable>
42.93 + </result>
42.94 + </test>
42.95 +
42.96 + <test name="testInstallSinglePackageRequireInstalledRequireInstall">
42.97 + <set name="system">
42.98 + <package name="zip" version="1-3" arch="i386">
42.99 + <requires name="zap"/>
42.100 + </package>
42.101 + </set>
42.102 + <set name="repo">
42.103 + <package name="zsh" version="1-1" arch="i386">
42.104 + <requires name="zip"/>
42.105 + </package>
42.106 + <package name="zap" version="1-2" arch="i386"/>
42.107 + </set>
42.108 + <transaction>
42.109 + <install name="zsh"/>
42.110 + <install name="zap"/>
42.111 + </transaction>
42.112 + <result>
42.113 + <set>
42.114 + <package name="zap" version="1-2" arch="i386"/>
42.115 + <package name="zip" version="1-3" arch="i386"/>
42.116 + <package name="zsh" version="1-1" arch="i386"/>
42.117 + </set>
42.118 + </result>
42.119 + </test>
42.120 +
42.121 + <test name="testInstallSinglePackageRequireVer1NotProvided">
42.122 + <set name="system">
42.123 + <package name="zip" version="1.0-2" arch="i386"/>
42.124 + </set>
42.125 + <set name="repo">
42.126 + <package name="zsh" version="1-1" arch="i386">
42.127 + <requires name="zip" relation="EQ" version="1.3-2"/>
42.128 + </package>
42.129 + </set>
42.130 + <transaction>
42.131 + <install name="zsh"/>
42.132 + </transaction>
42.133 + <result>
42.134 + <unsatisfiable>
42.135 + <requires name="zip" relation="EQ" version="1.3-2"/>
42.136 + </unsatisfiable>
42.137 + </result>
42.138 + </test>
42.139 +
42.140 + <test name="testInstallSinglePackageRequireVer1Installed">
42.141 + <set name="system">
42.142 + <package name="zip" version="1.3-2" arch="i386"/>
42.143 + </set>
42.144 + <set name="repo">
42.145 + <package name="zsh" version="1-1" arch="i386">
42.146 + <requires name="zip" relation="EQ" version="1.3-2"/>
42.147 + </package>
42.148 + </set>
42.149 + <transaction>
42.150 + <install name="zsh"/>
42.151 + </transaction>
42.152 + <result>
42.153 + <set>
42.154 + <package name="zip" version="1.3-2" arch="i386"/>
42.155 + <package name="zsh" version="1-1" arch="i386"/>
42.156 + </set>
42.157 + </result>
42.158 + </test>
42.159 +
42.160 + <test name="testInstallSinglePackageRequireVer2NotProvided">
42.161 + <set name="system">
42.162 + <package name="zip" version="1.3-2" arch="i386"/>
42.163 + </set>
42.164 + <set name="repo">
42.165 + <package name="zsh" version="1-1" arch="i386">
42.166 + <requires name="zip" relation="EQ" version="1.3-4"/>
42.167 + </package>
42.168 + </set>
42.169 + <transaction>
42.170 + <install name="zsh"/>
42.171 + </transaction>
42.172 + <result>
42.173 + <unsatisfiable>
42.174 + <requires name="zip" relation="EQ" version="1.3-4"/>
42.175 + </unsatisfiable>
42.176 + </result>
42.177 + </test>
42.178 +
42.179 + <test name="testInstallSinglePackageRequireVer2Installed">
42.180 + <set name="system">
42.181 + <package name="zip" version="1.3-4" arch="i386"/>
42.182 + </set>
42.183 + <set name="repo">
42.184 + <package name="zsh" version="1-1" arch="i386">
42.185 + <requires name="zip" relation="EQ" version="1.3-4"/>
42.186 + </package>
42.187 + </set>
42.188 + <transaction>
42.189 + <install name="zsh"/>
42.190 + </transaction>
42.191 + <result>
42.192 + <set>
42.193 + <package name="zip" version="1.3-4" arch="i386"/>
42.194 + <package name="zsh" version="1-1" arch="i386"/>
42.195 + </set>
42.196 + </result>
42.197 + </test>
42.198 +
42.199 + <test name="testInstallSinglePackageRequireVer3NotProvided">
42.200 + <set name="system">
42.201 + <package name="zip" version="0:1.3-4" arch="i386"/>
42.202 + </set>
42.203 + <set name="repo">
42.204 + <package name="zsh" version="1-1" arch="i386">
42.205 + <requires name="zip" relation="GE" version="1:1.3-4"/>
42.206 + </package>
42.207 + </set>
42.208 + <transaction>
42.209 + <install name="zsh"/>
42.210 + </transaction>
42.211 + <result>
42.212 + <unsatisfiable>
42.213 + <requires name="zip" relation="GE" version="1:1.3-4"/>
42.214 + </unsatisfiable>
42.215 + </result>
42.216 + </test>
42.217 +
42.218 + <test name="testInstallSinglePackageRequireVer3Installed">
42.219 + <set name="system">
42.220 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.221 + </set>
42.222 + <set name="repo">
42.223 + <package name="zsh" version="1-1" arch="i386">
42.224 + <requires name="zip" relation="GE" version="2:1.3-4"/>
42.225 + </package>
42.226 + </set>
42.227 + <transaction>
42.228 + <install name="zsh"/>
42.229 + </transaction>
42.230 + <result>
42.231 + <set>
42.232 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.233 + <package name="zsh" version="1-1" arch="i386"/>
42.234 + </set>
42.235 + </result>
42.236 + </test>
42.237 +
42.238 + <test name="testInstallSinglePackageRequireVer4NotProvided">
42.239 + <set name="system">
42.240 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.241 + </set>
42.242 + <set name="repo">
42.243 + <package name="zsh" version="1-1" arch="i386">
42.244 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.245 + </package>
42.246 + </set>
42.247 + <transaction>
42.248 + <install name="zsh"/>
42.249 + </transaction>
42.250 + <result>
42.251 + <unsatisfiable>
42.252 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.253 + </unsatisfiable>
42.254 + </result>
42.255 + </test>
42.256 +
42.257 + <test name="testInstallSinglePackageRequireVer4_1Installed">
42.258 + <set name="system">
42.259 + <package name="zip" version="2:1.0-4" arch="i386"/>
42.260 + </set>
42.261 + <set name="repo">
42.262 + <package name="zsh" version="1-1" arch="i386">
42.263 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.264 + </package>
42.265 + </set>
42.266 + <transaction>
42.267 + <install name="zsh"/>
42.268 + </transaction>
42.269 + <result>
42.270 + <set>
42.271 + <package name="zip" version="2:1.0-4" arch="i386"/>
42.272 + <package name="zsh" version="1-1" arch="i386"/>
42.273 + </set>
42.274 + </result>
42.275 + </test>
42.276 +
42.277 + <test name="testInstallSinglePackageRequireVer4_2Installed">
42.278 + <set name="system">
42.279 + <package name="zip" version="2:1.3-3" arch="i386"/>
42.280 + </set>
42.281 + <set name="repo">
42.282 + <package name="zsh" version="1-1" arch="i386">
42.283 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.284 + </package>
42.285 + </set>
42.286 + <transaction>
42.287 + <install name="zsh"/>
42.288 + </transaction>
42.289 + <result>
42.290 + <set>
42.291 + <package name="zip" version="2:1.3-3" arch="i386"/>
42.292 + <package name="zsh" version="1-1" arch="i386"/>
42.293 + </set>
42.294 + </result>
42.295 + </test>
42.296 +
42.297 + <test name="testInstallSinglePackageRequireVer4_3Installed">
42.298 + <set name="system">
42.299 + <package name="zip" version="1.3-4" arch="i386"/>
42.300 + </set>
42.301 + <set name="repo">
42.302 + <package name="zsh" version="1-1" arch="i386">
42.303 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.304 + </package>
42.305 + </set>
42.306 + <transaction>
42.307 + <install name="zsh"/>
42.308 + </transaction>
42.309 + <result>
42.310 + <set>
42.311 + <package name="zip" version="1.3-4" arch="i386"/>
42.312 + <package name="zsh" version="1-1" arch="i386"/>
42.313 + </set>
42.314 + </result>
42.315 + </test>
42.316 +
42.317 + <test name="testInstallSinglePackageRequireVer4_4Installed">
42.318 + <set name="system">
42.319 + <package name="zip" version="1:1.3-4" arch="i386"/>
42.320 + </set>
42.321 + <set name="repo">
42.322 + <package name="zsh" version="1-1" arch="i386">
42.323 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.324 + </package>
42.325 + </set>
42.326 + <transaction>
42.327 + <install name="zsh"/>
42.328 + </transaction>
42.329 + <result>
42.330 + <set>
42.331 + <package name="zip" version="1:1.3-4" arch="i386"/>
42.332 + <package name="zsh" version="1-1" arch="i386"/>
42.333 + </set>
42.334 + </result>
42.335 + </test>
42.336 +
42.337 + <test name="testInstallSinglePackageRequireVer4_5Installed">
42.338 + <set name="system">
42.339 + <package name="zip" version="2:0.3-4" arch="i386"/>
42.340 + </set>
42.341 + <set name="repo">
42.342 + <package name="zsh" version="1-1" arch="i386">
42.343 + <requires name="zip" relation="LT" version="2:1.3-4"/>
42.344 + </package>
42.345 + </set>
42.346 + <transaction>
42.347 + <install name="zsh"/>
42.348 + </transaction>
42.349 + <result>
42.350 + <set>
42.351 + <package name="zip" version="2:0.3-4" arch="i386"/>
42.352 + <package name="zsh" version="1-1" arch="i386"/>
42.353 + </set>
42.354 + </result>
42.355 + </test>
42.356 +
42.357 + <test name="testInstallSinglePackageRequireXtraBadVer">
42.358 + <set name="system">
42.359 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.360 + </set>
42.361 + <set name="repo">
42.362 + <package name="zsh" version="1-1" arch="i386">
42.363 + <requires name="zip" relation="EQ" version="2:1.3-4"/>
42.364 + <requires name="zap" relation="EQ" version="2:1.3-4"/>
42.365 + </package>
42.366 + <package name="zap" version="0:1.3-4" arch="i386"/>
42.367 + </set>
42.368 + <transaction>
42.369 + <install name="zsh"/>
42.370 + </transaction>
42.371 + <result>
42.372 + <unsatisfiable>
42.373 + <requires name="zap" relation="EQ" version="2:1.3-4"/>
42.374 + </unsatisfiable>
42.375 + </result>
42.376 + </test>
42.377 +
42.378 + <test name="testInstallSinglePackageRequireXtra">
42.379 + <set name="system">
42.380 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.381 + </set>
42.382 + <set name="repo">
42.383 + <package name="zsh" version="1-1" arch="i386">
42.384 + <requires name="zip" relation="EQ" version="2:1.3-4"/>
42.385 + <requires name="zap" relation="EQ" version="4:2.6-8"/>
42.386 + </package>
42.387 + <package name="zap" version="4:2.6-8" arch="i386"/>
42.388 + </set>
42.389 + <transaction>
42.390 + <install name="zsh"/>
42.391 + </transaction>
42.392 + <result>
42.393 + <set>
42.394 + <package name="zap" version="4:2.6-8" arch="i386"/>
42.395 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.396 + <package name="zsh" version="1-1" arch="i386"/>
42.397 + </set>
42.398 + </result>
42.399 + </test>
42.400 +
42.401 + <test name="testInstallSinglePackageRequireInstalledRequireXtra">
42.402 + <set name="system">
42.403 + <package name="zip" version="2:1.3-4" arch="i386">
42.404 + <requires name="zap" relation="EQ" version="4:2.6-8"/>
42.405 + </package>
42.406 + </set>
42.407 + <set name="repo">
42.408 + <package name="zsh" version="1-1" arch="i386">
42.409 + <requires name="zip" relation="EQ" version="2:1.3-4"/>
42.410 + </package>
42.411 + <!-- This may be a bug in the python test; it doesn't
42.412 + actually matter whether or not zap is available
42.413 + -->
42.414 + <package name="zap" version="4:2.6-8" arch="i386"/>
42.415 + </set>
42.416 + <transaction>
42.417 + <install name="zsh"/>
42.418 + </transaction>
42.419 + <result>
42.420 + <set>
42.421 + <package name="zip" version="2:1.3-4" arch="i386"/>
42.422 + <package name="zsh" version="1-1" arch="i386"/>
42.423 + </set>
42.424 + </result>
42.425 + </test>
42.426 +
42.427 + <test name="testInstallSinglePackageRequireUpgradeRequireXtraErr">
42.428 + <set name="system">
42.429 + <package name="zip" version="2:1.3-4" arch="i386">
42.430 + <requires name="zap" relation="EQ" version="2:1.3-3"/>
42.431 + </package>
42.432 + </set>
42.433 + <set name="repo">
42.434 + <package name="zsh" version="1-1" arch="i386">
42.435 + <requires name="zip" relation="EQ" version="4:2.6-8"/>
42.436 + </package>
42.437 + <package name="zip" version="4:2.6-8" arch="i386">
42.438 + <requires name="zap" relation="EQ" version="2:1.3-4"/>
42.439 + </package>
42.440 + <package name="zap" version="2:1.3-4" arch="i386">
42.441 + <requires name="zsh" relation="EQ" version="2:4-8"/>
42.442 + </package>
42.443 + </set>
42.444 + <transaction>
42.445 + <install name="zsh"/>
42.446 + </transaction>
42.447 + <result>
42.448 + <unsatisfiable>
42.449 + <requires name="zsh" relation="EQ" version="2:4-8"/>
42.450 + </unsatisfiable>
42.451 + </result>
42.452 + </test>
42.453 +
42.454 + <test name="testInstallSinglePackageRequireUpgradeRequireXtraOk">
42.455 + <set name="system">
42.456 + <package name="zip" version="2:1.3-4" arch="i386">
42.457 + <requires name="zap" relation="EQ" version="2:1.3-3"/>
42.458 + </package>
42.459 + </set>
42.460 + <set name="repo">
42.461 + <package name="zsh" version="1-1" arch="i386">
42.462 + <requires name="zip" relation="EQ" version="4:2.6-8"/>
42.463 + </package>
42.464 + <package name="zip" version="4:2.6-8" arch="i386">
42.465 + <requires name="zap" relation="EQ" version="2:1.3-4"/>
42.466 + </package>
42.467 + <package name="zap" version="2:1.3-4" arch="i386"/>
42.468 + </set>
42.469 + <transaction>
42.470 + <install name="zsh"/>
42.471 + </transaction>
42.472 + <result>
42.473 + <set>
42.474 + <package name="zap" version="2:1.3-4" arch="i386"/>
42.475 + <package name="zip" version="4:2.6-8" arch="i386"/>
42.476 + <package name="zsh" version="1-1" arch="i386"/>
42.477 + </set>
42.478 + </result>
42.479 + </test>
42.480 +
42.481 + <test name="testInstallSinglePackageRequireMultiXtra">
42.482 + <set name="system"/>
42.483 + <set name="repo">
42.484 + <package name="zsh" version="1-1" arch="i386">
42.485 + <requires name="zip" relation="EQ" version="4:2.6-8"/>
42.486 + </package>
42.487 + <package name="zip" version="4:2.6-8" arch="i386">
42.488 + <requires name="zap" relation="EQ" version="2:1.3-4"/>
42.489 + </package>
42.490 + <package name="zap" version="2:1.3-4" arch="i386"/>
42.491 + </set>
42.492 + <transaction>
42.493 + <install name="zsh"/>
42.494 + </transaction>
42.495 + <result>
42.496 + <set>
42.497 + <package name="zap" version="2:1.3-4" arch="i386"/>
42.498 + <package name="zip" version="4:2.6-8" arch="i386"/>
42.499 + <package name="zsh" version="1-1" arch="i386"/>
42.500 + </set>
42.501 + </result>
42.502 + </test>
42.503 +
42.504 + <test name="testInstallSinglePackageRequireInstalledMultiLib">
42.505 + <set name="system">
42.506 + <package name="zip" version="1-3" arch="i386"/>
42.507 + </set>
42.508 + <set name="repo">
42.509 + <package name="zsh" version="1-1" arch="x86_64">
42.510 + <requires name="zip"/>
42.511 + </package>
42.512 + <package name="zip" version="1-3" arch="x86_64"/>
42.513 + </set>
42.514 + <transaction>
42.515 + <install name="zsh"/>
42.516 + </transaction>
42.517 + <result>
42.518 + <set>
42.519 + <package name="zip" version="1-3" arch="i386"/>
42.520 + <package name="zsh" version="1-1" arch="x86_64"/>
42.521 + </set>
42.522 + </result>
42.523 + </test>
42.524 +
42.525 + <test name="testInstallSinglePackageRequireXtra1MultiLib">
42.526 + <set name="system"/>
42.527 + <set name="repo">
42.528 + <package name="zsh" version="1-1" arch="x86_64">
42.529 + <requires name="zip"/>
42.530 + </package>
42.531 + <package name="zip" version="1-3" arch="i386"/>
42.532 + </set>
42.533 + <transaction>
42.534 + <install name="zsh"/>
42.535 + </transaction>
42.536 + <result>
42.537 + <set>
42.538 + <package name="zip" version="1-3" arch="i386"/>
42.539 + <package name="zsh" version="1-1" arch="x86_64"/>
42.540 + </set>
42.541 + </result>
42.542 + </test>
42.543 +
42.544 + <test name="testInstallSinglePackageRequireXtra2_64MultiLib">
42.545 + <set name="system"/>
42.546 + <set name="repo">
42.547 + <package name="zsh" version="1-1" arch="x86_64">
42.548 + <requires name="zip"/>
42.549 + </package>
42.550 + <package name="zip" version="1-3" arch="i386"/>
42.551 + <package name="zip" version="1-3" arch="x86_64"/>
42.552 + </set>
42.553 + <transaction>
42.554 + <install name="zsh"/>
42.555 + </transaction>
42.556 + <result>
42.557 + <set>
42.558 + <package name="zsh" version="1-1" arch="x86_64"/>
42.559 + <package name="zip" version="1-3" arch="x86_64"/>
42.560 + </set>
42.561 + </result>
42.562 + </test>
42.563 +
42.564 + <test name="testInstallSinglePackageRequireXtra2_32MultiLib">
42.565 + <set name="system"/>
42.566 + <set name="repo">
42.567 + <package name="zsh" version="1-1" arch="i386">
42.568 + <requires name="zip"/>
42.569 + </package>
42.570 + <package name="zip" version="1-3" arch="i386"/>
42.571 + <package name="zip" version="1-3" arch="x86_64"/>
42.572 + </set>
42.573 + <transaction>
42.574 + <install name="zsh"/>
42.575 + </transaction>
42.576 + <result>
42.577 + <set>
42.578 + <package name="zip" version="1-3" arch="i386"/>
42.579 + <package name="zsh" version="1-1" arch="i386"/>
42.580 + </set>
42.581 + </result>
42.582 + </test>
42.583 +
42.584 + <test name="testUpdateSinglePackage">
42.585 + <set name="system">
42.586 + <package name="zsh" version="1-1" arch="i386"/>
42.587 + </set>
42.588 + <set name="repo">
42.589 + <package name="zsh" version="1-3" arch="i386"/>
42.590 + </set>
42.591 + <transaction>
42.592 + <install name="zsh"/>
42.593 + </transaction>
42.594 + <result>
42.595 + <set>
42.596 + <package name="zsh" version="1-3" arch="i386"/>
42.597 + </set>
42.598 + </result>
42.599 + </test>
42.600 +
42.601 + <test name="testUpdateForDependency">
42.602 + <set name="system">
42.603 + <package name="zip" version="0:1-1" arch="i386"/>
42.604 + </set>
42.605 + <set name="repo">
42.606 + <package name="zsh" version="0:1-1" arch="i386">
42.607 + <requires name="zip" relation="EQ" version="0:2-1"/>
42.608 + </package>
42.609 + <package name="zip" version="0:2-1" arch="i386"/>
42.610 + </set>
42.611 + <transaction>
42.612 + <install name="zsh"/>
42.613 + </transaction>
42.614 + <result>
42.615 + <set>
42.616 + <package name="zip" version="0:2-1" arch="i386"/>
42.617 + <package name="zsh" version="0:1-1" arch="i386"/>
42.618 + </set>
42.619 + </result>
42.620 + </test>
42.621 +
42.622 + <test name="testUpdateSplitPackage">
42.623 + <set name="system">
42.624 + <package name="zip" version="0:1-1" arch="i386">
42.625 + <provides name="libzip" relation="EQ" version="0:1-1"/>
42.626 + </package>
42.627 + </set>
42.628 + <set name="repo">
42.629 + <package name="zsh" version="0:1-1" arch="i386">
42.630 + <requires name="libzip" relation="EQ" version="0:2-1"/>
42.631 + </package>
42.632 + <package name="zip" version="0:2-1" arch="i386">
42.633 + <requires name="zip-libs" relation="EQ" version="0:2-1"/>
42.634 + </package>
42.635 + <package name="zip-libs" version="0:2-1" arch="i386">
42.636 + <provides name="libzip" relation="EQ" version="0:2-1"/>
42.637 + </package>
42.638 + </set>
42.639 + <transaction>
42.640 + <install name="zsh"/>
42.641 + </transaction>
42.642 + <result>
42.643 + <set>
42.644 + <package name="zip" version="0:1-1" arch="i386"/>
42.645 + <package name="zip-libs" version="0:2-1" arch="i386"/>
42.646 + <package name="zsh" version="0:1-1" arch="i386"/>
42.647 + </set>
42.648 + </result>
42.649 + </test>
42.650 +
42.651 + <test name="testUpdateSinglePackageNewRequires">
42.652 + <set name="system">
42.653 + <package name="zsh" version="1-1" arch="i386"/>
42.654 + </set>
42.655 + <set name="repo">
42.656 + <package name="zsh" version="1-3" arch="i386">
42.657 + <requires name="zip"/>
42.658 + </package>
42.659 + <package name="zip" version="1-3" arch="x86_64"/>
42.660 + </set>
42.661 + <transaction>
42.662 + <install name="zsh"/>
42.663 + </transaction>
42.664 + <result>
42.665 + <set>
42.666 + <package name="zsh" version="1-3" arch="i386"/>
42.667 + <package name="zip" version="1-3" arch="x86_64"/>
42.668 + </set>
42.669 + </result>
42.670 + </test>
42.671 +
42.672 + <test name="testUpdateSinglePackageOldRequires">
42.673 + <set name="system">
42.674 + <package name="zsh" version="1-1" arch="i386">
42.675 + <requires name="zip"/>
42.676 + </package>
42.677 + <package name="zip" version="1-3" arch="x86_64"/>
42.678 + </set>
42.679 + <set name="repo">
42.680 + <package name="zsh" version="1-3" arch="i386">
42.681 + <requires name="zip"/>
42.682 + </package>
42.683 + </set>
42.684 + <transaction>
42.685 + <install name="zsh"/>
42.686 + </transaction>
42.687 + <result>
42.688 + <set>
42.689 + <package name="zip" version="1-3" arch="x86_64"/>
42.690 + <package name="zsh" version="1-3" arch="i386"/>
42.691 + </set>
42.692 + </result>
42.693 + </test>
42.694 +
42.695 + <test name="testUpdateSinglePackageOldRequiresGone">
42.696 + <set name="system">
42.697 + <package name="zsh" version="1-1" arch="i386">
42.698 + <requires name="zip"/>
42.699 + </package>
42.700 + <package name="zip" version="1-3" arch="x86_64"/>
42.701 + </set>
42.702 + <set name="repo">
42.703 + <package name="zsh" version="1-3" arch="i386"/>
42.704 + </set>
42.705 + <transaction>
42.706 + <install name="zsh"/>
42.707 + </transaction>
42.708 + <result>
42.709 + <set>
42.710 + <package name="zip" version="1-3" arch="x86_64"/>
42.711 + <package name="zsh" version="1-3" arch="i386"/>
42.712 + </set>
42.713 + </result>
42.714 + </test>
42.715 +
42.716 + <test name="testUpdateSinglePackageObsoletesOldRequirement">
42.717 + <set name="system">
42.718 + <package name="zsh" version="1-1" arch="i386">
42.719 + <requires name="zip"/>
42.720 + </package>
42.721 + <package name="zip" version="1-1" arch="i386"/>
42.722 + </set>
42.723 + <set name="repo">
42.724 + <package name="zsh" version="1-3" arch="i386">
42.725 + <!-- depsolvetests.py actually adds the obsoletes
42.726 + to the installed zsh rather than the new zsh,
42.727 + but I'm assuming that's a bug -->
42.728 + <obsoletes name="zip"/>
42.729 + </package>
42.730 + </set>
42.731 + <transaction>
42.732 + <install name="zsh"/>
42.733 + </transaction>
42.734 + <result>
42.735 + <set>
42.736 + <package name="zsh" version="1-3" arch="i386"/>
42.737 + </set>
42.738 + </result>
42.739 + </test>
42.740 +
42.741 + <test name="testUpdateForConflict">
42.742 + <set name="system">
42.743 + <package name="zip" version="0:1-1" arch="i386"/>
42.744 + </set>
42.745 + <set name="repo">
42.746 + <package name="zsh" version="0:1-1" arch="i386">
42.747 + <conflicts name="zip" relation="LE" version="0:1-1"/>
42.748 + </package>
42.749 + <package name="zip" version="0:2-1" arch="i386"/>
42.750 + </set>
42.751 + <transaction>
42.752 + <install name="zsh"/>
42.753 + </transaction>
42.754 + <result>
42.755 + <set>
42.756 + <package name="zip" version="0:2-1" arch="i386"/>
42.757 + <package name="zsh" version="0:1-1" arch="i386"/>
42.758 + </set>
42.759 + </result>
42.760 + </test>
42.761 +
42.762 + <test name="testUpdateForConflict2">
42.763 + <set name="system">
42.764 + <package name="zip" version="0:1-1" arch="i386">
42.765 + <conflicts name="zsh" relation="LE" version="0:1-1"/>
42.766 + </package>
42.767 + </set>
42.768 + <set name="repo">
42.769 + <package name="zsh" version="0:1-1" arch="i386"/>
42.770 + <package name="zip" version="0:2-1" arch="i386"/>
42.771 + </set>
42.772 + <transaction>
42.773 + <install name="zsh"/>
42.774 + </transaction>
42.775 + <result>
42.776 + <set>
42.777 + <package name="zsh" version="0:1-1" arch="i386"/>
42.778 + <package name="zip" version="0:2-1" arch="i386"/>
42.779 + </set>
42.780 + </result>
42.781 + </test>
42.782 +
42.783 + <test name="testUpdateForConflictProvide">
42.784 + <set name="system">
42.785 + <package name="zip" version="0:1-1" arch="i386">
42.786 + <provides name="zippy" relation="EQ" version="0:1-1"/>
42.787 + </package>
42.788 + </set>
42.789 + <set name="repo">
42.790 + <package name="zsh" version="0:1-1" arch="i386">
42.791 + <conflicts name="zippy" relation="LE" version="0:1-1"/>
42.792 + </package>
42.793 + <package name="zip" version="0:2-1" arch="i386"/>
42.794 + </set>
42.795 + <transaction>
42.796 + <install name="zsh"/>
42.797 + </transaction>
42.798 + <result>
42.799 + <set>
42.800 + <package name="zip" version="0:2-1" arch="i386"/>
42.801 + <package name="zsh" version="0:1-1" arch="i386"/>
42.802 + </set>
42.803 + </result>
42.804 + </test>
42.805 +
42.806 + <test name="testUpdateForConflictProvide2">
42.807 + <set name="system">
42.808 + <package name="zip" version="0:1-1" arch="i386">
42.809 + <conflicts name="zippy" relation="GT" version="0:1-1"/>
42.810 + <conflicts name="zippy" relation="LT" version="0:1-1"/>
42.811 + </package>
42.812 + </set>
42.813 + <set name="repo">
42.814 + <package name="zsh" version="0:1-1" arch="i386">
42.815 + <provides name="zippy" relation="EQ" version="0:2-1"/>
42.816 + </package>
42.817 + <package name="zip" version="0:2-1" arch="i386">
42.818 + <conflicts name="zippy" relation="GT" version="0:2-1"/>
42.819 + <conflicts name="zippy" relation="LT" version="0:2-1"/>
42.820 + </package>
42.821 + </set>
42.822 + <transaction>
42.823 + <install name="zsh"/>
42.824 + </transaction>
42.825 + <result>
42.826 + <set>
42.827 + <package name="zip" version="0:2-1" arch="i386"/>
42.828 + <package name="zsh" version="0:1-1" arch="i386"/>
42.829 + </set>
42.830 + </result>
42.831 + </test>
42.832 +
42.833 + <test name="testEraseSinglePackage">
42.834 + <set name="system">
42.835 + <package name="zsh" version="0:1-1" arch="i386"/>
42.836 + </set>
42.837 + <set name="repo"/>
42.838 + <transaction>
42.839 + <remove name="zsh"/>
42.840 + </transaction>
42.841 + <result>
42.842 + <set/>
42.843 + </result>
42.844 + </test>
42.845 +
42.846 + <test name="testEraseSinglePackageRequiredByOneInstalled">
42.847 + <set name="system">
42.848 + <package name="zippy" version="0:1-1" arch="i386">
42.849 + <requires name="zsh"/>
42.850 + </package>
42.851 + <package name="zsh" version="0:1-1" arch="i386"/>
42.852 + </set>
42.853 + <set name="repo"/>
42.854 + <transaction>
42.855 + <remove name="zsh"/>
42.856 + </transaction>
42.857 + <result>
42.858 + <set/>
42.859 + </result>
42.860 + </test>
42.861 +</tests>
43.1 --- a/test-driver.c Sun Jun 15 23:15:59 2008 -0400
43.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
43.3 @@ -1,458 +0,0 @@
43.4 -#include <stdio.h>
43.5 -#include <string.h>
43.6 -#include <stdarg.h>
43.7 -#include <unistd.h>
43.8 -#include <fcntl.h>
43.9 -#include <errno.h>
43.10 -#include <expat.h>
43.11 -
43.12 -#include "razor.h"
43.13 -
43.14 -#define XML_BUFFER_SIZE 4096
43.15 -
43.16 -static void
43.17 -parse_xml_file(const char *filename,
43.18 - XML_StartElementHandler start,
43.19 - XML_EndElementHandler end,
43.20 - void *data)
43.21 -{
43.22 - XML_Parser parser;
43.23 - char *buffer;
43.24 - int fd, len, err;
43.25 -
43.26 - parser = XML_ParserCreate(NULL);
43.27 - XML_SetElementHandler(parser, start, end);
43.28 - XML_SetUserData(parser, data);
43.29 -
43.30 - fd = open(filename, O_RDONLY);
43.31 - if (fd < 0) {
43.32 - fprintf(stderr, "failed to open %s: %m\n", filename);
43.33 - exit(-1);
43.34 - }
43.35 -
43.36 - while (1) {
43.37 - buffer = XML_GetBuffer(parser, XML_BUFFER_SIZE);
43.38 - len = read(fd, buffer, XML_BUFFER_SIZE);
43.39 - if (len == 0)
43.40 - break;
43.41 - err = XML_ParseBuffer(parser, len, len == 0);
43.42 - if (err == XML_STATUS_ERROR) {
43.43 - fprintf(stderr, "parse error at line %lu:\n%s\n",
43.44 - XML_GetCurrentLineNumber(parser),
43.45 - XML_ErrorString(XML_GetErrorCode(parser)));
43.46 - exit(-1);
43.47 - }
43.48 - }
43.49 -
43.50 - if (fd < 0) {
43.51 - fprintf(stderr, "read: %m\n");
43.52 - exit(-1);
43.53 - }
43.54 -
43.55 - close(fd);
43.56 -}
43.57 -
43.58 -struct test_context {
43.59 - struct razor_set *system_set, *repo_set, *result_set;
43.60 -
43.61 - struct razor_importer *importer;
43.62 - struct razor_set **importer_set;
43.63 -
43.64 - struct razor_transaction *trans;
43.65 -
43.66 - char *install_pkgs[3], *remove_pkgs[3];
43.67 - int n_install_pkgs, n_remove_pkgs;
43.68 -
43.69 - int unsat;
43.70 - int in_result;
43.71 -
43.72 - int debug, errors;
43.73 -};
43.74 -
43.75 -static void
43.76 -get_atts(const char **atts, ...)
43.77 -{
43.78 - va_list ap;
43.79 - const char *name, **ptr;
43.80 - int i;
43.81 -
43.82 - va_start(ap, atts);
43.83 - while (name = va_arg(ap, const char *), name != NULL) {
43.84 - ptr = va_arg(ap, const char **);
43.85 - *ptr = NULL;
43.86 - for (i = 0; atts[i]; i += 2) {
43.87 - if (strcmp(atts[i], name) == 0)
43.88 - *ptr = atts[i + 1];
43.89 - }
43.90 - }
43.91 - va_end(ap);
43.92 -}
43.93 -
43.94 -static enum razor_version_relation
43.95 -parse_relation (const char *rel_str)
43.96 -{
43.97 - if (!rel_str)
43.98 - return -1;
43.99 - if (rel_str[0] == 'L')
43.100 - return rel_str[1] == 'E' ? RAZOR_VERSION_LESS_OR_EQUAL : RAZOR_VERSION_LESS;
43.101 - else if (rel_str[0] == 'G')
43.102 - return rel_str[1] == 'E' ? RAZOR_VERSION_GREATER_OR_EQUAL : RAZOR_VERSION_GREATER;
43.103 - else if (rel_str[0] == 'E' || rel_str[1] == 'Q')
43.104 - return RAZOR_VERSION_EQUAL;
43.105 - else
43.106 - return -1;
43.107 -}
43.108 -
43.109 -static void
43.110 -start_test(struct test_context *ctx, const char **atts)
43.111 -{
43.112 - const char *name = NULL;
43.113 -
43.114 - get_atts(atts, "name", &name, NULL);
43.115 - if (!name) {
43.116 - fprintf(stderr, "Test with no name\n");
43.117 - exit(1);
43.118 - }
43.119 - printf("%s\n", name);
43.120 -}
43.121 -
43.122 -static void
43.123 -end_test(struct test_context *ctx)
43.124 -{
43.125 - if (ctx->system_set) {
43.126 - razor_set_destroy(ctx->system_set);
43.127 - ctx->system_set = NULL;
43.128 - }
43.129 - if (ctx->repo_set) {
43.130 - razor_set_destroy(ctx->repo_set);
43.131 - ctx->repo_set = NULL;
43.132 - }
43.133 - if (ctx->result_set) {
43.134 - razor_set_destroy(ctx->result_set);
43.135 - ctx->result_set = NULL;
43.136 - }
43.137 - if (ctx->trans) {
43.138 - razor_transaction_destroy(ctx->trans);
43.139 - ctx->trans = NULL;
43.140 - }
43.141 -}
43.142 -
43.143 -static void
43.144 -start_set(struct test_context *ctx, const char **atts)
43.145 -{
43.146 - const char *name = NULL;
43.147 -
43.148 - ctx->importer = razor_importer_new();
43.149 - get_atts(atts, "name", &name, NULL);
43.150 - if (!name)
43.151 - ctx->importer_set = &ctx->result_set;
43.152 - else if (!strcmp(name, "system"))
43.153 - ctx->importer_set = &ctx->system_set;
43.154 - else if (!strcmp(name, "repo"))
43.155 - ctx->importer_set = &ctx->repo_set;
43.156 - else {
43.157 - fprintf(stderr, " bad set name '%s'\n", name);
43.158 - exit(1);
43.159 - }
43.160 -}
43.161 -
43.162 -static void
43.163 -end_set(struct test_context *ctx)
43.164 -{
43.165 - *ctx->importer_set = razor_importer_finish(ctx->importer);
43.166 - ctx->importer = NULL;
43.167 -}
43.168 -
43.169 -static void
43.170 -start_package(struct test_context *ctx, const char **atts)
43.171 -{
43.172 - const char *name = NULL, *version = NULL, *arch = NULL;
43.173 -
43.174 - get_atts(atts, "name", &name,
43.175 - "version", &version,
43.176 - "arch", &arch,
43.177 - NULL);
43.178 -
43.179 - if (!name) {
43.180 - fprintf(stderr, " package with no name\n");
43.181 - exit(1);
43.182 - }
43.183 -
43.184 - razor_importer_begin_package(ctx->importer, name, version, arch);
43.185 - razor_importer_add_property(ctx->importer, name,
43.186 - RAZOR_VERSION_EQUAL, version,
43.187 - RAZOR_PROPERTY_PROVIDES);
43.188 -}
43.189 -
43.190 -static void
43.191 -end_package(struct test_context *ctx)
43.192 -{
43.193 - razor_importer_finish_package(ctx->importer);
43.194 -}
43.195 -
43.196 -static void
43.197 -add_property(struct test_context *ctx, enum razor_property_type type, const char *name, enum razor_version_relation rel, const char *version)
43.198 -{
43.199 - razor_importer_add_property(ctx->importer, name,
43.200 - rel, version, type);
43.201 -}
43.202 -
43.203 -static void
43.204 -check_unsatisfiable_property(struct test_context *ctx,
43.205 - enum razor_property_type type,
43.206 - const char *name,
43.207 - enum razor_version_relation rel,
43.208 - const char *version)
43.209 -{
43.210 - static const char *relation_string[] = { "<", "<=", "=", ">=", ">" };
43.211 -
43.212 - if (!version)
43.213 - version = "";
43.214 -
43.215 - if (razor_transaction_unsatisfied_property(ctx->trans,
43.216 - name, rel, version, type))
43.217 - return;
43.218 -
43.219 - fprintf(stderr, " didn't get unsatisfiable '%s %s %s'\n",
43.220 - name, relation_string[rel], version);
43.221 - ctx->errors++;
43.222 -}
43.223 -
43.224 -static void
43.225 -start_property(struct test_context *ctx, enum razor_property_type type, const char **atts)
43.226 -{
43.227 - const char *name = NULL, *rel_str = NULL, *version = NULL;
43.228 - enum razor_version_relation rel;
43.229 -
43.230 - get_atts(atts, "name", &name, "relation", &rel_str, "version", &version, NULL);
43.231 - if (name == NULL) {
43.232 - fprintf(stderr, " no name specified for property\n");
43.233 - exit(1);
43.234 - }
43.235 - if (version) {
43.236 - rel = parse_relation(rel_str);
43.237 - if (rel == -1) {
43.238 - fprintf(stderr, " bad or missing version relation for property %s\n", name);
43.239 - exit(1);
43.240 - }
43.241 - } else
43.242 - rel = RAZOR_VERSION_EQUAL;
43.243 -
43.244 - if (ctx->unsat)
43.245 - check_unsatisfiable_property(ctx, type, name, rel, version);
43.246 - else
43.247 - add_property(ctx, type, name, rel, version);
43.248 -}
43.249 -
43.250 -static void
43.251 -start_transaction(struct test_context *ctx, const char **atts)
43.252 -{
43.253 - ctx->n_install_pkgs = 0;
43.254 - ctx->n_remove_pkgs = 0;
43.255 -}
43.256 -
43.257 -static void
43.258 -end_transaction(struct test_context *ctx)
43.259 -{
43.260 - struct razor_package *pkg;
43.261 - int errors, i;
43.262 -
43.263 - ctx->trans = razor_transaction_create(ctx->system_set, ctx->repo_set);
43.264 - for (i = 0; i < ctx->n_install_pkgs; i++) {
43.265 - pkg = razor_set_get_package(ctx->repo_set,
43.266 - ctx->install_pkgs[i]);
43.267 - razor_transaction_install_package(ctx->trans, pkg);
43.268 - }
43.269 - for (i = 0; i < ctx->n_remove_pkgs; i++) {
43.270 - pkg = razor_set_get_package(ctx->repo_set,
43.271 - ctx->remove_pkgs[i]);
43.272 - razor_transaction_remove_package(ctx->trans, pkg);
43.273 - }
43.274 -
43.275 - errors = razor_transaction_resolve(ctx->trans);
43.276 - printf("\n");
43.277 -
43.278 - while (ctx->n_install_pkgs--)
43.279 - free(ctx->install_pkgs[ctx->n_install_pkgs]);
43.280 - while (ctx->n_remove_pkgs--)
43.281 - free(ctx->remove_pkgs[ctx->n_remove_pkgs]);
43.282 -
43.283 - if (!errors) {
43.284 - struct razor_set *new;
43.285 - new = razor_transaction_finish(ctx->trans);
43.286 - ctx->system_set = new;
43.287 - }
43.288 -}
43.289 -
43.290 -static void
43.291 -start_install_or_update(struct test_context *ctx, const char **atts)
43.292 -{
43.293 - const char *name = NULL;
43.294 -
43.295 - get_atts(atts, "name", &name, NULL);
43.296 - if (!name) {
43.297 - fprintf(stderr, " install/update with no name\n");
43.298 - exit(1);
43.299 - }
43.300 -
43.301 - ctx->install_pkgs[ctx->n_install_pkgs++] = strdup(name);
43.302 -}
43.303 -
43.304 -static void
43.305 -start_remove(struct test_context *ctx, const char **atts)
43.306 -{
43.307 - const char *name = NULL;
43.308 -
43.309 - get_atts(atts, "name", &name, NULL);
43.310 - if (!name) {
43.311 - fprintf(stderr, " remove with no name\n");
43.312 - exit(1);
43.313 - }
43.314 -
43.315 - ctx->remove_pkgs[ctx->n_remove_pkgs++] = strdup(name);
43.316 -}
43.317 -
43.318 -static void
43.319 -start_result(struct test_context *ctx, const char **atts)
43.320 -{
43.321 - ctx->in_result = 1;
43.322 -}
43.323 -
43.324 -static void
43.325 -diff_callback(const char *name,
43.326 - const char *old_version,
43.327 - const char *new_version,
43.328 - const char *arch,
43.329 - void *data)
43.330 -{
43.331 - struct test_context *ctx = data;
43.332 -
43.333 - ctx->errors++;
43.334 - if (old_version) {
43.335 - fprintf(stderr, " result set should not contain %s %s\n",
43.336 - name, old_version);
43.337 - } else {
43.338 - fprintf(stderr, " result set should contain %s %s\n",
43.339 - name, new_version);
43.340 - }
43.341 -}
43.342 -
43.343 -static void
43.344 -end_result(struct test_context *ctx)
43.345 -{
43.346 - ctx->in_result = 0;
43.347 -
43.348 - if (ctx->result_set) {
43.349 - if (!ctx->system_set)
43.350 - ctx->system_set = razor_set_create();
43.351 - razor_set_diff(ctx->system_set, ctx->result_set,
43.352 - diff_callback, ctx);
43.353 - }
43.354 -}
43.355 -
43.356 -static void
43.357 -start_unsatisfiable(struct test_context *ctx, const char **atts)
43.358 -{
43.359 - if (ctx->result_set) {
43.360 - fprintf(stderr, "Expected to fail, but didn't\n");
43.361 - exit(1);
43.362 - }
43.363 -
43.364 - ctx->unsat = 1;
43.365 -}
43.366 -
43.367 -static void
43.368 -end_unsatisfiable(struct test_context *ctx)
43.369 -{
43.370 - ctx->unsat = 0;
43.371 -}
43.372 -
43.373 -static void
43.374 -start_test_element(void *data, const char *element, const char **atts)
43.375 -{
43.376 - struct test_context *ctx = data;
43.377 -
43.378 - if (strcmp(element, "tests") == 0) {
43.379 - ;
43.380 - } else if (strcmp(element, "test") == 0) {
43.381 - start_test(ctx, atts);
43.382 - } else if (strcmp(element, "set") == 0) {
43.383 - start_set(ctx, atts);
43.384 - } else if (strcmp(element, "transaction") == 0) {
43.385 - start_transaction(ctx, atts);
43.386 - } else if (strcmp(element, "install") == 0) {
43.387 - start_install_or_update(ctx, atts);
43.388 - } else if (strcmp(element, "install") == 0) {
43.389 - start_install_or_update(ctx, atts);
43.390 - } else if (strcmp(element, "remove") == 0) {
43.391 - start_remove(ctx, atts);
43.392 - } else if (strcmp(element, "result") == 0) {
43.393 - start_result(ctx, atts);
43.394 - } else if (strcmp(element, "unsatisfiable") == 0) {
43.395 - start_unsatisfiable(ctx, atts);
43.396 - } else if (strcmp(element, "package") == 0) {
43.397 - start_package(ctx, atts);
43.398 - } else if (strcmp(element, "requires") == 0) {
43.399 - start_property(ctx, RAZOR_PROPERTY_REQUIRES, atts);
43.400 - } else if (strcmp(element, "provides") == 0) {
43.401 - start_property(ctx, RAZOR_PROPERTY_PROVIDES, atts);
43.402 - } else if (strcmp(element, "conflicts") == 0) {
43.403 - start_property(ctx, RAZOR_PROPERTY_CONFLICTS, atts);
43.404 - } else if (strcmp(element, "obsoletes") == 0) {
43.405 - start_property(ctx, RAZOR_PROPERTY_OBSOLETES, atts);
43.406 - } else {
43.407 - fprintf(stderr, "Unrecognized element '%s'\n", element);
43.408 - exit(1);
43.409 - }
43.410 -}
43.411 -
43.412 -static void
43.413 -end_test_element (void *data, const char *element)
43.414 -{
43.415 - struct test_context *ctx = data;
43.416 -
43.417 - if (strcmp(element, "test") == 0) {
43.418 - end_test(ctx);
43.419 - } else if (strcmp(element, "set") == 0) {
43.420 - end_set(ctx);
43.421 - } else if (strcmp(element, "package") == 0) {
43.422 - end_package(ctx);
43.423 - } else if (strcmp(element, "transaction") == 0) {
43.424 - end_transaction(ctx);
43.425 - } else if (strcmp(element, "result") == 0) {
43.426 - end_result(ctx);
43.427 - } else if (strcmp(element, "unsatisfiable") == 0) {
43.428 - end_unsatisfiable(ctx);
43.429 - }
43.430 -}
43.431 -
43.432 -int main(int argc, char *argv[])
43.433 -{
43.434 - struct test_context ctx;
43.435 - const char *test_file;
43.436 -
43.437 - memset(&ctx, 0, sizeof ctx);
43.438 -
43.439 - if (argc > 3) {
43.440 - fprintf(stderr, "usage: %s [-d] [TESTS-FILE]\n", argv[0]);
43.441 - exit(-1);
43.442 - }
43.443 -
43.444 - if (argc >= 2 && !strcmp (argv[1], "-d")) {
43.445 - ctx.debug = 1;
43.446 - argc--;
43.447 - argv++;
43.448 - }
43.449 - if (argc == 2)
43.450 - test_file = argv[1];
43.451 - else
43.452 - test_file = "test.xml";
43.453 -
43.454 - parse_xml_file(test_file, start_test_element, end_test_element, &ctx);
43.455 -
43.456 - if (ctx.errors) {
43.457 - fprintf(stderr, "\n%d errors\n", ctx.errors);
43.458 - return 1;
43.459 - } else
43.460 - return 0;
43.461 -}
44.1 --- a/test.xml Sun Jun 15 23:15:59 2008 -0400
44.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
44.3 @@ -1,858 +0,0 @@
44.4 -<tests>
44.5 -
44.6 - <test name="testEmpty">
44.7 - <set name="system"/>
44.8 - <set name="repo">
44.9 - <package name="zsh" version="1-1" arch="i386"/>
44.10 - </set>
44.11 - <transaction>
44.12 - <install name="zsh"/>
44.13 - <remove name="zsh"/>
44.14 - </transaction>
44.15 - <result>
44.16 - <set/>
44.17 - </result>
44.18 - </test>
44.19 -
44.20 - <test name="testInstallSinglePackageNoRequires">
44.21 - <set name="system"/>
44.22 - <set name="repo">
44.23 - <package name="zsh" version="1-1" arch="i386"/>
44.24 - </set>
44.25 - <transaction>
44.26 - <install name="zsh"/>
44.27 - </transaction>
44.28 - <result>
44.29 - <set>
44.30 - <package name="zsh" version="1-1" arch="i386"/>
44.31 - </set>
44.32 - </result>
44.33 - </test>
44.34 -
44.35 - <test name="testInstallSinglePackageRequireNotProvided">
44.36 - <set name="system"/>
44.37 - <set name="repo">
44.38 - <package name="zsh" version="1-1" arch="i386">
44.39 - <requires name="zip"/>
44.40 - </package>
44.41 - </set>
44.42 - <transaction>
44.43 - <install name="zsh"/>
44.44 - </transaction>
44.45 - <result>
44.46 - <unsatisfiable>
44.47 - <requires name="zip"/>
44.48 - </unsatisfiable>
44.49 - </result>
44.50 - </test>
44.51 -
44.52 - <test name="testInstallSinglePackageRequireInstalled">
44.53 - <set name="system">
44.54 - <package name="zip" version="1-1" arch="i386"/>
44.55 - </set>
44.56 - <set name="repo">
44.57 - <package name="zsh" version="1-1" arch="i386">
44.58 - <requires name="zip"/>
44.59 - </package>
44.60 - </set>
44.61 - <transaction>
44.62 - <install name="zsh"/>
44.63 - </transaction>
44.64 - <result>
44.65 - <set>
44.66 - <package name="zip" version="1-1" arch="i386"/>
44.67 - <package name="zsh" version="1-1" arch="i386"/>
44.68 - </set>
44.69 - </result>
44.70 - </test>
44.71 -
44.72 - <test name="testInstallSinglePackageRequireInstalledRequireNotProvided">
44.73 - <set name="system">
44.74 - <package name="zip" version="1-2" arch="i386"/>
44.75 - </set>
44.76 - <set name="repo">
44.77 - <package name="zsh" version="1-1" arch="i386">
44.78 - <requires name="zip"/>
44.79 - <!-- This may be a bug in the python test: it looks
44.80 - like they meant to have zip require zap, not zsh.
44.81 - But the install succeeds if you do that...
44.82 - -->
44.83 - <requires name="zap"/>
44.84 - </package>
44.85 - </set>
44.86 - <transaction>
44.87 - <install name="zsh"/>
44.88 - </transaction>
44.89 - <result>
44.90 - <unsatisfiable>
44.91 - <requires name="zap"/>
44.92 - </unsatisfiable>
44.93 - </result>
44.94 - </test>
44.95 -
44.96 - <test name="testInstallSinglePackageRequireInstalledRequireInstall">
44.97 - <set name="system">
44.98 - <package name="zip" version="1-3" arch="i386">
44.99 - <requires name="zap"/>
44.100 - </package>
44.101 - </set>
44.102 - <set name="repo">
44.103 - <package name="zsh" version="1-1" arch="i386">
44.104 - <requires name="zip"/>
44.105 - </package>
44.106 - <package name="zap" version="1-2" arch="i386"/>
44.107 - </set>
44.108 - <transaction>
44.109 - <install name="zsh"/>
44.110 - <install name="zap"/>
44.111 - </transaction>
44.112 - <result>
44.113 - <set>
44.114 - <package name="zap" version="1-2" arch="i386"/>
44.115 - <package name="zip" version="1-3" arch="i386"/>
44.116 - <package name="zsh" version="1-1" arch="i386"/>
44.117 - </set>
44.118 - </result>
44.119 - </test>
44.120 -
44.121 - <test name="testInstallSinglePackageRequireVer1NotProvided">
44.122 - <set name="system">
44.123 - <package name="zip" version="1.0-2" arch="i386"/>
44.124 - </set>
44.125 - <set name="repo">
44.126 - <package name="zsh" version="1-1" arch="i386">
44.127 - <requires name="zip" relation="EQ" version="1.3-2"/>
44.128 - </package>
44.129 - </set>
44.130 - <transaction>
44.131 - <install name="zsh"/>
44.132 - </transaction>
44.133 - <result>
44.134 - <unsatisfiable>
44.135 - <requires name="zip" relation="EQ" version="1.3-2"/>
44.136 - </unsatisfiable>
44.137 - </result>
44.138 - </test>
44.139 -
44.140 - <test name="testInstallSinglePackageRequireVer1Installed">
44.141 - <set name="system">
44.142 - <package name="zip" version="1.3-2" arch="i386"/>
44.143 - </set>
44.144 - <set name="repo">
44.145 - <package name="zsh" version="1-1" arch="i386">
44.146 - <requires name="zip" relation="EQ" version="1.3-2"/>
44.147 - </package>
44.148 - </set>
44.149 - <transaction>
44.150 - <install name="zsh"/>
44.151 - </transaction>
44.152 - <result>
44.153 - <set>
44.154 - <package name="zip" version="1.3-2" arch="i386"/>
44.155 - <package name="zsh" version="1-1" arch="i386"/>
44.156 - </set>
44.157 - </result>
44.158 - </test>
44.159 -
44.160 - <test name="testInstallSinglePackageRequireVer2NotProvided">
44.161 - <set name="system">
44.162 - <package name="zip" version="1.3-2" arch="i386"/>
44.163 - </set>
44.164 - <set name="repo">
44.165 - <package name="zsh" version="1-1" arch="i386">
44.166 - <requires name="zip" relation="EQ" version="1.3-4"/>
44.167 - </package>
44.168 - </set>
44.169 - <transaction>
44.170 - <install name="zsh"/>
44.171 - </transaction>
44.172 - <result>
44.173 - <unsatisfiable>
44.174 - <requires name="zip" relation="EQ" version="1.3-4"/>
44.175 - </unsatisfiable>
44.176 - </result>
44.177 - </test>
44.178 -
44.179 - <test name="testInstallSinglePackageRequireVer2Installed">
44.180 - <set name="system">
44.181 - <package name="zip" version="1.3-4" arch="i386"/>
44.182 - </set>
44.183 - <set name="repo">
44.184 - <package name="zsh" version="1-1" arch="i386">
44.185 - <requires name="zip" relation="EQ" version="1.3-4"/>
44.186 - </package>
44.187 - </set>
44.188 - <transaction>
44.189 - <install name="zsh"/>
44.190 - </transaction>
44.191 - <result>
44.192 - <set>
44.193 - <package name="zip" version="1.3-4" arch="i386"/>
44.194 - <package name="zsh" version="1-1" arch="i386"/>
44.195 - </set>
44.196 - </result>
44.197 - </test>
44.198 -
44.199 - <test name="testInstallSinglePackageRequireVer3NotProvided">
44.200 - <set name="system">
44.201 - <package name="zip" version="0:1.3-4" arch="i386"/>
44.202 - </set>
44.203 - <set name="repo">
44.204 - <package name="zsh" version="1-1" arch="i386">
44.205 - <requires name="zip" relation="GE" version="1:1.3-4"/>
44.206 - </package>
44.207 - </set>
44.208 - <transaction>
44.209 - <install name="zsh"/>
44.210 - </transaction>
44.211 - <result>
44.212 - <unsatisfiable>
44.213 - <requires name="zip" relation="GE" version="1:1.3-4"/>
44.214 - </unsatisfiable>
44.215 - </result>
44.216 - </test>
44.217 -
44.218 - <test name="testInstallSinglePackageRequireVer3Installed">
44.219 - <set name="system">
44.220 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.221 - </set>
44.222 - <set name="repo">
44.223 - <package name="zsh" version="1-1" arch="i386">
44.224 - <requires name="zip" relation="GE" version="2:1.3-4"/>
44.225 - </package>
44.226 - </set>
44.227 - <transaction>
44.228 - <install name="zsh"/>
44.229 - </transaction>
44.230 - <result>
44.231 - <set>
44.232 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.233 - <package name="zsh" version="1-1" arch="i386"/>
44.234 - </set>
44.235 - </result>
44.236 - </test>
44.237 -
44.238 - <test name="testInstallSinglePackageRequireVer4NotProvided">
44.239 - <set name="system">
44.240 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.241 - </set>
44.242 - <set name="repo">
44.243 - <package name="zsh" version="1-1" arch="i386">
44.244 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.245 - </package>
44.246 - </set>
44.247 - <transaction>
44.248 - <install name="zsh"/>
44.249 - </transaction>
44.250 - <result>
44.251 - <unsatisfiable>
44.252 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.253 - </unsatisfiable>
44.254 - </result>
44.255 - </test>
44.256 -
44.257 - <test name="testInstallSinglePackageRequireVer4_1Installed">
44.258 - <set name="system">
44.259 - <package name="zip" version="2:1.0-4" arch="i386"/>
44.260 - </set>
44.261 - <set name="repo">
44.262 - <package name="zsh" version="1-1" arch="i386">
44.263 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.264 - </package>
44.265 - </set>
44.266 - <transaction>
44.267 - <install name="zsh"/>
44.268 - </transaction>
44.269 - <result>
44.270 - <set>
44.271 - <package name="zip" version="2:1.0-4" arch="i386"/>
44.272 - <package name="zsh" version="1-1" arch="i386"/>
44.273 - </set>
44.274 - </result>
44.275 - </test>
44.276 -
44.277 - <test name="testInstallSinglePackageRequireVer4_2Installed">
44.278 - <set name="system">
44.279 - <package name="zip" version="2:1.3-3" arch="i386"/>
44.280 - </set>
44.281 - <set name="repo">
44.282 - <package name="zsh" version="1-1" arch="i386">
44.283 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.284 - </package>
44.285 - </set>
44.286 - <transaction>
44.287 - <install name="zsh"/>
44.288 - </transaction>
44.289 - <result>
44.290 - <set>
44.291 - <package name="zip" version="2:1.3-3" arch="i386"/>
44.292 - <package name="zsh" version="1-1" arch="i386"/>
44.293 - </set>
44.294 - </result>
44.295 - </test>
44.296 -
44.297 - <test name="testInstallSinglePackageRequireVer4_3Installed">
44.298 - <set name="system">
44.299 - <package name="zip" version="1.3-4" arch="i386"/>
44.300 - </set>
44.301 - <set name="repo">
44.302 - <package name="zsh" version="1-1" arch="i386">
44.303 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.304 - </package>
44.305 - </set>
44.306 - <transaction>
44.307 - <install name="zsh"/>
44.308 - </transaction>
44.309 - <result>
44.310 - <set>
44.311 - <package name="zip" version="1.3-4" arch="i386"/>
44.312 - <package name="zsh" version="1-1" arch="i386"/>
44.313 - </set>
44.314 - </result>
44.315 - </test>
44.316 -
44.317 - <test name="testInstallSinglePackageRequireVer4_4Installed">
44.318 - <set name="system">
44.319 - <package name="zip" version="1:1.3-4" arch="i386"/>
44.320 - </set>
44.321 - <set name="repo">
44.322 - <package name="zsh" version="1-1" arch="i386">
44.323 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.324 - </package>
44.325 - </set>
44.326 - <transaction>
44.327 - <install name="zsh"/>
44.328 - </transaction>
44.329 - <result>
44.330 - <set>
44.331 - <package name="zip" version="1:1.3-4" arch="i386"/>
44.332 - <package name="zsh" version="1-1" arch="i386"/>
44.333 - </set>
44.334 - </result>
44.335 - </test>
44.336 -
44.337 - <test name="testInstallSinglePackageRequireVer4_5Installed">
44.338 - <set name="system">
44.339 - <package name="zip" version="2:0.3-4" arch="i386"/>
44.340 - </set>
44.341 - <set name="repo">
44.342 - <package name="zsh" version="1-1" arch="i386">
44.343 - <requires name="zip" relation="LT" version="2:1.3-4"/>
44.344 - </package>
44.345 - </set>
44.346 - <transaction>
44.347 - <install name="zsh"/>
44.348 - </transaction>
44.349 - <result>
44.350 - <set>
44.351 - <package name="zip" version="2:0.3-4" arch="i386"/>
44.352 - <package name="zsh" version="1-1" arch="i386"/>
44.353 - </set>
44.354 - </result>
44.355 - </test>
44.356 -
44.357 - <test name="testInstallSinglePackageRequireXtraBadVer">
44.358 - <set name="system">
44.359 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.360 - </set>
44.361 - <set name="repo">
44.362 - <package name="zsh" version="1-1" arch="i386">
44.363 - <requires name="zip" relation="EQ" version="2:1.3-4"/>
44.364 - <requires name="zap" relation="EQ" version="2:1.3-4"/>
44.365 - </package>
44.366 - <package name="zap" version="0:1.3-4" arch="i386"/>
44.367 - </set>
44.368 - <transaction>
44.369 - <install name="zsh"/>
44.370 - </transaction>
44.371 - <result>
44.372 - <unsatisfiable>
44.373 - <requires name="zap" relation="EQ" version="2:1.3-4"/>
44.374 - </unsatisfiable>
44.375 - </result>
44.376 - </test>
44.377 -
44.378 - <test name="testInstallSinglePackageRequireXtra">
44.379 - <set name="system">
44.380 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.381 - </set>
44.382 - <set name="repo">
44.383 - <package name="zsh" version="1-1" arch="i386">
44.384 - <requires name="zip" relation="EQ" version="2:1.3-4"/>
44.385 - <requires name="zap" relation="EQ" version="4:2.6-8"/>
44.386 - </package>
44.387 - <package name="zap" version="4:2.6-8" arch="i386"/>
44.388 - </set>
44.389 - <transaction>
44.390 - <install name="zsh"/>
44.391 - </transaction>
44.392 - <result>
44.393 - <set>
44.394 - <package name="zap" version="4:2.6-8" arch="i386"/>
44.395 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.396 - <package name="zsh" version="1-1" arch="i386"/>
44.397 - </set>
44.398 - </result>
44.399 - </test>
44.400 -
44.401 - <test name="testInstallSinglePackageRequireInstalledRequireXtra">
44.402 - <set name="system">
44.403 - <package name="zip" version="2:1.3-4" arch="i386">
44.404 - <requires name="zap" relation="EQ" version="4:2.6-8"/>
44.405 - </package>
44.406 - </set>
44.407 - <set name="repo">
44.408 - <package name="zsh" version="1-1" arch="i386">
44.409 - <requires name="zip" relation="EQ" version="2:1.3-4"/>
44.410 - </package>
44.411 - <!-- This may be a bug in the python test; it doesn't
44.412 - actually matter whether or not zap is available
44.413 - -->
44.414 - <package name="zap" version="4:2.6-8" arch="i386"/>
44.415 - </set>
44.416 - <transaction>
44.417 - <install name="zsh"/>
44.418 - </transaction>
44.419 - <result>
44.420 - <set>
44.421 - <package name="zip" version="2:1.3-4" arch="i386"/>
44.422 - <package name="zsh" version="1-1" arch="i386"/>
44.423 - </set>
44.424 - </result>
44.425 - </test>
44.426 -
44.427 - <test name="testInstallSinglePackageRequireUpgradeRequireXtraErr">
44.428 - <set name="system">
44.429 - <package name="zip" version="2:1.3-4" arch="i386">
44.430 - <requires name="zap" relation="EQ" version="2:1.3-3"/>
44.431 - </package>
44.432 - </set>
44.433 - <set name="repo">
44.434 - <package name="zsh" version="1-1" arch="i386">
44.435 - <requires name="zip" relation="EQ" version="4:2.6-8"/>
44.436 - </package>
44.437 - <package name="zip" version="4:2.6-8" arch="i386">
44.438 - <requires name="zap" relation="EQ" version="2:1.3-4"/>
44.439 - </package>
44.440 - <package name="zap" version="2:1.3-4" arch="i386">
44.441 - <requires name="zsh" relation="EQ" version="2:4-8"/>
44.442 - </package>
44.443 - </set>
44.444 - <transaction>
44.445 - <install name="zsh"/>
44.446 - </transaction>
44.447 - <result>
44.448 - <unsatisfiable>
44.449 - <requires name="zsh" relation="EQ" version="2:4-8"/>
44.450 - </unsatisfiable>
44.451 - </result>
44.452 - </test>
44.453 -
44.454 - <test name="testInstallSinglePackageRequireUpgradeRequireXtraOk">
44.455 - <set name="system">
44.456 - <package name="zip" version="2:1.3-4" arch="i386">
44.457 - <requires name="zap" relation="EQ" version="2:1.3-3"/>
44.458 - </package>
44.459 - </set>
44.460 - <set name="repo">
44.461 - <package name="zsh" version="1-1" arch="i386">
44.462 - <requires name="zip" relation="EQ" version="4:2.6-8"/>
44.463 - </package>
44.464 - <package name="zip" version="4:2.6-8" arch="i386">
44.465 - <requires name="zap" relation="EQ" version="2:1.3-4"/>
44.466 - </package>
44.467 - <package name="zap" version="2:1.3-4" arch="i386"/>
44.468 - </set>
44.469 - <transaction>
44.470 - <install name="zsh"/>
44.471 - </transaction>
44.472 - <result>
44.473 - <set>
44.474 - <package name="zap" version="2:1.3-4" arch="i386"/>
44.475 - <package name="zip" version="4:2.6-8" arch="i386"/>
44.476 - <package name="zsh" version="1-1" arch="i386"/>
44.477 - </set>
44.478 - </result>
44.479 - </test>
44.480 -
44.481 - <test name="testInstallSinglePackageRequireMultiXtra">
44.482 - <set name="system"/>
44.483 - <set name="repo">
44.484 - <package name="zsh" version="1-1" arch="i386">
44.485 - <requires name="zip" relation="EQ" version="4:2.6-8"/>
44.486 - </package>
44.487 - <package name="zip" version="4:2.6-8" arch="i386">
44.488 - <requires name="zap" relation="EQ" version="2:1.3-4"/>
44.489 - </package>
44.490 - <package name="zap" version="2:1.3-4" arch="i386"/>
44.491 - </set>
44.492 - <transaction>
44.493 - <install name="zsh"/>
44.494 - </transaction>
44.495 - <result>
44.496 - <set>
44.497 - <package name="zap" version="2:1.3-4" arch="i386"/>
44.498 - <package name="zip" version="4:2.6-8" arch="i386"/>
44.499 - <package name="zsh" version="1-1" arch="i386"/>
44.500 - </set>
44.501 - </result>
44.502 - </test>
44.503 -
44.504 - <test name="testInstallSinglePackageRequireInstalledMultiLib">
44.505 - <set name="system">
44.506 - <package name="zip" version="1-3" arch="i386"/>
44.507 - </set>
44.508 - <set name="repo">
44.509 - <package name="zsh" version="1-1" arch="x86_64">
44.510 - <requires name="zip"/>
44.511 - </package>
44.512 - <package name="zip" version="1-3" arch="x86_64"/>
44.513 - </set>
44.514 - <transaction>
44.515 - <install name="zsh"/>
44.516 - </transaction>
44.517 - <result>
44.518 - <set>
44.519 - <package name="zip" version="1-3" arch="i386"/>
44.520 - <package name="zsh" version="1-1" arch="x86_64"/>
44.521 - </set>
44.522 - </result>
44.523 - </test>
44.524 -
44.525 - <test name="testInstallSinglePackageRequireXtra1MultiLib">
44.526 - <set name="system"/>
44.527 - <set name="repo">
44.528 - <package name="zsh" version="1-1" arch="x86_64">
44.529 - <requires name="zip"/>
44.530 - </package>
44.531 - <package name="zip" version="1-3" arch="i386"/>
44.532 - </set>
44.533 - <transaction>
44.534 - <install name="zsh"/>
44.535 - </transaction>
44.536 - <result>
44.537 - <set>
44.538 - <package name="zip" version="1-3" arch="i386"/>
44.539 - <package name="zsh" version="1-1" arch="x86_64"/>
44.540 - </set>
44.541 - </result>
44.542 - </test>
44.543 -
44.544 - <test name="testInstallSinglePackageRequireXtra2_64MultiLib">
44.545 - <set name="system"/>
44.546 - <set name="repo">
44.547 - <package name="zsh" version="1-1" arch="x86_64">
44.548 - <requires name="zip"/>
44.549 - </package>
44.550 - <package name="zip" version="1-3" arch="i386"/>
44.551 - <package name="zip" version="1-3" arch="x86_64"/>
44.552 - </set>
44.553 - <transaction>
44.554 - <install name="zsh"/>
44.555 - </transaction>
44.556 - <result>
44.557 - <set>
44.558 - <package name="zsh" version="1-1" arch="x86_64"/>
44.559 - <package name="zip" version="1-3" arch="x86_64"/>
44.560 - </set>
44.561 - </result>
44.562 - </test>
44.563 -
44.564 - <test name="testInstallSinglePackageRequireXtra2_32MultiLib">
44.565 - <set name="system"/>
44.566 - <set name="repo">
44.567 - <package name="zsh" version="1-1" arch="i386">
44.568 - <requires name="zip"/>
44.569 - </package>
44.570 - <package name="zip" version="1-3" arch="i386"/>
44.571 - <package name="zip" version="1-3" arch="x86_64"/>
44.572 - </set>
44.573 - <transaction>
44.574 - <install name="zsh"/>
44.575 - </transaction>
44.576 - <result>
44.577 - <set>
44.578 - <package name="zip" version="1-3" arch="i386"/>
44.579 - <package name="zsh" version="1-1" arch="i386"/>
44.580 - </set>
44.581 - </result>
44.582 - </test>
44.583 -
44.584 - <test name="testUpdateSinglePackage">
44.585 - <set name="system">
44.586 - <package name="zsh" version="1-1" arch="i386"/>
44.587 - </set>
44.588 - <set name="repo">
44.589 - <package name="zsh" version="1-3" arch="i386"/>
44.590 - </set>
44.591 - <transaction>
44.592 - <install name="zsh"/>
44.593 - </transaction>
44.594 - <result>
44.595 - <set>
44.596 - <package name="zsh" version="1-3" arch="i386"/>
44.597 - </set>
44.598 - </result>
44.599 - </test>
44.600 -
44.601 - <test name="testUpdateForDependency">
44.602 - <set name="system">
44.603 - <package name="zip" version="0:1-1" arch="i386"/>
44.604 - </set>
44.605 - <set name="repo">
44.606 - <package name="zsh" version="0:1-1" arch="i386">
44.607 - <requires name="zip" relation="EQ" version="0:2-1"/>
44.608 - </package>
44.609 - <package name="zip" version="0:2-1" arch="i386"/>
44.610 - </set>
44.611 - <transaction>
44.612 - <install name="zsh"/>
44.613 - </transaction>
44.614 - <result>
44.615 - <set>
44.616 - <package name="zip" version="0:2-1" arch="i386"/>
44.617 - <package name="zsh" version="0:1-1" arch="i386"/>
44.618 - </set>
44.619 - </result>
44.620 - </test>
44.621 -
44.622 - <test name="testUpdateSplitPackage">
44.623 - <set name="system">
44.624 - <package name="zip" version="0:1-1" arch="i386">
44.625 - <provides name="libzip" relation="EQ" version="0:1-1"/>
44.626 - </package>
44.627 - </set>
44.628 - <set name="repo">
44.629 - <package name="zsh" version="0:1-1" arch="i386">
44.630 - <requires name="libzip" relation="EQ" version="0:2-1"/>
44.631 - </package>
44.632 - <package name="zip" version="0:2-1" arch="i386">
44.633 - <requires name="zip-libs" relation="EQ" version="0:2-1"/>
44.634 - </package>
44.635 - <package name="zip-libs" version="0:2-1" arch="i386">
44.636 - <provides name="libzip" relation="EQ" version="0:2-1"/>
44.637 - </package>
44.638 - </set>
44.639 - <transaction>
44.640 - <install name="zsh"/>
44.641 - </transaction>
44.642 - <result>
44.643 - <set>
44.644 - <package name="zip" version="0:1-1" arch="i386"/>
44.645 - <package name="zip-libs" version="0:2-1" arch="i386"/>
44.646 - <package name="zsh" version="0:1-1" arch="i386"/>
44.647 - </set>
44.648 - </result>
44.649 - </test>
44.650 -
44.651 - <test name="testUpdateSinglePackageNewRequires">
44.652 - <set name="system">
44.653 - <package name="zsh" version="1-1" arch="i386"/>
44.654 - </set>
44.655 - <set name="repo">
44.656 - <package name="zsh" version="1-3" arch="i386">
44.657 - <requires name="zip"/>
44.658 - </package>
44.659 - <package name="zip" version="1-3" arch="x86_64"/>
44.660 - </set>
44.661 - <transaction>
44.662 - <install name="zsh"/>
44.663 - </transaction>
44.664 - <result>
44.665 - <set>
44.666 - <package name="zsh" version="1-3" arch="i386"/>
44.667 - <package name="zip" version="1-3" arch="x86_64"/>
44.668 - </set>
44.669 - </result>
44.670 - </test>
44.671 -
44.672 - <test name="testUpdateSinglePackageOldRequires">
44.673 - <set name="system">
44.674 - <package name="zsh" version="1-1" arch="i386">
44.675 - <requires name="zip"/>
44.676 - </package>
44.677 - <package name="zip" version="1-3" arch="x86_64"/>
44.678 - </set>
44.679 - <set name="repo">
44.680 - <package name="zsh" version="1-3" arch="i386">
44.681 - <requires name="zip"/>
44.682 - </package>
44.683 - </set>
44.684 - <transaction>
44.685 - <install name="zsh"/>
44.686 - </transaction>
44.687 - <result>
44.688 - <set>
44.689 - <package name="zip" version="1-3" arch="x86_64"/>
44.690 - <package name="zsh" version="1-3" arch="i386"/>
44.691 - </set>
44.692 - </result>
44.693 - </test>
44.694 -
44.695 - <test name="testUpdateSinglePackageOldRequiresGone">
44.696 - <set name="system">
44.697 - <package name="zsh" version="1-1" arch="i386">
44.698 - <requires name="zip"/>
44.699 - </package>
44.700 - <package name="zip" version="1-3" arch="x86_64"/>
44.701 - </set>
44.702 - <set name="repo">
44.703 - <package name="zsh" version="1-3" arch="i386"/>
44.704 - </set>
44.705 - <transaction>
44.706 - <install name="zsh"/>
44.707 - </transaction>
44.708 - <result>
44.709 - <set>
44.710 - <package name="zip" version="1-3" arch="x86_64"/>
44.711 - <package name="zsh" version="1-3" arch="i386"/>
44.712 - </set>
44.713 - </result>
44.714 - </test>
44.715 -
44.716 - <test name="testUpdateSinglePackageObsoletesOldRequirement">
44.717 - <set name="system">
44.718 - <package name="zsh" version="1-1" arch="i386">
44.719 - <requires name="zip"/>
44.720 - </package>
44.721 - <package name="zip" version="1-1" arch="i386"/>
44.722 - </set>
44.723 - <set name="repo">
44.724 - <package name="zsh" version="1-3" arch="i386">
44.725 - <!-- depsolvetests.py actually adds the obsoletes
44.726 - to the installed zsh rather than the new zsh,
44.727 - but I'm assuming that's a bug -->
44.728 - <obsoletes name="zip"/>
44.729 - </package>
44.730 - </set>
44.731 - <transaction>
44.732 - <install name="zsh"/>
44.733 - </transaction>
44.734 - <result>
44.735 - <set>
44.736 - <package name="zsh" version="1-3" arch="i386"/>
44.737 - </set>
44.738 - </result>
44.739 - </test>
44.740 -
44.741 - <test name="testUpdateForConflict">
44.742 - <set name="system">
44.743 - <package name="zip" version="0:1-1" arch="i386"/>
44.744 - </set>
44.745 - <set name="repo">
44.746 - <package name="zsh" version="0:1-1" arch="i386">
44.747 - <conflicts name="zip" relation="LE" version="0:1-1"/>
44.748 - </package>
44.749 - <package name="zip" version="0:2-1" arch="i386"/>
44.750 - </set>
44.751 - <transaction>
44.752 - <install name="zsh"/>
44.753 - </transaction>
44.754 - <result>
44.755 - <set>
44.756 - <package name="zip" version="0:2-1" arch="i386"/>
44.757 - <package name="zsh" version="0:1-1" arch="i386"/>
44.758 - </set>
44.759 - </result>
44.760 - </test>
44.761 -
44.762 - <test name="testUpdateForConflict2">
44.763 - <set name="system">
44.764 - <package name="zip" version="0:1-1" arch="i386">
44.765 - <conflicts name="zsh" relation="LE" version="0:1-1"/>
44.766 - </package>
44.767 - </set>
44.768 - <set name="repo">
44.769 - <package name="zsh" version="0:1-1" arch="i386"/>
44.770 - <package name="zip" version="0:2-1" arch="i386"/>
44.771 - </set>
44.772 - <transaction>
44.773 - <install name="zsh"/>
44.774 - </transaction>
44.775 - <result>
44.776 - <set>
44.777 - <package name="zsh" version="0:1-1" arch="i386"/>
44.778 - <package name="zip" version="0:2-1" arch="i386"/>
44.779 - </set>
44.780 - </result>
44.781 - </test>
44.782 -
44.783 - <test name="testUpdateForConflictProvide">
44.784 - <set name="system">
44.785 - <package name="zip" version="0:1-1" arch="i386">
44.786 - <provides name="zippy" relation="EQ" version="0:1-1"/>
44.787 - </package>
44.788 - </set>
44.789 - <set name="repo">
44.790 - <package name="zsh" version="0:1-1" arch="i386">
44.791 - <conflicts name="zippy" relation="LE" version="0:1-1"/>
44.792 - </package>
44.793 - <package name="zip" version="0:2-1" arch="i386"/>
44.794 - </set>
44.795 - <transaction>
44.796 - <install name="zsh"/>
44.797 - </transaction>
44.798 - <result>
44.799 - <set>
44.800 - <package name="zip" version="0:2-1" arch="i386"/>
44.801 - <package name="zsh" version="0:1-1" arch="i386"/>
44.802 - </set>
44.803 - </result>
44.804 - </test>
44.805 -
44.806 - <test name="testUpdateForConflictProvide2">
44.807 - <set name="system">
44.808 - <package name="zip" version="0:1-1" arch="i386">
44.809 - <conflicts name="zippy" relation="GT" version="0:1-1"/>
44.810 - <conflicts name="zippy" relation="LT" version="0:1-1"/>
44.811 - </package>
44.812 - </set>
44.813 - <set name="repo">
44.814 - <package name="zsh" version="0:1-1" arch="i386">
44.815 - <provides name="zippy" relation="EQ" version="0:2-1"/>
44.816 - </package>
44.817 - <package name="zip" version="0:2-1" arch="i386">
44.818 - <conflicts name="zippy" relation="GT" version="0:2-1"/>
44.819 - <conflicts name="zippy" relation="LT" version="0:2-1"/>
44.820 - </package>
44.821 - </set>
44.822 - <transaction>
44.823 - <install name="zsh"/>
44.824 - </transaction>
44.825 - <result>
44.826 - <set>
44.827 - <package name="zip" version="0:2-1" arch="i386"/>
44.828 - <package name="zsh" version="0:1-1" arch="i386"/>
44.829 - </set>
44.830 - </result>
44.831 - </test>
44.832 -
44.833 - <test name="testEraseSinglePackage">
44.834 - <set name="system">
44.835 - <package name="zsh" version="0:1-1" arch="i386"/>
44.836 - </set>
44.837 - <set name="repo"/>
44.838 - <transaction>
44.839 - <remove name="zsh"/>
44.840 - </transaction>
44.841 - <result>
44.842 - <set/>
44.843 - </result>
44.844 - </test>
44.845 -
44.846 - <test name="testEraseSinglePackageRequiredByOneInstalled">
44.847 - <set name="system">
44.848 - <package name="zippy" version="0:1-1" arch="i386">
44.849 - <requires name="zsh"/>
44.850 - </package>
44.851 - <package name="zsh" version="0:1-1" arch="i386"/>
44.852 - </set>
44.853 - <set name="repo"/>
44.854 - <transaction>
44.855 - <remove name="zsh"/>
44.856 - </transaction>
44.857 - <result>
44.858 - <set/>
44.859 - </result>
44.860 - </test>
44.861 -</tests>
45.1 --- a/types.c Sun Jun 15 23:15:59 2008 -0400
45.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
45.3 @@ -1,246 +0,0 @@
45.4 -#include <stdlib.h>
45.5 -#include <string.h>
45.6 -
45.7 -#include "types.h"
45.8 -
45.9 -void
45.10 -array_init(struct array *array)
45.11 -{
45.12 - memset(array, 0, sizeof *array);
45.13 -}
45.14 -
45.15 -void
45.16 -array_release(struct array *array)
45.17 -{
45.18 - free(array->data);
45.19 -}
45.20 -
45.21 -void *
45.22 -array_add(struct array *array, int size)
45.23 -{
45.24 - int alloc;
45.25 - void *data, *p;
45.26 -
45.27 - if (array->alloc > 0)
45.28 - alloc = array->alloc;
45.29 - else
45.30 - alloc = 16;
45.31 -
45.32 - while (alloc < array->size + size)
45.33 - alloc *= 2;
45.34 -
45.35 - if (array->alloc < alloc) {
45.36 - data = realloc(array->data, alloc);
45.37 - if (data == NULL)
45.38 - return 0;
45.39 - array->data = data;
45.40 - array->alloc = alloc;
45.41 - }
45.42 -
45.43 - p = array->data + array->size;
45.44 - array->size += size;
45.45 -
45.46 - return p;
45.47 -}
45.48 -
45.49 -/* RAZOR_IMMEDIATE and RAZOR_ENTRY_LAST must have the same value */
45.50 -#define RAZOR_ENTRY_LAST 0x80
45.51 -#define RAZOR_IMMEDIATE 0x80
45.52 -#define RAZOR_EMPTY_LIST 0xff
45.53 -
45.54 -void
45.55 -list_set_empty(struct list_head *head)
45.56 -{
45.57 - head->list_ptr = ~0;
45.58 - head->flags = RAZOR_EMPTY_LIST;
45.59 -}
45.60 -
45.61 -void
45.62 -list_set_ptr(struct list_head *head, uint32_t ptr)
45.63 -{
45.64 - head->list_ptr = ptr;
45.65 - head->flags = 0;
45.66 -}
45.67 -
45.68 -void
45.69 -list_set_array(struct list_head *head, struct array *pool,
45.70 - struct array *items, int force_indirect)
45.71 -{
45.72 - struct list *p;
45.73 -
45.74 - if (!force_indirect) {
45.75 - if (items->size == 0) {
45.76 - list_set_empty(head);
45.77 - return;
45.78 - } else if (items->size == sizeof (uint32_t)) {
45.79 - head->list_ptr = *(uint32_t *) items->data;
45.80 - head->flags = RAZOR_IMMEDIATE;
45.81 - return;
45.82 - }
45.83 - }
45.84 -
45.85 - p = array_add(pool, items->size);
45.86 - memcpy(p, items->data, items->size);
45.87 - p[items->size / sizeof *p - 1].flags = RAZOR_ENTRY_LAST;
45.88 - list_set_ptr(head, p - (struct list *) pool->data);
45.89 -}
45.90 -
45.91 -struct list *
45.92 -list_first(struct list_head *head, struct array *pool)
45.93 -{
45.94 - if (head->flags == RAZOR_EMPTY_LIST)
45.95 - return NULL;
45.96 - else if (head->flags == RAZOR_IMMEDIATE)
45.97 - return (struct list *) head;
45.98 - else
45.99 - return (struct list *) pool->data + head->list_ptr;
45.100 -}
45.101 -
45.102 -struct list *
45.103 -list_next(struct list *list)
45.104 -{
45.105 - if (list->flags)
45.106 - return NULL;
45.107 - return ++list;
45.108 -}
45.109 -
45.110 -void
45.111 -list_remap_pool(struct array *pool, uint32_t *map)
45.112 -{
45.113 - struct list *p, *end;
45.114 -
45.115 - end = pool->data + pool->size;
45.116 - for (p = pool->data; p < end; p++)
45.117 - p->data = map[p->data];
45.118 -}
45.119 -
45.120 -void
45.121 -list_remap_head(struct list_head *head, uint32_t *map)
45.122 -{
45.123 - if (head->flags == RAZOR_IMMEDIATE)
45.124 - head->list_ptr = map[head->list_ptr];
45.125 -}
45.126 -
45.127 -
45.128 -void
45.129 -hashtable_init(struct hashtable *table, struct array *pool)
45.130 -{
45.131 - array_init(&table->buckets);
45.132 - table->pool = pool;
45.133 -}
45.134 -
45.135 -void
45.136 -hashtable_release(struct hashtable *table)
45.137 -{
45.138 - array_release(&table->buckets);
45.139 -}
45.140 -
45.141 -static unsigned int
45.142 -hash_string(const char *key)
45.143 -{
45.144 - const char *p;
45.145 - unsigned int hash = 0;
45.146 -
45.147 - for (p = key; *p; p++)
45.148 - hash = (hash * 617) ^ *p;
45.149 -
45.150 - return hash;
45.151 -}
45.152 -
45.153 -uint32_t
45.154 -hashtable_lookup(struct hashtable *table, const char *key)
45.155 -{
45.156 - unsigned int mask, start, i;
45.157 - uint32_t *b;
45.158 - char *pool;
45.159 -
45.160 - pool = table->pool->data;
45.161 - mask = table->buckets.alloc - 1;
45.162 - start = hash_string(key) * sizeof(uint32_t);
45.163 -
45.164 - for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
45.165 - b = table->buckets.data + ((start + i) & mask);
45.166 -
45.167 - if (*b == 0)
45.168 - return 0;
45.169 -
45.170 - if (strcmp(key, &pool[*b]) == 0)
45.171 - return *b;
45.172 - }
45.173 -
45.174 - return 0;
45.175 -}
45.176 -
45.177 -static void
45.178 -do_insert(struct hashtable *table, uint32_t value)
45.179 -{
45.180 - unsigned int mask, start, i;
45.181 - uint32_t *b;
45.182 - const char *key;
45.183 -
45.184 - key = (char *) table->pool->data + value;
45.185 - mask = table->buckets.alloc - 1;
45.186 - start = hash_string(key) * sizeof(uint32_t);
45.187 -
45.188 - for (i = 0; i < table->buckets.alloc; i += sizeof *b) {
45.189 - b = table->buckets.data + ((start + i) & mask);
45.190 - if (*b == 0) {
45.191 - *b = value;
45.192 - break;
45.193 - }
45.194 - }
45.195 -}
45.196 -
45.197 -static uint32_t
45.198 -add_to_string_pool(struct hashtable *table, const char *key)
45.199 -{
45.200 - int len;
45.201 - char *p;
45.202 -
45.203 - len = strlen(key) + 1;
45.204 - p = array_add(table->pool, len);
45.205 - memcpy(p, key, len);
45.206 -
45.207 - return p - (char *) table->pool->data;
45.208 -}
45.209 -
45.210 -uint32_t
45.211 -hashtable_insert(struct hashtable *table, const char *key)
45.212 -{
45.213 - uint32_t value, *buckets, *b, *end;
45.214 - int alloc;
45.215 -
45.216 - alloc = table->buckets.alloc;
45.217 - array_add(&table->buckets, 4 * sizeof *buckets);
45.218 - if (alloc != table->buckets.alloc) {
45.219 - end = table->buckets.data + alloc;
45.220 - memset(end, 0, table->buckets.alloc - alloc);
45.221 - for (b = table->buckets.data; b < end; b++) {
45.222 - value = *b;
45.223 - if (value != 0) {
45.224 - *b = 0;
45.225 - do_insert(table, value);
45.226 - }
45.227 - }
45.228 - }
45.229 -
45.230 - value = add_to_string_pool(table, key);
45.231 - do_insert (table, value);
45.232 -
45.233 - return value;
45.234 -}
45.235 -
45.236 -uint32_t
45.237 -hashtable_tokenize(struct hashtable *table, const char *string)
45.238 -{
45.239 - uint32_t token;
45.240 -
45.241 - if (string == NULL)
45.242 - string = "";
45.243 -
45.244 - token = hashtable_lookup(table, string);
45.245 - if (token != 0)
45.246 - return token;
45.247 -
45.248 - return hashtable_insert(table, string);
45.249 -}
46.1 --- a/types.h Sun Jun 15 23:15:59 2008 -0400
46.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
46.3 @@ -1,59 +0,0 @@
46.4 -#ifndef _RAZOR_TYPES_H_
46.5 -#define _RAZOR_TYPES_H_
46.6 -
46.7 -#include <stdint.h>
46.8 -
46.9 -struct array {
46.10 - void *data;
46.11 - int size, alloc;
46.12 -};
46.13 -
46.14 -void array_init(struct array *array);
46.15 -void array_release(struct array *array);
46.16 -void *array_add(struct array *array, int size);
46.17 -
46.18 -
46.19 -struct list_head {
46.20 - uint list_ptr : 24;
46.21 - uint flags : 8;
46.22 -};
46.23 -
46.24 -struct list {
46.25 - uint data : 24;
46.26 - uint flags : 8;
46.27 -};
46.28 -
46.29 -void list_set_empty(struct list_head *head);
46.30 -void list_set_ptr(struct list_head *head, uint32_t ptr);
46.31 -void list_set_array(struct list_head *head, struct array *pool, struct array *items, int force_indirect);
46.32 -
46.33 -struct list *list_first(struct list_head *head, struct array *pool);
46.34 -struct list *list_next(struct list *list);
46.35 -
46.36 -void list_remap_pool(struct array *pool, uint32_t *map);
46.37 -void list_remap_head(struct list_head *list, uint32_t *map);
46.38 -
46.39 -
46.40 -struct hashtable {
46.41 - struct array buckets;
46.42 - struct array *pool;
46.43 -};
46.44 -
46.45 -void hashtable_init(struct hashtable *table, struct array *pool);
46.46 -void hashtable_release(struct hashtable *table);
46.47 -uint32_t hashtable_insert(struct hashtable *table, const char *key);
46.48 -uint32_t hashtable_lookup(struct hashtable *table, const char *key);
46.49 -uint32_t hashtable_tokenize(struct hashtable *table, const char *string);
46.50 -
46.51 -
46.52 -struct bitarray {
46.53 - uint32_t *bits;
46.54 -};
46.55 -
46.56 -void bitarray_init(struct bitarray *bitarray, int size, int intial_value);
46.57 -void bitarray_release(struct bitarray *bitarray);
46.58 -void bitarray_set(struct bitarray *bitarray, int bit, int value);
46.59 -int bitarray_get(struct bitarray *bitarray, int bit);
46.60 -
46.61 -
46.62 -#endif /* _RAZOR_TYPES_H_ */
47.1 --- a/util.c Sun Jun 15 23:15:59 2008 -0400
47.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
47.3 @@ -1,167 +0,0 @@
47.4 -#include <limits.h>
47.5 -#include <string.h>
47.6 -#include <sys/stat.h>
47.7 -#include <stdlib.h>
47.8 -#include <stdio.h>
47.9 -#include <stdint.h>
47.10 -#include <unistd.h>
47.11 -
47.12 -#include "razor-internal.h"
47.13 -
47.14 -int
47.15 -razor_create_dir(const char *root, const char *path)
47.16 -{
47.17 - char buffer[PATH_MAX], *p;
47.18 - const char *slash, *next;
47.19 - struct stat buf;
47.20 -
47.21 - /* Create all sub-directories in dir. We know root exists and
47.22 - * is a dir, root does not end in a '/', and path has a
47.23 - * leading '/'. */
47.24 -
47.25 - strcpy(buffer, root);
47.26 - p = buffer + strlen(buffer);
47.27 - slash = path;
47.28 - for (slash = path; *slash != '\0'; slash = next) {
47.29 - next = strchr(slash + 1, '/');
47.30 - if (next == NULL)
47.31 - break;
47.32 -
47.33 - memcpy(p, slash, next - slash);
47.34 - p += next - slash;
47.35 - *p = '\0';
47.36 -
47.37 - if (stat(buffer, &buf) == 0) {
47.38 - if (!S_ISDIR(buf.st_mode)) {
47.39 - fprintf(stderr,
47.40 - "%s exists but is not a directory\n",
47.41 - buffer);
47.42 - return -1;
47.43 - }
47.44 - } else if (mkdir(buffer, 0777) < 0) {
47.45 - fprintf(stderr, "failed to make directory %s: %m\n",
47.46 - buffer);
47.47 - return -1;
47.48 - }
47.49 -
47.50 - /* FIXME: What to do about permissions for dirs we
47.51 - * have to create but are not in the cpio archive? */
47.52 - }
47.53 -
47.54 - return 0;
47.55 -}
47.56 -
47.57 -int
47.58 -razor_write(int fd, const void *data, size_t size)
47.59 -{
47.60 - size_t rest;
47.61 - ssize_t written;
47.62 - const unsigned char *p;
47.63 -
47.64 - rest = size;
47.65 - p = data;
47.66 - while (rest > 0) {
47.67 - written = write(fd, p, rest);
47.68 - if (written < 0) {
47.69 - fprintf(stderr, "write error: %m\n");
47.70 - return -1;
47.71 - }
47.72 - rest -= written;
47.73 - p += written;
47.74 - }
47.75 -
47.76 - return 0;
47.77 -}
47.78 -
47.79 -struct qsort_context {
47.80 - size_t size;
47.81 - razor_compare_with_data_func_t compare;
47.82 - void *data;
47.83 -};
47.84 -
47.85 -static void
47.86 -qsort_swap(void *p1, void *p2, size_t size)
47.87 -{
47.88 - char buffer[size];
47.89 -
47.90 - memcpy(buffer, p1, size);
47.91 - memcpy(p1, p2, size);
47.92 - memcpy(p2, buffer, size);
47.93 -}
47.94 -
47.95 -static void
47.96 -__qsort_with_data(void *base, size_t nelem, uint32_t *map,
47.97 - struct qsort_context *ctx)
47.98 -{
47.99 - void *p, *start, *end, *pivot;
47.100 - uint32_t *mp, *mstart, *mend, tmp;
47.101 - int left, right, result;
47.102 - size_t size = ctx->size;
47.103 -
47.104 - p = base;
47.105 - start = base;
47.106 - end = base + nelem * size;
47.107 - mp = map;
47.108 - mstart = map;
47.109 - mend = map + nelem;
47.110 - pivot = base + (random() % nelem) * size;
47.111 -
47.112 - while (p < end) {
47.113 - result = ctx->compare(p, pivot, ctx->data);
47.114 - if (result < 0) {
47.115 - qsort_swap(p, start, size);
47.116 - tmp = *mp;
47.117 - *mp = *mstart;
47.118 - *mstart = tmp;
47.119 - if (start == pivot)
47.120 - pivot = p;
47.121 - start += size;
47.122 - mstart++;
47.123 - p += size;
47.124 - mp++;
47.125 - } else if (result == 0) {
47.126 - p += size;
47.127 - mp++;
47.128 - } else {
47.129 - end -= size;
47.130 - mend--;
47.131 - qsort_swap(p, end, size);
47.132 - tmp = *mp;
47.133 - *mp = *mend;
47.134 - *mend = tmp;
47.135 - if (end == pivot)
47.136 - pivot = p;
47.137 - }
47.138 - }
47.139 -
47.140 - left = (start - base) / size;
47.141 - right = (base + nelem * size - end) / size;
47.142 - if (left > 1)
47.143 - __qsort_with_data(base, left, map, ctx);
47.144 - if (right > 1)
47.145 - __qsort_with_data(end, right, mend, ctx);
47.146 -}
47.147 -
47.148 -uint32_t *
47.149 -razor_qsort_with_data(void *base, size_t nelem, size_t size,
47.150 - razor_compare_with_data_func_t compare, void *data)
47.151 -{
47.152 - struct qsort_context ctx;
47.153 - uint32_t *map;
47.154 - int i;
47.155 -
47.156 - if (nelem == 0)
47.157 - return NULL;
47.158 -
47.159 - ctx.size = size;
47.160 - ctx.compare = compare;
47.161 - ctx.data = data;
47.162 -
47.163 - map = malloc(nelem * sizeof (uint32_t));
47.164 - for (i = 0; i < nelem; i++)
47.165 - map[i] = i;
47.166 -
47.167 - __qsort_with_data(base, nelem, map, &ctx);
47.168 -
47.169 - return map;
47.170 -}
48.1 --- a/yum.c Sun Jun 15 23:15:59 2008 -0400
48.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
48.3 @@ -1,337 +0,0 @@
48.4 -/*
48.5 - * Copyright (C) 2008 Kristian Høgsberg <krh@redhat.com>
48.6 - * Copyright (C) 2008 Red Hat, Inc
48.7 - *
48.8 - * This program is free software; you can redistribute it and/or modify
48.9 - * it under the terms of the GNU General Public License as published by
48.10 - * the Free Software Foundation; either version 2 of the License, or
48.11 - * (at your option) any later version.
48.12 - *
48.13 - * This program is distributed in the hope that it will be useful,
48.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
48.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48.16 - * GNU General Public License for more details.
48.17 - *
48.18 - * You should have received a copy of the GNU General Public License along
48.19 - * with this program; if not, write to the Free Software Foundation, Inc.,
48.20 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
48.21 - */
48.22 -
48.23 -#define _GNU_SOURCE
48.24 -
48.25 -#include <string.h>
48.26 -#include <stdio.h>
48.27 -#include <sys/stat.h>
48.28 -#include <sys/mman.h>
48.29 -#include <unistd.h>
48.30 -#include <fcntl.h>
48.31 -#include <errno.h>
48.32 -
48.33 -#include <expat.h>
48.34 -#include <zlib.h>
48.35 -#include "razor.h"
48.36 -
48.37 -/* Import a yum filelist as a razor package set. */
48.38 -
48.39 -enum {
48.40 - YUM_STATE_BEGIN,
48.41 - YUM_STATE_PACKAGE_NAME,
48.42 - YUM_STATE_PACKAGE_ARCH,
48.43 - YUM_STATE_CHECKSUM,
48.44 - YUM_STATE_REQUIRES,
48.45 - YUM_STATE_PROVIDES,
48.46 - YUM_STATE_OBSOLETES,
48.47 - YUM_STATE_CONFLICTS,
48.48 - YUM_STATE_FILE
48.49 -};
48.50 -
48.51 -struct yum_context {
48.52 - XML_Parser primary_parser;
48.53 - XML_Parser filelists_parser;
48.54 - XML_Parser current_parser;
48.55 -
48.56 - struct razor_importer *importer;
48.57 - struct import_property_context *current_property_context;
48.58 - char name[256], arch[64], buffer[512], *p;
48.59 - char pkgid[128];
48.60 - int state;
48.61 -};
48.62 -
48.63 -static enum razor_version_relation
48.64 -yum_to_razor_flags (const char *flags)
48.65 -{
48.66 - /* FIXME? */
48.67 - if (!flags)
48.68 - return RAZOR_VERSION_EQUAL;
48.69 -
48.70 - if (flags[0] == 'L') {
48.71 - if (flags[1] == 'T')
48.72 - return RAZOR_VERSION_LESS;
48.73 - else
48.74 - return RAZOR_VERSION_LESS_OR_EQUAL;
48.75 - } else if (flags[0] == 'G') {
48.76 - if (flags[1] == 'T')
48.77 - return RAZOR_VERSION_GREATER;
48.78 - else
48.79 - return RAZOR_VERSION_GREATER_OR_EQUAL;
48.80 - } else
48.81 - return RAZOR_VERSION_EQUAL;
48.82 -}
48.83 -
48.84 -static void
48.85 -yum_primary_start_element(void *data, const char *name, const char **atts)
48.86 -{
48.87 - struct yum_context *ctx = data;
48.88 - const char *n, *epoch, *version, *release, *flags;
48.89 - char buffer[128];
48.90 - int i;
48.91 -
48.92 - if (strcmp(name, "name") == 0) {
48.93 - ctx->state = YUM_STATE_PACKAGE_NAME;
48.94 - ctx->p = ctx->name;
48.95 - } else if (strcmp(name, "arch") == 0) {
48.96 - ctx->state = YUM_STATE_PACKAGE_ARCH;
48.97 - ctx->p = ctx->arch;
48.98 - } else if (strcmp(name, "version") == 0) {
48.99 - epoch = NULL;
48.100 - version = NULL;
48.101 - release = NULL;
48.102 - for (i = 0; atts[i]; i += 2) {
48.103 - if (strcmp(atts[i], "epoch") == 0)
48.104 - epoch = atts[i + 1];
48.105 - else if (strcmp(atts[i], "ver") == 0)
48.106 - version = atts[i + 1];
48.107 - else if (strcmp(atts[i], "rel") == 0)
48.108 - release = atts[i + 1];
48.109 - }
48.110 - if (version == NULL || release == NULL) {
48.111 - fprintf(stderr, "invalid version tag, "
48.112 - "missing version or release attribute\n");
48.113 - return;
48.114 - }
48.115 -
48.116 - razor_build_evr(buffer, sizeof buffer, epoch, version, release);
48.117 - razor_importer_begin_package(ctx->importer,
48.118 - ctx->name, buffer, ctx->arch);
48.119 - } else if (strcmp(name, "checksum") == 0) {
48.120 - ctx->p = ctx->pkgid;
48.121 - ctx->state = YUM_STATE_CHECKSUM;
48.122 - } else if (strcmp(name, "rpm:requires") == 0) {
48.123 - ctx->state = YUM_STATE_REQUIRES;
48.124 - } else if (strcmp(name, "rpm:provides") == 0) {
48.125 - ctx->state = YUM_STATE_PROVIDES;
48.126 - } else if (strcmp(name, "rpm:obsoletes") == 0) {
48.127 - ctx->state = YUM_STATE_OBSOLETES;
48.128 - } else if (strcmp(name, "rpm:conflicts") == 0) {
48.129 - ctx->state = YUM_STATE_CONFLICTS;
48.130 - } else if (strcmp(name, "rpm:entry") == 0 &&
48.131 - ctx->state != YUM_STATE_BEGIN) {
48.132 - n = NULL;
48.133 - epoch = NULL;
48.134 - version = NULL;
48.135 - release = NULL;
48.136 - flags = NULL;
48.137 - for (i = 0; atts[i]; i += 2) {
48.138 - if (strcmp(atts[i], "name") == 0)
48.139 - n = atts[i + 1];
48.140 - else if (strcmp(atts[i], "epoch") == 0)
48.141 - epoch = atts[i + 1];
48.142 - else if (strcmp(atts[i], "ver") == 0)
48.143 - version = atts[i + 1];
48.144 - else if (strcmp(atts[i], "rel") == 0)
48.145 - release = atts[i + 1];
48.146 - else if (strcmp(atts[i], "flags") == 0)
48.147 - flags = atts[i + 1];
48.148 - }
48.149 -
48.150 - if (n == NULL) {
48.151 - fprintf(stderr, "invalid rpm:entry, "
48.152 - "missing name or version attributes\n");
48.153 - return;
48.154 - }
48.155 -
48.156 - razor_build_evr(buffer, sizeof buffer, epoch, version, release);
48.157 - switch (ctx->state) {
48.158 - case YUM_STATE_REQUIRES:
48.159 - razor_importer_add_property(ctx->importer, n,
48.160 - yum_to_razor_flags (flags),
48.161 - buffer,
48.162 - RAZOR_PROPERTY_REQUIRES);
48.163 - break;
48.164 - case YUM_STATE_PROVIDES:
48.165 - razor_importer_add_property(ctx->importer, n,
48.166 - yum_to_razor_flags (flags),
48.167 - buffer,
48.168 - RAZOR_PROPERTY_PROVIDES);
48.169 - break;
48.170 - case YUM_STATE_OBSOLETES:
48.171 - razor_importer_add_property(ctx->importer, n,
48.172 - yum_to_razor_flags (flags),
48.173 - buffer,
48.174 - RAZOR_PROPERTY_OBSOLETES);
48.175 - break;
48.176 - case YUM_STATE_CONFLICTS:
48.177 - razor_importer_add_property(ctx->importer, n,
48.178 - yum_to_razor_flags (flags),
48.179 - buffer,
48.180 - RAZOR_PROPERTY_CONFLICTS);
48.181 - break;
48.182 - }
48.183 - }
48.184 -}
48.185 -
48.186 -static void
48.187 -yum_primary_end_element (void *data, const char *name)
48.188 -{
48.189 - struct yum_context *ctx = data;
48.190 -
48.191 - switch (ctx->state) {
48.192 - case YUM_STATE_PACKAGE_NAME:
48.193 - case YUM_STATE_PACKAGE_ARCH:
48.194 - case YUM_STATE_CHECKSUM:
48.195 - case YUM_STATE_FILE:
48.196 - ctx->state = YUM_STATE_BEGIN;
48.197 - break;
48.198 - }
48.199 -
48.200 - if (strcmp(name, "package") == 0) {
48.201 - XML_StopParser(ctx->current_parser, XML_TRUE);
48.202 - ctx->current_parser = ctx->filelists_parser;
48.203 - }
48.204 -}
48.205 -
48.206 -static void
48.207 -yum_character_data (void *data, const XML_Char *s, int len)
48.208 -{
48.209 - struct yum_context *ctx = data;
48.210 -
48.211 - switch (ctx->state) {
48.212 - case YUM_STATE_PACKAGE_NAME:
48.213 - case YUM_STATE_PACKAGE_ARCH:
48.214 - case YUM_STATE_CHECKSUM:
48.215 - case YUM_STATE_FILE:
48.216 - memcpy(ctx->p, s, len);
48.217 - ctx->p += len;
48.218 - *ctx->p = '\0';
48.219 - break;
48.220 - }
48.221 -}
48.222 -
48.223 -static void
48.224 -yum_filelists_start_element(void *data, const char *name, const char **atts)
48.225 -{
48.226 - struct yum_context *ctx = data;
48.227 - const char *pkg, *pkgid;
48.228 - int i;
48.229 -
48.230 - if (strcmp(name, "package") == 0) {
48.231 - pkg = NULL;
48.232 - pkgid = NULL;
48.233 - for (i = 0; atts[i]; i += 2) {
48.234 - if (strcmp(atts[i], "name") == 0)
48.235 - pkg = atts[i + 1];
48.236 - else if (strcmp(atts[i], "pkgid") == 0)
48.237 - pkgid = atts[i + 1];
48.238 - }
48.239 - if (strcmp(pkgid, ctx->pkgid) != 0)
48.240 - fprintf(stderr, "primary.xml and filelists.xml "
48.241 - "mismatch for %s: %s vs %s",
48.242 - pkg, pkgid, ctx->pkgid);
48.243 - } else if (strcmp(name, "file") == 0) {
48.244 - ctx->state = YUM_STATE_FILE;
48.245 - ctx->p = ctx->buffer;
48.246 - }
48.247 -}
48.248 -
48.249 -
48.250 -static void
48.251 -yum_filelists_end_element (void *data, const char *name)
48.252 -{
48.253 - struct yum_context *ctx = data;
48.254 -
48.255 - ctx->state = YUM_STATE_BEGIN;
48.256 - if (strcmp(name, "package") == 0) {
48.257 - XML_StopParser(ctx->current_parser, XML_TRUE);
48.258 - ctx->current_parser = ctx->primary_parser;
48.259 - razor_importer_finish_package(ctx->importer);
48.260 - } else if (strcmp(name, "file") == 0)
48.261 - razor_importer_add_file(ctx->importer, ctx->buffer);
48.262 -
48.263 -}
48.264 -
48.265 -#define XML_BUFFER_SIZE 4096
48.266 -
48.267 -struct razor_set *
48.268 -razor_set_create_from_yum(void)
48.269 -{
48.270 - struct yum_context ctx;
48.271 - void *buf;
48.272 - int len, ret;
48.273 - gzFile primary, filelists;
48.274 - XML_ParsingStatus status;
48.275 -
48.276 - ctx.importer = razor_importer_new();
48.277 - ctx.state = YUM_STATE_BEGIN;
48.278 -
48.279 - ctx.primary_parser = XML_ParserCreate(NULL);
48.280 - XML_SetUserData(ctx.primary_parser, &ctx);
48.281 - XML_SetElementHandler(ctx.primary_parser,
48.282 - yum_primary_start_element,
48.283 - yum_primary_end_element);
48.284 - XML_SetCharacterDataHandler(ctx.primary_parser,
48.285 - yum_character_data);
48.286 -
48.287 - ctx.filelists_parser = XML_ParserCreate(NULL);
48.288 - XML_SetUserData(ctx.filelists_parser, &ctx);
48.289 - XML_SetElementHandler(ctx.filelists_parser,
48.290 - yum_filelists_start_element,
48.291 - yum_filelists_end_element);
48.292 - XML_SetCharacterDataHandler(ctx.filelists_parser,
48.293 - yum_character_data);
48.294 -
48.295 - primary = gzopen("primary.xml.gz", "rb");
48.296 - if (primary == NULL)
48.297 - return NULL;
48.298 - filelists = gzopen("filelists.xml.gz", "rb");
48.299 - if (filelists == NULL)
48.300 - return NULL;
48.301 -
48.302 - ctx.current_parser = ctx.primary_parser;
48.303 -
48.304 - do {
48.305 - XML_GetParsingStatus(ctx.current_parser, &status);
48.306 - switch (status.parsing) {
48.307 - case XML_SUSPENDED:
48.308 - ret = XML_ResumeParser(ctx.current_parser);
48.309 - break;
48.310 - case XML_PARSING:
48.311 - case XML_INITIALIZED:
48.312 - buf = XML_GetBuffer(ctx.current_parser,
48.313 - XML_BUFFER_SIZE);
48.314 - if (ctx.current_parser == ctx.primary_parser)
48.315 - len = gzread(primary, buf, XML_BUFFER_SIZE);
48.316 - else
48.317 - len = gzread(filelists, buf, XML_BUFFER_SIZE);
48.318 - if (len < 0) {
48.319 - fprintf(stderr,
48.320 - "couldn't read input: %s\n",
48.321 - strerror(errno));
48.322 - return NULL;
48.323 - }
48.324 -
48.325 - XML_ParseBuffer(ctx.current_parser, len, len == 0);
48.326 - break;
48.327 - case XML_FINISHED:
48.328 - break;
48.329 - }
48.330 - } while (status.parsing != XML_FINISHED);
48.331 -
48.332 -
48.333 - XML_ParserFree(ctx.primary_parser);
48.334 - XML_ParserFree(ctx.filelists_parser);
48.335 -
48.336 - gzclose(primary);
48.337 - gzclose(filelists);
48.338 -
48.339 - return razor_importer_finish(ctx.importer);
48.340 -}