Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2014, Vsevolod Stakhov
3 : : * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org>
4 : : * Copyright (c) 2012 Julien Laffaye <jlaffaye@FreeBSD.org>
5 : : * All rights reserved.
6 : : *
7 : : * Redistribution and use in source and binary forms, with or without
8 : : * modification, are permitted provided that the following conditions are met:
9 : : * * Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * * Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : *
15 : : * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
16 : : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 : : * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 : : * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
19 : : * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 : : * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 : : */
26 : :
27 : : #include <sys/stat.h>
28 : : #include <sys/param.h>
29 : : #include <sys/time.h>
30 : :
31 : : #include <stdio.h>
32 : : #include <stdlib.h>
33 : : #include <string.h>
34 : : #include <unistd.h>
35 : : #include <errno.h>
36 : : #include <limits.h>
37 : :
38 : : #include <archive.h>
39 : : #include <archive_entry.h>
40 : :
41 : : #include "pkg.h"
42 : : #include "private/event.h"
43 : : #include "private/utils.h"
44 : : #include "private/pkgdb.h"
45 : : #include "private/pkg.h"
46 : : #include "binary.h"
47 : : #include "binary_private.h"
48 : :
49 : : static int
50 : 244 : pkg_repo_binary_init_update(struct pkg_repo *repo, const char *name)
51 : : {
52 : : sqlite3 *sqlite;
53 : 244 : const char update_check_sql[] = ""
54 : : "INSERT INTO repo_update VALUES(1);";
55 : 244 : const char update_start_sql[] = ""
56 : : "CREATE TABLE IF NOT EXISTS repo_update (n INT);";
57 : :
58 : : /* [Re]create repo */
59 [ - + ]: 244 : if (repo->ops->create(repo) != EPKG_OK) {
60 : 0 : pkg_emit_notice("Unable to create repository %s", repo->name);
61 : 0 : return (EPKG_FATAL);
62 : : }
63 [ - + ]: 244 : if (repo->ops->open(repo, R_OK|W_OK) != EPKG_OK) {
64 : 0 : pkg_emit_notice("Unable to open created repository %s", repo->name);
65 : 0 : return (EPKG_FATAL);
66 : : }
67 : :
68 : 244 : repo->ops->init(repo);
69 : :
70 [ + - ]: 244 : sqlite = PRIV_GET(repo);
71 : :
72 [ + - ]: 244 : if(sqlite3_exec(sqlite, update_check_sql, NULL, NULL, NULL) == SQLITE_OK) {
73 : 0 : pkg_emit_notice("Previous update has not been finished, restart it");
74 : 0 : return (EPKG_END);
75 : : }
76 : : else {
77 : 244 : sql_exec(sqlite, update_start_sql);
78 : : }
79 : :
80 : 244 : return (EPKG_OK);
81 : 244 : }
82 : :
83 : : static int
84 : 0 : pkg_repo_binary_delete_conflicting(const char *origin, const char *version,
85 : : const char *pkg_path, bool forced)
86 : : {
87 : 0 : int ret = EPKG_FATAL;
88 : : const char *oversion;
89 : :
90 [ # # ]: 0 : if (pkg_repo_binary_run_prstatement(REPO_VERSION, origin) != SQLITE_ROW) {
91 : 0 : ret = EPKG_FATAL;
92 : 0 : goto cleanup;
93 : : }
94 : 0 : oversion = sqlite3_column_text(pkg_repo_binary_stmt_prstatement(REPO_VERSION), 0);
95 [ # # ]: 0 : if (!forced) {
96 [ # # # ]: 0 : switch(pkg_version_cmp(oversion, version)) {
97 : : case -1:
98 : 0 : pkg_emit_error("duplicate package origin: replacing older "
99 : : "version %s in repo with package %s for "
100 : 0 : "origin %s", oversion, pkg_path, origin);
101 : :
102 [ # # ]: 0 : if (pkg_repo_binary_run_prstatement(DELETE, origin, origin) !=
103 : : SQLITE_DONE)
104 : 0 : ret = EPKG_FATAL;
105 : : else
106 : 0 : ret = EPKG_OK; /* conflict cleared */
107 : :
108 : 0 : break;
109 : : case 0:
110 : : case 1:
111 : 0 : pkg_emit_error("duplicate package origin: package %s is not "
112 : : "newer than version %s already in repo for "
113 : 0 : "origin %s", pkg_path, oversion, origin);
114 : 0 : ret = EPKG_END; /* keep what is already in the repo */
115 : 0 : break;
116 : : }
117 : 0 : }
118 : : else {
119 : 0 : ret = EPKG_OK;
120 [ # # ]: 0 : if (pkg_repo_binary_run_prstatement(DELETE, origin, origin) != SQLITE_DONE)
121 : 0 : ret = EPKG_FATAL;
122 : : }
123 : :
124 : : cleanup:
125 : 0 : sqlite3_reset(pkg_repo_binary_stmt_prstatement(REPO_VERSION));
126 : :
127 : 0 : return (ret);
128 : : }
129 : :
130 : : static int
131 : 492 : pkg_repo_binary_add_pkg(struct pkg *pkg, const char *pkg_path,
132 : : sqlite3 *sqlite, bool forced)
133 : : {
134 : : int ret;
135 : 492 : struct pkg_dep *dep = NULL;
136 : 492 : struct pkg_option *option = NULL;
137 : : struct pkg_kv *kv;
138 : : const char *arch;
139 : : int64_t package_id;
140 : : pkghash_it it;
141 : :
142 [ + - ]: 492 : arch = pkg->abi != NULL ? pkg->abi : pkg->arch;
143 : :
144 : : try_again:
145 [ - + - + ]: 984 : if ((ret = pkg_repo_binary_run_prstatement(PKG,
146 : 492 : pkg->origin, pkg->name, pkg->version, pkg->comment, pkg->desc,
147 : 492 : arch, pkg->maintainer, pkg->www, pkg->prefix, pkg->pkgsize,
148 : 492 : pkg->flatsize, (int64_t)pkg->licenselogic, pkg->sum, pkg->repopath,
149 : 984 : pkg->digest, pkg->old_digest, pkg->vital)) != SQLITE_DONE) {
150 [ # # ]: 0 : if (ret == SQLITE_CONSTRAINT) {
151 : 0 : ERROR_SQLITE(sqlite, "grmbl");
152 [ # # # # : 0 : switch(pkg_repo_binary_delete_conflicting(pkg->origin,
# # ]
153 : 0 : pkg->version, pkg_path, forced)) {
154 : : case EPKG_FATAL: /* sqlite error */
155 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PKG));
156 : 0 : return (EPKG_FATAL);
157 : : break;
158 : : case EPKG_END: /* repo already has newer */
159 : 0 : return (EPKG_END);
160 : : break;
161 : : default: /* conflict cleared, try again */
162 : 0 : goto try_again;
163 : : break;
164 : : }
165 : : } else {
166 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PKG));
167 : 0 : return (EPKG_FATAL);
168 : : }
169 : : }
170 : 492 : package_id = sqlite3_last_insert_rowid(sqlite);
171 : :
172 : 492 : dep = NULL;
173 [ + + ]: 704 : while (pkg_deps(pkg, &dep) == EPKG_OK) {
174 [ + - + - : 636 : if (pkg_repo_binary_run_prstatement(DEPS, dep->origin,
+ - ]
175 : 424 : dep->name, dep->version, package_id) != SQLITE_DONE) {
176 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(DEPS));
177 : 0 : return (EPKG_FATAL);
178 : : }
179 : : }
180 : :
181 : 492 : it = pkghash_iterator(pkg->categories);
182 [ + + ]: 976 : while (pkghash_next(&it)) {
183 : 484 : ret = pkg_repo_binary_run_prstatement(CAT1, it.key);
184 [ - + ]: 484 : if (ret == SQLITE_DONE)
185 : 968 : ret = pkg_repo_binary_run_prstatement(CAT2, package_id,
186 : 484 : it.key);
187 [ + - ]: 484 : if (ret != SQLITE_DONE) {
188 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(CAT2));
189 : 0 : return (EPKG_FATAL);
190 : : }
191 : : }
192 : :
193 : 492 : it = pkghash_iterator(pkg->licenses);
194 [ - + ]: 492 : while (pkghash_next(&it)) {
195 : 0 : ret = pkg_repo_binary_run_prstatement(LIC1, it.key);
196 [ # # ]: 0 : if (ret == SQLITE_DONE)
197 : 0 : ret = pkg_repo_binary_run_prstatement(LIC2, package_id,
198 : 0 : it.key);
199 [ # # ]: 0 : if (ret != SQLITE_DONE) {
200 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(LIC2));
201 : 0 : return (EPKG_FATAL);
202 : : }
203 : : }
204 : :
205 : 492 : option = NULL;
206 [ + + ]: 508 : while (pkg_options(pkg, &option) == EPKG_OK) {
207 : 16 : ret = pkg_repo_binary_run_prstatement(OPT1, option->key);
208 [ - + ]: 16 : if (ret == SQLITE_DONE)
209 : 32 : ret = pkg_repo_binary_run_prstatement(OPT2, option->key,
210 : 16 : option->value, package_id);
211 [ + - ]: 16 : if(ret != SQLITE_DONE) {
212 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(OPT2));
213 : 0 : return (EPKG_FATAL);
214 : : }
215 : : }
216 : :
217 : 492 : it = pkghash_iterator(pkg->shlibs_required);
218 [ + + ]: 500 : while (pkghash_next(&it)) {
219 : 8 : ret = pkg_repo_binary_run_prstatement(SHLIB1, it.key);
220 [ - + ]: 8 : if (ret == SQLITE_DONE)
221 : 16 : ret = pkg_repo_binary_run_prstatement(SHLIB_REQD, package_id,
222 : 8 : it.key);
223 [ + - ]: 8 : if (ret != SQLITE_DONE) {
224 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_REQD));
225 : 0 : return (EPKG_FATAL);
226 : : }
227 : : }
228 : :
229 : 492 : it = pkghash_iterator(pkg->shlibs_provided);
230 [ + + ]: 504 : while (pkghash_next(&it)) {
231 : 12 : ret = pkg_repo_binary_run_prstatement(SHLIB1, it.key);
232 [ - + ]: 12 : if (ret == SQLITE_DONE)
233 : 24 : ret = pkg_repo_binary_run_prstatement(SHLIB_PROV, package_id,
234 : 12 : it.key);
235 [ + - ]: 12 : if (ret != SQLITE_DONE) {
236 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(SHLIB_PROV));
237 : 0 : return (EPKG_FATAL);
238 : : }
239 : : }
240 : :
241 : 492 : it = pkghash_iterator(pkg->provides);
242 [ + + ]: 504 : while (pkghash_next(&it)) {
243 : 12 : ret = pkg_repo_binary_run_prstatement(PROVIDE, it.key);
244 [ - + ]: 12 : if (ret == SQLITE_DONE)
245 : 24 : ret = pkg_repo_binary_run_prstatement(PROVIDES, package_id,
246 : 12 : it.key);
247 [ + - ]: 12 : if (ret != SQLITE_DONE) {
248 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(PROVIDES));
249 : 0 : return (EPKG_FATAL);
250 : : }
251 : : }
252 : :
253 : 492 : it = pkghash_iterator(pkg->requires);
254 [ + + ]: 516 : while (pkghash_next(&it)) {
255 : 24 : ret = pkg_repo_binary_run_prstatement(REQUIRE, it.key);
256 [ - + ]: 24 : if (ret == SQLITE_DONE)
257 : 48 : ret = pkg_repo_binary_run_prstatement(REQUIRES, package_id,
258 : 24 : it.key);
259 [ + - ]: 24 : if (ret != SQLITE_DONE) {
260 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(REQUIRES));
261 : 0 : return (EPKG_FATAL);
262 : : }
263 : : }
264 : :
265 [ + + ]: 868 : LL_FOREACH(pkg->annotations, kv) {
266 : 376 : ret = pkg_repo_binary_run_prstatement(ANNOTATE1, kv->key);
267 [ - + ]: 376 : if (ret == SQLITE_DONE)
268 : 376 : ret = pkg_repo_binary_run_prstatement(ANNOTATE1, kv->value);
269 [ - + ]: 376 : if (ret == SQLITE_DONE)
270 : 752 : ret = pkg_repo_binary_run_prstatement(ANNOTATE2, package_id,
271 : 376 : kv->key, kv->value);
272 [ - + ]: 376 : if (ret != SQLITE_DONE) {
273 : 0 : ERROR_SQLITE(sqlite, pkg_repo_binary_sql_prstatement(ANNOTATE2));
274 : 0 : return (EPKG_FATAL);
275 : : }
276 : 376 : }
277 : :
278 : 492 : return (EPKG_OK);
279 : 492 : }
280 : :
281 : : static int
282 : : pkg_repo_binary_register_conflicts(const char *origin, char **conflicts,
283 : : int conflicts_num, sqlite3 *sqlite)
284 : : {
285 : : const char clean_conflicts_sql[] = ""
286 : : "DELETE FROM pkg_conflicts "
287 : : "WHERE package_id = ?1;";
288 : : const char select_id_sql[] = ""
289 : : "SELECT id FROM packages "
290 : : "WHERE origin = ?1;";
291 : : const char insert_conflict_sql[] = ""
292 : : "INSERT INTO pkg_conflicts "
293 : : "(package_id, conflict_id) "
294 : : "VALUES (?1, ?2);";
295 : : sqlite3_stmt *stmt = NULL;
296 : : int ret, i;
297 : : int64_t origin_id, conflict_id;
298 : :
299 : : pkg_debug(4, "pkgdb_repo_register_conflicts: running '%s'", select_id_sql);
300 : : stmt = prepare_sql(sqlite, select_id_sql);
301 : : if (stmt == NULL)
302 : : return (EPKG_FATAL);
303 : :
304 : : sqlite3_bind_text(stmt, 1, origin, -1, SQLITE_TRANSIENT);
305 : : ret = sqlite3_step(stmt);
306 : :
307 : : if (ret == SQLITE_ROW) {
308 : : origin_id = sqlite3_column_int64(stmt, 0);
309 : : }
310 : : else {
311 : : ERROR_SQLITE(sqlite, select_id_sql);
312 : : return (EPKG_FATAL);
313 : : }
314 : : sqlite3_finalize(stmt);
315 : :
316 : : pkg_debug(4, "pkgdb_repo_register_conflicts: running '%s'", clean_conflicts_sql);
317 : : stmt = prepare_sql(sqlite, clean_conflicts_sql);
318 : : if (stmt == NULL)
319 : : return (EPKG_FATAL);
320 : :
321 : : sqlite3_bind_int64(stmt, 1, origin_id);
322 : : /* Ignore cleanup result */
323 : : (void)sqlite3_step(stmt);
324 : :
325 : : sqlite3_finalize(stmt);
326 : :
327 : : for (i = 0; i < conflicts_num; i ++) {
328 : : /* Select a conflict */
329 : : pkg_debug(4, "pkgdb_repo_register_conflicts: running '%s'", select_id_sql);
330 : : stmt = prepare_sql(sqlite, select_id_sql);
331 : : if (stmt == NULL)
332 : : return (EPKG_FATAL);
333 : :
334 : : sqlite3_bind_text(stmt, 1, conflicts[i], -1, SQLITE_TRANSIENT);
335 : : ret = sqlite3_step(stmt);
336 : :
337 : : if (ret == SQLITE_ROW) {
338 : : conflict_id = sqlite3_column_int64(stmt, 0);
339 : : }
340 : : else {
341 : : ERROR_SQLITE(sqlite, select_id_sql);
342 : : return (EPKG_FATAL);
343 : : }
344 : :
345 : : sqlite3_finalize(stmt);
346 : :
347 : : /* Insert a pair */
348 : : pkg_debug(4, "pkgdb_repo_register_conflicts: running '%s'", insert_conflict_sql);
349 : : stmt = prepare_sql(sqlite, insert_conflict_sql);
350 : : if (stmt == NULL)
351 : : return (EPKG_FATAL);
352 : :
353 : : sqlite3_bind_int64(stmt, 1, origin_id);
354 : : sqlite3_bind_int64(stmt, 2, conflict_id);
355 : : ret = sqlite3_step(stmt);
356 : :
357 : : if (ret != SQLITE_DONE) {
358 : : ERROR_SQLITE(sqlite, insert_conflict_sql);
359 : : return (EPKG_FATAL);
360 : : }
361 : :
362 : : sqlite3_finalize(stmt);
363 : : }
364 : :
365 : : return (EPKG_OK);
366 : : }
367 : :
368 : : static int
369 : 492 : pkg_repo_binary_add_from_manifest(const char *buf, sqlite3 *sqlite, size_t len,
370 : : struct pkg_manifest_key **keys, struct pkg **p __unused,
371 : : struct pkg_repo *repo)
372 : : {
373 : 492 : int rc = EPKG_OK;
374 : : struct pkg *pkg;
375 : : const char *abi;
376 : :
377 : 492 : rc = pkg_new(&pkg, PKG_REMOTE);
378 [ - + ]: 492 : if (rc != EPKG_OK)
379 : 0 : return (EPKG_FATAL);
380 : :
381 : 492 : pkg_manifest_keys_new(keys);
382 : 492 : rc = pkg_parse_manifest(pkg, buf, len, *keys);
383 [ - + ]: 492 : if (rc != EPKG_OK) {
384 : 0 : goto cleanup;
385 : : }
386 : :
387 [ - + # # ]: 492 : if (pkg->digest == NULL || !pkg_checksum_is_valid(pkg->digest, strlen(pkg->digest)))
388 : 492 : pkg_checksum_calculate(pkg, NULL, false, true, false);
389 [ + - ]: 492 : abi = pkg->abi != NULL ? pkg->abi : pkg->arch;
390 [ + - - + ]: 492 : if (abi == NULL || !is_valid_abi(abi, true)) {
391 : 0 : rc = EPKG_FATAL;
392 : 0 : pkg_emit_error("repository %s contains packages with wrong ABI: %s",
393 : 0 : repo->name, abi);
394 : 0 : goto cleanup;
395 : : }
396 [ + - ]: 492 : if (!is_valid_os_version(pkg)) {
397 : 0 : rc = EPKG_FATAL;
398 : 0 : pkg_emit_error("repository %s contains packages for wrong OS "
399 : 0 : "version: %s", repo->name, abi);
400 : 0 : goto cleanup;
401 : : }
402 : :
403 : 492 : free(pkg->reponame);
404 : 492 : pkg->reponame = xstrdup(repo->name);
405 : :
406 : 492 : rc = pkg_repo_binary_add_pkg(pkg, NULL, sqlite, true);
407 : :
408 : : cleanup:
409 : 492 : pkg_free(pkg);
410 : :
411 : 492 : return (rc);
412 : 492 : }
413 : :
414 : : static void __unused
415 : : pkg_repo_binary_parse_conflicts(FILE *f, sqlite3 *sqlite)
416 : : {
417 : : size_t linecap = 0;
418 : : ssize_t linelen;
419 : : char *linebuf = NULL, *p, **deps;
420 : : const char *origin, *pdep;
421 : : int ndep, i;
422 : : const char conflicts_clean_sql[] = ""
423 : : "DELETE FROM pkg_conflicts;";
424 : :
425 : : pkg_debug(4, "pkg_parse_conflicts_file: running '%s'", conflicts_clean_sql);
426 : : (void)sql_exec(sqlite, conflicts_clean_sql);
427 : :
428 : : while ((linelen = getline(&linebuf, &linecap, f)) > 0) {
429 : : p = linebuf;
430 : : origin = strsep(&p, ":");
431 : : /* Check dependencies number */
432 : : pdep = p;
433 : : ndep = 1;
434 : : while (*pdep != '\0') {
435 : : if (*pdep == ',')
436 : : ndep ++;
437 : : pdep ++;
438 : : }
439 : : deps = xmalloc(sizeof(char *) * ndep);
440 : : for (i = 0; i < ndep; i ++) {
441 : : deps[i] = strsep(&p, ",\n");
442 : : }
443 : : pkg_repo_binary_register_conflicts(origin, deps, ndep, sqlite);
444 : : free(deps);
445 : : }
446 : :
447 : : free(linebuf);
448 : : }
449 : :
450 : : static void
451 : 0 : rollback_repo(void *data)
452 : : {
453 : 0 : const char *name = (const char *)data;
454 : : char path[MAXPATHLEN];
455 : :
456 : 0 : snprintf(path, sizeof(path), "%s-pkgtemp", name);
457 : 0 : unlink(name);
458 : 0 : rename(path, name);
459 : 0 : snprintf(path, sizeof(path), "%s-journal", name);
460 : 0 : unlink(path);
461 : 0 : }
462 : : static int
463 : 416 : pkg_repo_binary_update_proceed(const char *name, struct pkg_repo *repo,
464 : : time_t *mtime, bool force)
465 : : {
466 : 416 : struct pkg *pkg = NULL;
467 : 416 : int rc = EPKG_FATAL;
468 : 416 : sqlite3 *sqlite = NULL;
469 : 416 : int cnt = 0;
470 : : time_t local_t;
471 : 416 : struct pkg_manifest_key *keys = NULL;
472 : 416 : size_t len = 0;
473 : 416 : bool in_trans = false;
474 : 416 : char *path = NULL;
475 : 416 : FILE *f = NULL;
476 : : int fd;
477 : 416 : char *line = NULL;
478 : 416 : size_t linecap = 0;
479 : 416 : ssize_t linelen, totallen = 0;
480 : :
481 : 416 : pkg_debug(1, "Pkgrepo, begin update of '%s'", name);
482 : :
483 : : /* In forced mode, ignore mtime */
484 [ + + ]: 416 : if (force)
485 : 246 : *mtime = 0;
486 : :
487 : : /* Fetch meta */
488 : 416 : local_t = *mtime;
489 [ + + ]: 416 : if (pkg_repo_fetch_meta(repo, &local_t) == EPKG_FATAL)
490 : 4 : pkg_emit_notice("repository %s has no meta file, using "
491 : 4 : "default settings", repo->name);
492 : :
493 : : /* Fetch packagesite */
494 : 416 : local_t = *mtime;
495 : 832 : fd = pkg_repo_fetch_remote_extract_fd(repo,
496 : 416 : repo->meta->manifests, &local_t, &rc, &len);
497 [ + + ]: 416 : if (fd == -1)
498 : 172 : goto cleanup;
499 : 244 : f = fdopen(fd, "r");
500 : 244 : rewind(f);
501 : :
502 : 244 : *mtime = local_t;
503 : : /*fconflicts = repo_fetch_remote_extract_tmp(repo,
504 : : repo_conflicts_archive, "txz", &local_t,
505 : : &rc, repo_conflicts_file);*/
506 : :
507 : : /* Load local repository data */
508 : 244 : xasprintf(&path, "%s-pkgtemp", name);
509 : 244 : rename(name, path);
510 : 244 : pkg_register_cleanup_callback(rollback_repo, (void *)name);
511 : 244 : rc = pkg_repo_binary_init_update(repo, name);
512 [ - + ]: 244 : if (rc != EPKG_OK) {
513 : 0 : rc = EPKG_FATAL;
514 : 0 : goto cleanup;
515 : : }
516 : :
517 : : /* Here sqlite is initialized */
518 [ + - ]: 244 : sqlite = PRIV_GET(repo);
519 : :
520 : 244 : pkg_debug(1, "Pkgrepo, reading new packagesite.yaml for '%s'", name);
521 : :
522 : 244 : pkg_emit_progress_start("Processing entries");
523 : :
524 : : /* 200MB should be enough */
525 : 244 : sql_exec(sqlite, "PRAGMA mmap_size = 209715200;");
526 : 244 : sql_exec(sqlite, "PRAGMA page_size = %d;", getpagesize());
527 : 244 : sql_exec(sqlite, "PRAGMA foreign_keys = OFF;");
528 : 244 : sql_exec(sqlite, "PRAGMA synchronous = OFF;");
529 : :
530 : 244 : rc = pkgdb_transaction_begin_sqlite(sqlite, "REPO");
531 [ - + ]: 244 : if (rc != EPKG_OK)
532 : 0 : goto cleanup;
533 : :
534 : 244 : in_trans = true;
535 [ + + ]: 736 : while ((linelen = getline(&line, &linecap, f)) > 0) {
536 : 492 : cnt++;
537 : 492 : totallen += linelen;
538 [ - + ]: 492 : if ((cnt % 10 ) == 0)
539 : 0 : pkg_emit_progress_tick(totallen, len);
540 : 984 : rc = pkg_repo_binary_add_from_manifest(line, sqlite, linelen,
541 : 492 : &keys, &pkg, repo);
542 [ + - ]: 492 : if (rc != EPKG_OK) {
543 : 0 : pkg_emit_progress_tick(len, len);
544 : 0 : break;
545 : : }
546 : : }
547 : 244 : pkg_emit_progress_tick(len, len);
548 : :
549 [ - + ]: 244 : if (rc == EPKG_OK)
550 : 244 : pkg_emit_incremental_update(repo->name, cnt);
551 : :
552 : 244 : sql_exec(sqlite, ""
553 : : "CREATE INDEX packages_origin ON packages(origin COLLATE NOCASE);"
554 : : "CREATE INDEX packages_name ON packages(name COLLATE NOCASE);"
555 : : "CREATE INDEX packages_uid_nocase ON packages(name COLLATE NOCASE, origin COLLATE NOCASE);"
556 : : "CREATE INDEX packages_version_nocase ON packages(name COLLATE NOCASE, version);"
557 : : "CREATE INDEX packages_uid ON packages(name, origin);"
558 : : "CREATE INDEX packages_version ON packages(name, version);"
559 : : "CREATE UNIQUE INDEX packages_digest ON packages(manifestdigest);"
560 : : );
561 : :
562 : : cleanup:
563 : :
564 [ + + ]: 416 : if (in_trans) {
565 [ + - ]: 244 : if (rc != EPKG_OK)
566 : 0 : pkgdb_transaction_rollback_sqlite(sqlite, "REPO");
567 : :
568 [ + - ]: 244 : if (pkgdb_transaction_commit_sqlite(sqlite, "REPO") != EPKG_OK)
569 : 0 : rc = EPKG_FATAL;
570 : 244 : }
571 : : /* restore the previous db in case of failures */
572 [ + + + + ]: 416 : if (rc != EPKG_OK && rc != EPKG_UPTODATE) {
573 : 4 : unlink(name);
574 : 4 : rename(path, name);
575 : 4 : }
576 [ + + ]: 416 : if (path != NULL) {
577 : 244 : unlink(path);
578 : 244 : free(path);
579 : 244 : }
580 : 416 : pkg_unregister_cleanup_callback(rollback_repo, (void *)name);
581 : 416 : pkg_manifest_keys_free(keys);
582 : 416 : pkg_free(pkg);
583 : 416 : free(line);
584 [ + + ]: 416 : if (f != NULL)
585 : 244 : fclose(f);
586 : :
587 : 416 : return (rc);
588 : : }
589 : :
590 : : int
591 : 416 : pkg_repo_binary_update(struct pkg_repo *repo, bool force)
592 : : {
593 : : char filepath[MAXPATHLEN];
594 : 416 : const char update_finish_sql[] = ""
595 : : "DROP TABLE repo_update;";
596 : : sqlite3 *sqlite;
597 : :
598 : : struct stat st;
599 : 416 : time_t t = 0;
600 : 416 : int res = EPKG_FATAL;
601 : :
602 : 416 : bool got_meta = false;
603 : :
604 : 416 : sqlite3_initialize();
605 : :
606 [ - + ]: 416 : if (!pkg_repo_enabled(repo))
607 : 0 : return (EPKG_OK);
608 : :
609 : 416 : pkg_debug(1, "PkgRepo: verifying update for %s", pkg_repo_name(repo));
610 : :
611 : : /* First of all, try to open and init repo and check whether it is fine */
612 [ + + ]: 416 : if (repo->ops->open(repo, R_OK|W_OK) != EPKG_OK) {
613 : 230 : pkg_debug(1, "PkgRepo: need forced update of %s", pkg_repo_name(repo));
614 : 230 : t = 0;
615 : 230 : force = true;
616 : 460 : snprintf(filepath, sizeof(filepath), "%s/%s", ctx.dbdir,
617 : 230 : pkg_repo_binary_get_filename(pkg_repo_name(repo)));
618 : 230 : }
619 : : else {
620 : 186 : repo->ops->close(repo, false);
621 : 186 : snprintf(filepath, sizeof(filepath), "%s/%s.meta", ctx.dbdir, pkg_repo_name(repo));
622 [ - + ]: 186 : if (stat(filepath, &st) != -1) {
623 [ + + ]: 186 : t = force ? 0 : st.st_mtime;
624 : 186 : got_meta = true;
625 : 186 : }
626 : :
627 : 372 : snprintf(filepath, sizeof(filepath), "%s/%s", ctx.dbdir,
628 : 186 : pkg_repo_binary_get_filename(pkg_repo_name(repo)));
629 [ + - - + ]: 186 : if (got_meta && stat(filepath, &st) != -1) {
630 [ + + ]: 186 : if (!force)
631 : 170 : t = st.st_mtime;
632 : 186 : }
633 : : }
634 : :
635 : 416 : res = pkg_repo_binary_update_proceed(filepath, repo, &t, force);
636 [ + + + + ]: 416 : if (res != EPKG_OK && res != EPKG_UPTODATE) {
637 : 4 : pkg_emit_notice("Unable to update repository %s", repo->name);
638 : 4 : goto cleanup;
639 : : }
640 : :
641 : : /* Finish updated repo */
642 [ + + ]: 656 : if (res == EPKG_OK) {
643 [ - + ]: 244 : sqlite = PRIV_GET(repo);
644 : 244 : sql_exec(sqlite, update_finish_sql);
645 : 244 : }
646 : :
647 : : cleanup:
648 : : /* Set mtime from http request if possible */
649 [ + + + + ]: 416 : if (t != 0 && res == EPKG_OK) {
650 : 488 : struct timeval ftimes[2] = {
651 : 488 : {
652 : 244 : .tv_sec = t,
653 : : .tv_usec = 0
654 : : },
655 : 488 : {
656 : 244 : .tv_sec = t,
657 : : .tv_usec = 0
658 : : }
659 : : };
660 : :
661 : 244 : utimes(filepath, ftimes);
662 [ + + ]: 244 : if (got_meta) {
663 : 18 : snprintf(filepath, sizeof(filepath), "%s/%s.meta", ctx.dbdir, pkg_repo_name(repo));
664 : 18 : utimes(filepath, ftimes);
665 : 18 : }
666 : 244 : }
667 : :
668 [ + + ]: 416 : if (repo->priv != NULL)
669 : 244 : repo->ops->close(repo, false);
670 : :
671 : 416 : return (res);
672 : 416 : }
|