XBPS Library API 20240111
The X Binary Package System
pkgdb_conversion.c
1/*-
2 * Copyright (c) 2014 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 <sys/stat.h>
32#include <fcntl.h>
33
34#include "xbps_api_impl.h"
35
36static int
37pkgdb038(struct xbps_handle *xhp, const char *opkgdb_plist)
38{
39 xbps_dictionary_t pkgdb, opkgdb;
40 xbps_object_iterator_t iter;
41 xbps_object_t obj;
42 int rv = 0;
43
44 /*
45 * The pkgdb-0.38.plist format contains all pkg metadata objects,
46 * except its files list. To avoid a broken conversion, the old
47 * pkg metadata plists are kept, and the converted ones are written
48 * to another path.
49 *
50 * - <metadir>/pkgdb-0.38.plist
51 * - <metadir>/.<pkgname>-files.plist
52 */
53 opkgdb = xbps_plist_dictionary_from_file(xhp, opkgdb_plist);
54 if (opkgdb == NULL)
55 return EINVAL;
56
57 pkgdb = xbps_dictionary_create();
58 assert(pkgdb);
59 /*
60 * Iterate over the old pkgdb dictionary and copy all pkg objects
61 * into the new pkgdb dictionary.
62 */
63 iter = xbps_dictionary_iterator(opkgdb);
64 assert(iter);
65
66 while ((obj = xbps_object_iterator_next(iter))) {
67 xbps_dictionary_t pkgd, pkgfilesd, pkgmetad;
68 xbps_object_iterator_t iter2;
69 xbps_object_t obj2;
70 const char *pkgname, *repo;
71 char *pkgmeta;
72
73 pkgname = xbps_dictionary_keysym_cstring_nocopy(obj);
74 pkgd = xbps_dictionary_get_keysym(opkgdb, obj);
75 /*
76 * Rename "repository-origin" obj to "repository" to match
77 * the repository index obj.
78 */
79 if (xbps_dictionary_get_cstring_nocopy(pkgd, "repository-origin", &repo)) {
80 xbps_dictionary_set_cstring(pkgd, "repository", repo);
81 xbps_dictionary_remove(pkgd, "repository-origin");
82 }
83 /*
84 * Copy old pkgdb objects to the new pkgdb.
85 */
86 if (!xbps_dictionary_set(pkgdb, pkgname, pkgd)) {
87 xbps_dbg_printf("%s: failed to copy %s pkgd "
88 "for pkgdb conversion\n", __func__, pkgname);
89 rv = EINVAL;
90 goto out;
91 }
92 /*
93 * Copy pkg metadata objs to the new pkgdb.
94 */
95 pkgmeta = xbps_xasprintf("%s/.%s.plist", xhp->metadir, pkgname);
96 pkgmetad = xbps_plist_dictionary_from_file(xhp, pkgmeta);
97 if (pkgmetad == NULL) {
98 rv = EINVAL;
99 xbps_dbg_printf("%s: cannot open %s: %s\n",
100 __func__, pkgmeta, strerror(errno));
101 goto out;
102 }
103 pkgfilesd = xbps_dictionary_create();
104 assert(pkgfilesd);
105
106 iter2 = xbps_dictionary_iterator(pkgmetad);
107 assert(iter2);
108
109 while ((obj2 = xbps_object_iterator_next(iter2))) {
110 xbps_object_t curobj;
111 const char *key, *excluded[] = {
112 "conf_files", "dirs", "files", "links"
113 };
114 bool skip = false;
115
116 key = xbps_dictionary_keysym_cstring_nocopy(obj2);
117 curobj = xbps_dictionary_get_keysym(pkgmetad, obj2);
118 for (uint8_t i = 0; i < __arraycount(excluded); i++) {
119 if (strcmp(excluded[i], key) == 0) {
120 skip = true;
121 break;
122 }
123 }
124 if (skip) {
125 assert(xbps_object_type(curobj) == XBPS_TYPE_ARRAY);
126 if (xbps_array_count(curobj))
127 xbps_dictionary_set(pkgfilesd, key, curobj);
128
129 continue;
130 }
131 if (!xbps_dictionary_set(pkgd, key, curobj)) {
132 xbps_dbg_printf("%s: failed to copy %s "
133 "pkgd for pkgdb conversion\n", pkgname, key);
134 xbps_object_iterator_release(iter2);
135 xbps_object_release(pkgmetad);
136 free(pkgmeta);
137 rv = EINVAL;
138 goto out;
139 }
140 }
141 xbps_object_iterator_release(iter2);
142 /*
143 * Externalize <pkgname>-files.plist if pkg contains any file.
144 */
145 if (xbps_dictionary_count(pkgfilesd)) {
146 char *pkgfiles, *sha256;
147
148 pkgfiles = xbps_xasprintf("%s/.%s-files.plist", xhp->metadir, pkgname);
149 if (!xbps_dictionary_externalize_to_file(pkgfilesd, pkgfiles)) {
150 xbps_dbg_printf("%s: failed to "
151 "externalize %s: %s\n", __func__, pkgfiles, strerror(errno));
152 rv = EINVAL;
153 goto out;
154 }
155 xbps_dbg_printf("%s: externalized %s successfully\n", __func__, pkgfiles);
156 /*
157 * Update SHA56 hash for the pkg files plist.
158 */
159 sha256 = xbps_file_hash(pkgfiles);
160 assert(sha256);
161 xbps_dictionary_set_cstring(pkgd, "metafile-sha256", sha256);
162 free(sha256);
163 free(pkgfiles);
164 } else {
165 /* unnecessary obj if pkg contains no files */
166 xbps_dictionary_remove(pkgd, "metafile-sha256");
167 }
168 xbps_object_release(pkgfilesd);
169 xbps_object_release(pkgmetad);
170 free(pkgmeta);
171 }
172 /*
173 * Externalize the new pkgdb plist.
174 */
175 if (!xbps_dictionary_externalize_to_file(pkgdb, xhp->pkgdb_plist)) {
176 xbps_dbg_printf("%s: failed to externalize %s: "
177 "%s!\n", __func__, xhp->pkgdb_plist, strerror(errno));
178 rv = EINVAL;
179 goto out;
180 }
181out:
182 if (iter)
183 xbps_object_iterator_release(iter);
184 if (pkgdb)
185 xbps_object_release(pkgdb);
186 if (opkgdb)
187 xbps_object_release(opkgdb);
188
189 return rv;
190}
191
192int HIDDEN
193xbps_pkgdb_conversion(struct xbps_handle *xhp)
194{
195 char *opkgdb = NULL;
196 int rv = 0;
197
198 /*
199 * If pkgdb-0.38.plist exists there's nothing to do.
200 */
201 if (xhp && xhp->pkgdb_plist && (access(xhp->pkgdb_plist, R_OK) == 0))
202 return 0;
203 /*
204 * If pkgdb-0.21.plist does not exist there's nothing to do.
205 */
206 opkgdb = xbps_xasprintf("%s/pkgdb-0.21.plist", xhp->metadir);
207 if (access(opkgdb, R_OK) == 0) {
208 /*
209 * Make the conversion and exit on success. It's just
210 * better to make the upgrade in two steps.
211 */
212 xbps_set_cb_state(xhp, XBPS_STATE_PKGDB, 0, NULL, NULL);
213 if ((rv = pkgdb038(xhp, opkgdb)) == 0) {
214 xbps_set_cb_state(xhp, XBPS_STATE_PKGDB_DONE, 0, NULL, NULL);
215 xbps_end(xhp);
216 exit(EXIT_SUCCESS);
217 }
218 }
219 free(opkgdb);
220
221 return rv;
222}
char metadir[XBPS_MAXPATH+sizeof(XBPS_META_PATH)]
Definition xbps.h:664
char * pkgdb_plist
Definition xbps.h:625
Generic XBPS structure handler for initialization.
Definition xbps.h:550
void xbps_end(struct xbps_handle *xhp)
Definition initend.c:180
xbps_dictionary_t xbps_plist_dictionary_from_file(const char *path)
char * xbps_xasprintf(const char *fmt,...) __attribute__((format(printf