XBPS Library API  0.19
The X Binary Package System
transaction_package_replace.c
1 /*-
2  * Copyright (c) 2011-2012 Juan Romero Pardines.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <stdio.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <libgen.h>
33 
34 #include "xbps_api_impl.h"
35 
36 int HIDDEN
37 xbps_transaction_package_replace(struct xbps_handle *xhp)
38 {
39  prop_array_t replaces, unsorted;
40  prop_dictionary_t instd, reppkgd, filesd;
41  prop_object_t obj, obj2;
42  prop_object_iterator_t iter;
43  const char *pattern, *pkgname, *curpkgname, *pkgver, *curpkgver;
44  char *buf;
45  bool instd_auto, sr;
46  size_t i;
47 
48  unsorted = prop_dictionary_get(xhp->transd, "unsorted_deps");
49 
50  for (i = 0; i < prop_array_count(unsorted); i++) {
51  obj = prop_array_get(unsorted, i);
52  replaces = prop_dictionary_get(obj, "replaces");
53  if (replaces == NULL || prop_array_count(replaces) == 0)
54  continue;
55 
56  iter = prop_array_iterator(replaces);
57  assert(iter);
58 
59  while ((obj2 = prop_object_iterator_next(iter)) != NULL) {
60  pattern = prop_string_cstring_nocopy(obj2);
61  /*
62  * Find the installed package that matches the pattern
63  * to be replaced.
64  */
65  if (((instd = xbps_pkgdb_get_pkg(xhp, pattern)) == NULL) &&
66  ((instd = xbps_pkgdb_get_virtualpkg(xhp, pattern)) == NULL))
67  continue;
68 
69  prop_dictionary_get_cstring_nocopy(obj,
70  "pkgname", &pkgname);
71  prop_dictionary_get_cstring_nocopy(obj,
72  "pkgver", &pkgver);
73  prop_dictionary_get_cstring_nocopy(instd,
74  "pkgname", &curpkgname);
75  prop_dictionary_get_cstring_nocopy(instd,
76  "pkgver", &curpkgver);
77  /*
78  * Check that we are not replacing the same package,
79  * due to virtual packages.
80  */
81  if (strcmp(pkgname, curpkgname) == 0)
82  continue;
83 
84  xbps_dbg_printf(xhp,
85  "Package `%s' will be replaced by `%s', "
86  "matched with `%s'\n", curpkgver, pkgver, pattern);
87  instd_auto = false;
88  prop_dictionary_get_bool(instd,
89  "automatic-install", &instd_auto);
90  /*
91  * Package contains replaces="pkgpattern", but the
92  * package that should be replaced is also in the
93  * transaction and it's going to be updated.
94  */
95  if ((reppkgd = xbps_find_pkg_in_array(unsorted, curpkgname)) ||
96  (reppkgd = xbps_find_virtualpkg_in_array(xhp, unsorted, curpkgname))) {
97  xbps_dbg_printf(xhp,
98  "found replaced pkg "
99  "in transaction\n");
100  prop_dictionary_set_bool(instd,
101  "remove-and-update", true);
102  prop_dictionary_set_bool(reppkgd,
103  "automatic-install", instd_auto);
104  prop_dictionary_set_bool(reppkgd,
105  "skip-obsoletes", true);
106  xbps_array_replace_dict_by_name(unsorted,
107  reppkgd, curpkgname);
108  }
109  /*
110  * If new package is providing a virtual package to the
111  * package that we want to replace we should respect
112  * the automatic-install object.
113  */
115  pattern, true) ||
117  pkgname, false)) {
118  prop_dictionary_set_bool(obj,
119  "automatic-install", instd_auto);
120  }
121  sr = false;
122  prop_dictionary_get_bool(obj, "softreplace", &sr);
123  if (sr) {
124  prop_dictionary_set_bool(obj,
125  "automatic-install", instd_auto);
126  prop_dictionary_set_bool(instd,
127  "softreplace", true);
128  buf = xbps_xasprintf("%s/.%s.plist",
129  xhp->metadir, curpkgname);
130  filesd = prop_dictionary_internalize_from_zfile(buf);
131  free(buf);
132  assert(filesd != NULL);
133  buf = xbps_xasprintf("%s/.%s.plist",
134  xhp->metadir, pkgname);
135  if (!prop_dictionary_externalize_to_zfile(filesd, buf)) {
136  free(buf);
137  prop_object_release(filesd);
138  prop_object_iterator_release(iter);
139  return errno;
140  }
141  prop_object_release(filesd);
142  free(buf);
143  }
144  /*
145  * Add package dictionary into the transaction and mark
146  * it as to be "removed".
147  */
148  prop_dictionary_set_cstring_nocopy(instd,
149  "transaction", "remove");
150  prop_array_add(unsorted, instd);
151  }
152  prop_object_iterator_release(iter);
153  }
154 
155  return 0;
156 }