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