]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
jail: Ignore any return codes from the shell
[people/ms/pakfire.git] / src / libpakfire / db.c
CommitLineData
33d55ab4
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2021 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
21#include <errno.h>
097b6ca6 22#include <linux/limits.h>
33d55ab4 23#include <stdlib.h>
788221bd 24#include <time.h>
33d55ab4 25
923d6794 26#include <openssl/sha.h>
c9c03e6a 27#include <solv/solver.h>
26affd69
MT
28#include <sqlite3.h>
29
f5c77233 30#include <pakfire/archive.h>
33d55ab4 31#include <pakfire/db.h>
2a623cf8 32#include <pakfire/dependencies.h>
c52e0148 33#include <pakfire/digest.h>
f5c77233 34#include <pakfire/file.h>
ac71886a 35#include <pakfire/filelist.h>
33d55ab4 36#include <pakfire/logging.h>
e49b93d1 37#include <pakfire/package.h>
18bf891d 38#include <pakfire/pakfire.h>
e49b93d1 39#include <pakfire/repo.h>
d973a13d 40#include <pakfire/string.h>
33d55ab4
MT
41#include <pakfire/util.h>
42
0cb487ff
MT
43#define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db"
44
5ba550fe 45#define CURRENT_SCHEMA 8
c745fb2d
MT
46#define SCHEMA_MIN_SUP 7
47
33d55ab4 48struct pakfire_db {
ac4c607b 49 struct pakfire* pakfire;
33d55ab4 50 int nrefs;
77a4b3a3 51
097b6ca6 52 char path[PATH_MAX];
77a4b3a3 53 int mode;
26affd69
MT
54
55 sqlite3* handle;
c745fb2d 56 int schema;
7b4df765 57 time_t last_modified_at;
33d55ab4
MT
58};
59
9c5938ea 60static void logging_callback(void* data, int r, const char* msg) {
ac4c607b 61 struct pakfire* pakfire = (struct pakfire*)data;
9c5938ea
MT
62
63 ERROR(pakfire, "Database Error: %s: %s\n",
64 sqlite3_errstr(r), msg);
65}
66
c745fb2d
MT
67static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
68 sqlite3_stmt* stmt = NULL;
69 sqlite3_value* val = NULL;
70 int r;
71
72 const char* sql = "SELECT val FROM settings WHERE key = ?";
73
74 // Prepare the statement
75 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
76 if (r != SQLITE_OK) {
77 //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
78 // sql, sqlite3_errmsg(db->handle));
79 return NULL;
80 }
81
82 // Bind key
83 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
84 if (r != SQLITE_OK) {
85 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
86 goto ERROR;
87 }
88
89 // Execute the statement
90 do {
91 r = sqlite3_step(stmt);
92 } while (r == SQLITE_BUSY);
93
f168dd0c
MT
94 // We should have read a row
95 if (r != SQLITE_ROW)
96 goto ERROR;
97
c745fb2d 98 // Read value
f168dd0c 99 val = sqlite3_column_value(stmt, 0);
c745fb2d
MT
100 if (!val) {
101 ERROR(db->pakfire, "Could not read value\n");
102 goto ERROR;
103 }
104
105 // Copy value onto the heap
106 val = sqlite3_value_dup(val);
107
108ERROR:
109 if (stmt)
110 sqlite3_finalize(stmt);
111
112 return val;
113}
114
33b38daa
MT
115static char* pakfire_db_get_string(struct pakfire_db* db, const char* key) {
116 char* s = NULL;
117
118 // Fetch the value from the database
119 sqlite3_value* value = pakfire_db_get(db, key);
120 if (!value)
121 return NULL;
122
123 // Extract the value as string
124 const char* p = (const char*)sqlite3_value_text(value);
125 if (!p)
126 goto ERROR;
127
128 // Copy string to heap
129 s = strdup(p);
130
131ERROR:
132 if (value)
133 sqlite3_value_free(value);
134
135 return s;
136}
137
138static int pakfire_db_set_string(struct pakfire_db* db, const char* key, const char* val) {
139 sqlite3_stmt* stmt = NULL;
140 int r;
141
142 DEBUG(db->pakfire, "Setting %s to '%s'\n", key, val);
143
144 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
145 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
146
147 // Prepare statement
148 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
149 if (r != SQLITE_OK) {
150 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
151 sql, sqlite3_errmsg(db->handle));
152 return 1;
153 }
154
155 // Bind key
156 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
157 if (r != SQLITE_OK) {
158 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
159 goto ERROR;
160 }
161
162 // Bind val
163 r = sqlite3_bind_text(stmt, 2, val, strlen(val), NULL);
164 if (r != SQLITE_OK) {
165 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
166 goto ERROR;
167 }
168
169 // Execute the statement
170 do {
171 r = sqlite3_step(stmt);
172 } while (r == SQLITE_BUSY);
173
174 // Set return code
175 r = (r == SQLITE_OK);
176
177ERROR:
178 if (stmt)
179 sqlite3_finalize(stmt);
180
181 return r;
182}
183
c745fb2d
MT
184static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
185 sqlite3_stmt* stmt = NULL;
186 int r;
187
7b4df765
MT
188 DEBUG(db->pakfire, "Setting %s to '%d'\n", key, val);
189
c745fb2d
MT
190 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
191 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
192
193 // Prepare statement
194 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
195 if (r != SQLITE_OK) {
196 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
197 sql, sqlite3_errmsg(db->handle));
198 return 1;
199 }
200
201 // Bind key
202 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
203 if (r != SQLITE_OK) {
204 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
205 goto ERROR;
206 }
207
208 // Bind val
209 r = sqlite3_bind_int64(stmt, 2, val);
210 if (r != SQLITE_OK) {
211 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
212 goto ERROR;
213 }
214
215 // Execute the statement
216 do {
217 r = sqlite3_step(stmt);
218 } while (r == SQLITE_BUSY);
219
220 // Set return code
221 r = (r == SQLITE_OK);
222
223ERROR:
224 if (stmt)
225 sqlite3_finalize(stmt);
226
227 return r;
228}
229
7b4df765
MT
230static time_t pakfire_read_modification_time(struct pakfire_db* db) {
231 time_t t = 0;
232
233 // Fetch the value from the database
234 sqlite3_value* value = pakfire_db_get(db, "last_modified_at");
235 if (value) {
236 t = sqlite3_value_int64(value);
237 sqlite3_value_free(value);
238 } else {
239 DEBUG(db->pakfire, "Could not find last modification timestamp\n");
240 }
241
242 return t;
243}
244
245static int pakfire_update_modification_time(struct pakfire_db* db) {
246 // Get the current time in UTC
247 time_t t = time(NULL);
248
249 // Store it in the database
250 int r = pakfire_db_set_int(db, "last_modified_at", t);
251 if (r)
252 return r;
253
254 // Update the last modification timestamp
255 db->last_modified_at = t;
256
257 return r;
258}
259
260static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
261 int r;
262
263 DEBUG(db->pakfire, "Executing database query: %s\n", stmt);
264
265 do {
266 r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
267 } while (r == SQLITE_BUSY);
268
269 // Log any errors
270 if (r) {
271 ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
272 }
273
274 return r;
275}
276
277static int pakfire_db_begin_transaction(struct pakfire_db* db) {
278 return pakfire_db_execute(db, "BEGIN TRANSACTION");
279}
280
281static int pakfire_db_commit(struct pakfire_db* db) {
282 /*
283 If the database was opened in read-write mode, we will store the
284 timestamp of the latest modification to compare whether the database
285 has been changed mid-transaction.
286 */
287 if (db->mode == PAKFIRE_DB_READWRITE) {
288 int r = pakfire_update_modification_time(db);
289 if (r)
290 return r;
291 }
292
293 return pakfire_db_execute(db, "COMMIT");
294}
295
296static int pakfire_db_rollback(struct pakfire_db* db) {
297 return pakfire_db_execute(db, "ROLLBACK");
298}
299
300/*
301 This function performs any fast optimization and tries to truncate the WAL log file
302 to keep the database as compact as possible on disk.
303*/
304static void pakfire_db_optimize(struct pakfire_db* db) {
305 pakfire_db_execute(db, "PRAGMA optimize");
306 pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
307}
308
309static void pakfire_db_free(struct pakfire_db* db) {
310 if (db->handle) {
311 // Optimize the database before it is being closed
312 pakfire_db_optimize(db);
313
314 // Close database handle
315 int r = sqlite3_close(db->handle);
316 if (r != SQLITE_OK) {
317 ERROR(db->pakfire, "Could not close database handle: %s\n",
318 sqlite3_errmsg(db->handle));
319 }
320 }
321
322 pakfire_unref(db->pakfire);
323
324 free(db);
325}
326
c745fb2d
MT
327static int pakfire_db_get_schema(struct pakfire_db* db) {
328 sqlite3_value* value = pakfire_db_get(db, "schema");
329 if (!value)
f168dd0c 330 return -1;
c745fb2d
MT
331
332 int schema = sqlite3_value_int64(value);
333 sqlite3_value_free(value);
334
335 DEBUG(db->pakfire, "Database has schema version %d\n", schema);
336
337 return schema;
338}
339
340static int pakfire_db_create_schema(struct pakfire_db* db) {
341 int r;
342
343 // Create settings table
344 r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)");
345 if (r)
346 return 1;
347
348 // settings: Add a unique index on key
349 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)");
350 if (r)
351 return 1;
352
704b3993
MT
353 // Create packages table
354 r = pakfire_db_execute(db,
355 "CREATE TABLE IF NOT EXISTS packages("
35b82e84
MT
356 "id INTEGER PRIMARY KEY, "
357 "name TEXT, "
358 "evr TEXT, "
359 "arch TEXT, "
360 "groups TEXT, "
361 "filename TEXT, "
362 "size INTEGER, "
363 "inst_size INTEGER, "
df824b86
MT
364 "digest_type INTEGER, "
365 "digest BLOB, "
35b82e84
MT
366 "license TEXT, "
367 "summary TEXT, "
368 "description TEXT, "
369 "uuid TEXT, "
370 "vendor TEXT, "
371 "build_host TEXT, "
372 "build_time INTEGER, "
373 "installed INTEGER, "
374 "userinstalled INTEGER, "
375 "repository TEXT, "
376 "source_name TEXT, "
377 "source_evr TEXT, "
378 "source_arch TEXT, "
379 "distribution TEXT"
704b3993
MT
380 ")");
381 if (r)
382 return 1;
383
384 // packages: Create index to find package by name
385 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS packages_name ON packages(name)");
386 if (r)
387 return 1;
388
00fd98ff
MT
389 // packages: Create unique index over UUID
390 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS packages_uuid ON packages(uuid)");
391 if (r)
392 return 1;
393
2359ca14
MT
394 // Create dependencies table
395 r = pakfire_db_execute(db,
396 "CREATE TABLE IF NOT EXISTS dependencies("
397 "pkg INTEGER, "
398 "type TEXT, "
46257c5f 399 "dependency TEXT, "
432a328a 400 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
2359ca14
MT
401 ")");
402 if (r)
403 return r;
404
405 // dependencies: Add index over packages
406 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS dependencies_pkg_index ON dependencies(pkg)");
407 if (r)
408 return r;
409
68036506
MT
410 // Create files table
411 r = pakfire_db_execute(db,
412 "CREATE TABLE IF NOT EXISTS files("
a3845369
MT
413 "id INTEGER PRIMARY KEY, "
414 "path TEXT, "
415 "pkg INTEGER, "
416 "size INTEGER, "
417 "config INTEGER, "
418 "datafile INTEGER, "
419 "mode INTEGER, "
ca8fe553
MT
420 "uname TEXT, "
421 "gname TEXT, "
a3845369
MT
422 "ctime INTEGER, "
423 "mtime INTEGER, "
210aabe9 424 "mimetype TEXT, "
a3845369
MT
425 "capabilities TEXT, "
426 "digest_sha2_512 BLOB, "
427 "digest_sha2_256 BLOB, "
428 "digest_blake2b512 BLOB, "
429 "digest_blake2s256 BLOB, "
430 "digest_sha3_512 BLOB, "
431 "digest_sha3_256 BLOB, "
432a328a 432 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
68036506
MT
433 ")");
434 if (r)
435 return 1;
436
437 // files: Add index over packages
438 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
439 if (r)
440 return 1;
441
ab1aa17a
MT
442 // files: Add index over path
443 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_path_index ON files(path)");
444 if (r)
445 return 1;
446
d83414aa
MT
447 // Create scriptlets table
448 r = pakfire_db_execute(db,
449 "CREATE TABLE IF NOT EXISTS scriptlets("
450 "id INTEGER PRIMARY KEY, "
451 "pkg INTEGER, "
265f539a 452 "type TEXT, "
46257c5f 453 "scriptlet TEXT, "
432a328a 454 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
d83414aa
MT
455 ")");
456 if (r)
457 return 1;
458
459 // scriptlets: Add index over packages
460 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
461 if (r)
462 return 1;
463
652f2a99 464 const char* arch = pakfire_get_effective_arch(db->pakfire);
33b38daa
MT
465
466 // Set architecture
467 r = pakfire_db_set_string(db, "arch", arch);
468 if (r) {
469 ERROR(db->pakfire, "Could not set architecture\n");
470 return r;
471 }
472
c745fb2d
MT
473 return 0;
474}
475
46257c5f 476static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
5ba550fe
MT
477 // packages: Drop build_id column
478
46257c5f
MT
479 // Add foreign keys
480 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
481 // need to recreate the whole table and rename it afterwards. Annoying.
482
483 return 0;
484}
485
c745fb2d
MT
486static int pakfire_db_migrate_schema(struct pakfire_db* db) {
487 int r;
488
489 while (db->schema < CURRENT_SCHEMA) {
490 // Begin a new transaction
491 r = pakfire_db_begin_transaction(db);
492 if (r)
493 goto ROLLBACK;
494
495 switch (db->schema) {
496 // No schema exists
f168dd0c 497 case -1:
c745fb2d
MT
498 r = pakfire_db_create_schema(db);
499 if (r)
500 goto ROLLBACK;
501
502 db->schema = CURRENT_SCHEMA;
503 break;
504
46257c5f
MT
505 case 7:
506 r = pakfire_db_migrate_to_schema_8(db);
507 if (r)
508 goto ROLLBACK;
509
510 db->schema++;
511 break;
512
c745fb2d
MT
513 default:
514 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
515 goto ROLLBACK;
516 }
517
518 // Update the schema version
519 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
520 if (r)
521 goto ROLLBACK;
522
523 // All done, commit!
524 r = pakfire_db_commit(db);
525 if (r)
526 goto ROLLBACK;
527 }
528
529 return 0;
530
531ROLLBACK:
532 pakfire_db_rollback(db);
533
534 return 1;
535}
536
33b38daa
MT
537static int pakfire_db_check_arch(struct pakfire_db* db) {
538 int r = 1;
539
540 // Fetch database architecture
541 char* db_arch = pakfire_db_get_string(db, "arch");
542 if (!db_arch) {
543 ERROR(db->pakfire, "Database is of an unknown architecture\n");
544 goto ERROR;
545 }
546
547 // Fetch the running architecture
652f2a99 548 const char* arch = pakfire_get_effective_arch(db->pakfire);
33b38daa
MT
549 if (!arch)
550 goto ERROR;
551
552 // They should match
553 if (strcmp(db_arch, arch) == 0)
554 r = 0;
555
556ERROR:
557 if (db_arch)
558 free(db_arch);
559
560 return r;
561}
562
9c5938ea 563static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
564 int r;
565
9c5938ea
MT
566 // Setup logging
567 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
568
46257c5f
MT
569 // Enable foreign keys
570 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
571
0076c50d
MT
572 // Make LIKE case-sensitive
573 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
574
c745fb2d
MT
575 // Fetch the current schema
576 db->schema = pakfire_db_get_schema(db);
577
578 // Check if the schema is recent enough
579 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
580 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
581 db->schema);
582 return 1;
583 }
584
7b4df765
MT
585 // Read modification timestamp
586 db->last_modified_at = pakfire_read_modification_time(db);
587
588 DEBUG(db->pakfire, "The database was last modified at %ld\n", db->last_modified_at);
589
9c5938ea
MT
590 // Done when not in read-write mode
591 if (db->mode != PAKFIRE_DB_READWRITE)
592 return 0;
593
0076c50d
MT
594 // Disable secure delete
595 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
596
25753290
MT
597 // Set database journal to WAL
598 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
599 if (r != SQLITE_OK) {
600 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
601 sqlite3_errmsg(db->handle));
602 return 1;
603 }
604
605 // Disable autocheckpoint
606 r = sqlite3_wal_autocheckpoint(db->handle, 0);
607 if (r != SQLITE_OK) {
608 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
609 sqlite3_errmsg(db->handle));
610 return 1;
611 }
612
c745fb2d
MT
613 // Create or migrate schema
614 r = pakfire_db_migrate_schema(db);
615 if (r)
616 return r;
9c5938ea
MT
617
618 return 0;
619}
620
ac4c607b 621int pakfire_db_open(struct pakfire_db** db, struct pakfire* pakfire, int flags) {
26affd69
MT
622 int r = 1;
623
90312f5c 624 struct pakfire_db* o = calloc(1, sizeof(*o));
33d55ab4
MT
625 if (!o)
626 return -ENOMEM;
627
33d55ab4
MT
628 o->pakfire = pakfire_ref(pakfire);
629 o->nrefs = 1;
630
26affd69
MT
631 int sqlite3_flags = 0;
632
633 // Store mode & forward it to sqlite3
634 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 635 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
636 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
637 } else {
77a4b3a3 638 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
639 sqlite3_flags |= SQLITE_OPEN_READONLY;
640 }
641
642 // Make the filename
77e26129
MT
643 r = pakfire_path(o->pakfire, o->path, "%s", DATABASE_PATH);
644 if (r)
26affd69
MT
645 goto END;
646
647 // Try to open the sqlite3 database file
097b6ca6 648 r = sqlite3_open_v2(o->path, &o->handle, sqlite3_flags, NULL);
26affd69
MT
649 if (r != SQLITE_OK) {
650 ERROR(pakfire, "Could not open database %s: %s\n",
097b6ca6 651 o->path, sqlite3_errmsg(o->handle));
26affd69
MT
652
653 r = 1;
654 goto END;
655 }
77a4b3a3 656
9c5938ea
MT
657 // Setup the database
658 r = pakfire_db_setup(o);
659 if (r)
660 goto END;
661
33b38daa
MT
662 // Check for compatible architecture
663 r = pakfire_db_check_arch(o);
664 if (r)
665 goto END;
666
33d55ab4 667 *db = o;
26affd69
MT
668 r = 0;
669
670END:
671 if (r)
672 pakfire_db_free(o);
33d55ab4 673
26affd69 674 return r;
33d55ab4
MT
675}
676
9c78c483 677struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
33d55ab4
MT
678 db->nrefs++;
679
680 return db;
681}
682
9c78c483 683struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
33d55ab4
MT
684 if (--db->nrefs > 0)
685 return db;
686
687 pakfire_db_free(db);
688
689 return NULL;
690}
eafbe2ce 691
a1571786
MT
692static unsigned long pakfire_db_integrity_check(struct pakfire_db* db) {
693 sqlite3_stmt* stmt = NULL;
694 int r;
695
696 r = sqlite3_prepare_v2(db->handle, "PRAGMA integrity_check", -1, &stmt, NULL);
697 if (r) {
698 ERROR(db->pakfire, "Could not prepare integrity check: %s\n",
699 sqlite3_errmsg(db->handle));
700 return 1;
701 }
702
703 // Count any errors
704 unsigned long errors = 0;
705
706 while (1) {
707 do {
708 r = sqlite3_step(stmt);
709 } while (r == SQLITE_BUSY);
710
711 if (r == SQLITE_ROW) {
712 const char* error = (const char*)sqlite3_column_text(stmt, 0);
713
714 // If the message is "ok", the database has passed the check
715 if (strcmp(error, "ok") == 0)
716 continue;
717
718 // Increment error counter
719 errors++;
720
721 // Log the message
722 ERROR(db->pakfire, "%s\n", error);
723
724 // Break on anything else
725 } else
726 break;
727 }
728
729 sqlite3_finalize(stmt);
730
731 if (errors)
732 ERROR(db->pakfire, "Database integrity check failed\n");
733 else
734 INFO(db->pakfire, "Database integrity check passed\n");
735
736 return errors;
737}
738
739static unsigned long pakfire_db_foreign_key_check(struct pakfire_db* db) {
740 sqlite3_stmt* stmt = NULL;
741 int r;
742
743 r = sqlite3_prepare_v2(db->handle, "PRAGMA foreign_key_check", -1, &stmt, NULL);
744 if (r) {
745 ERROR(db->pakfire, "Could not prepare foreign key check: %s\n",
746 sqlite3_errmsg(db->handle));
747 return 1;
748 }
749
750 // Count any errors
751 unsigned long errors = 0;
752
753 while (1) {
754 do {
755 r = sqlite3_step(stmt);
756 } while (r == SQLITE_BUSY);
757
758 if (r == SQLITE_ROW) {
759 const unsigned char* table = sqlite3_column_text(stmt, 0);
760 unsigned long rowid = sqlite3_column_int64(stmt, 1);
761 const unsigned char* foreign_table = sqlite3_column_text(stmt, 2);
762 unsigned long foreign_rowid = sqlite3_column_int64(stmt, 3);
763
764 // Increment error counter
765 errors++;
766
767 // Log the message
768 ERROR(db->pakfire, "Foreign key violation found in %s, row %lu: "
769 "%lu does not exist in table %s\n", table, rowid, foreign_rowid, foreign_table);
770
771 // Break on anything else
772 } else
773 break;
774 }
775
776 sqlite3_finalize(stmt);
777
778 if (errors)
779 ERROR(db->pakfire, "Foreign key check failed\n");
780 else
781 INFO(db->pakfire, "Foreign key check passed\n");
782
783 return errors;
784}
785
786/*
787 This function performs an integrity check of the database
788*/
9c78c483 789int pakfire_db_check(struct pakfire_db* db) {
a1571786
MT
790 int r;
791
792 // Perform integrity check
793 r = pakfire_db_integrity_check(db);
794 if (r)
795 return 1;
796
797 // Perform foreign key check
798 r = pakfire_db_foreign_key_check(db);
799 if (r)
800 return 1;
801
802 return 0;
803}
804
817757f4 805// Returns the number of packages installed
9c78c483 806ssize_t pakfire_db_packages(struct pakfire_db* db) {
817757f4
MT
807 sqlite3_stmt* stmt = NULL;
808 ssize_t packages = -1;
809
810 int r = sqlite3_prepare_v2(db->handle, "SELECT COUNT(*) FROM packages", -1, &stmt, NULL);
811 if (r) {
812 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
813 sqlite3_errmsg(db->handle));
814 return -1;
815 }
816
817 // Execute query
818 do {
819 r = sqlite3_step(stmt);
820 } while (r == SQLITE_BUSY);
821
822 if (r == SQLITE_ROW) {
823 packages = sqlite3_column_int64(stmt, 0);
824 }
825
826 sqlite3_finalize(stmt);
827
828 return packages;
829}
830
ac4c607b 831static void pakfire_db_add_userinstalled(struct pakfire* pakfire, const char* name) {
c9c03e6a
MT
832 Pool* pool = pakfire_get_solv_pool(pakfire);
833
834 // Convert name to ID
835 Id id = pool_str2id(pool, name, 1);
836
837 // Append it to pooljobs
838 queue_push2(&pool->pooljobs, SOLVER_USERINSTALLED|SOLVER_SOLVABLE_NAME, id);
839}
840
31480bee 841static int pakfire_db_add_dependencies(struct pakfire_db* db, unsigned long id, struct pakfire_package* pkg) {
1fb2b526 842 sqlite3_stmt* stmt = NULL;
6f3fad3b 843 char** list = NULL;
1fb2b526
MT
844 int r = 1;
845
846 const char* sql = "INSERT INTO dependencies(pkg, type, dependency) VALUES(?, ?, ?)";
847
848 // Prepare the statement
849 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
850 if (r) {
851 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
852 sql, sqlite3_errmsg(db->handle));
853 goto END;
854 }
855
6f3fad3b
MT
856 for (const struct pakfire_dep* dep = pakfire_deps; dep->key; dep++) {
857 list = pakfire_package_get_deps(pkg, dep->key);
858 if (!list) {
859 r = 1;
860 goto END;
861 }
1fb2b526 862
6f3fad3b 863 for (char** d = list; *d; d++) {
1fb2b526
MT
864 // Bind package ID
865 r = sqlite3_bind_int64(stmt, 1, id);
866 if (r) {
867 ERROR(db->pakfire, "Could not bind id: %s\n",
868 sqlite3_errmsg(db->handle));
1fb2b526
MT
869 goto END;
870 }
871
872 // Bind type
6f3fad3b 873 r = sqlite3_bind_text(stmt, 2, dep->name, -1, NULL);
1fb2b526
MT
874 if (r) {
875 ERROR(db->pakfire, "Could not bind type: %s\n",
876 sqlite3_errmsg(db->handle));
1fb2b526
MT
877 goto END;
878 }
879
880 // Bind dependency
6f3fad3b 881 r = sqlite3_bind_text(stmt, 3, *d, -1, NULL);
1fb2b526
MT
882 if (r) {
883 ERROR(db->pakfire, "Could not bind dependency: %s\n",
884 sqlite3_errmsg(db->handle));
1fb2b526
MT
885 goto END;
886 }
887
888 // Execute query
889 do {
890 r = sqlite3_step(stmt);
891 } while (r == SQLITE_BUSY);
892
1fb2b526
MT
893 // Reset bound values
894 sqlite3_reset(stmt);
895 }
1fb2b526
MT
896 }
897
898 // All okay
899 r = 0;
900
901END:
902 if (stmt)
903 sqlite3_finalize(stmt);
6f3fad3b
MT
904 if (list) {
905 for (char** dep = list; *dep; dep++)
727f2721 906 free(*dep);
6f3fad3b
MT
907 free(list);
908 }
1fb2b526
MT
909
910 return r;
911}
912
a3845369
MT
913static int pakfire_db_bind_digest(struct pakfire_db* db, sqlite3_stmt* stmt, const int field,
914 struct pakfire_file* file, const enum pakfire_digest_types type) {
915 const unsigned char* digest = NULL;
916 size_t length = 0;
917
918 // Fetch the digest
919 digest = pakfire_file_get_digest(file, type, &length);
920
921 // If this digest isn't set, just bind NULL
922 if (!digest)
923 return sqlite3_bind_null(stmt, field);
924
925 // Otherwise bind the data blob
926 return sqlite3_bind_blob(stmt, field, digest, length, NULL);
927}
928
900faa2f 929static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
f5c77233 930 sqlite3_stmt* stmt = NULL;
dccd04a4 931 int r = 1;
f5c77233
MT
932
933 // Get the filelist from the archive
1bbbfb9e 934 struct pakfire_filelist* filelist = pakfire_archive_get_filelist(archive);
5e9463ec 935 if (!filelist) {
f5c77233
MT
936 ERROR(db->pakfire, "Could not fetch filelist from archive\n");
937 return 1;
938 }
939
5e9463ec 940 // Nothing to do if the list is empty
9a6e3e2d
MT
941 if (pakfire_filelist_is_empty(filelist)) {
942 r = 0;
5e9463ec 943 goto END;
9a6e3e2d 944 }
5e9463ec 945
a3845369
MT
946 const char* sql =
947 "INSERT INTO "
948 " files("
949 "pkg, "
950 "path, "
951 "size, "
952 "config, "
953 "datafile, "
954 "mode, "
df824b86
MT
955 "uname, "
956 "gname, "
a3845369
MT
957 "ctime, "
958 "mtime, "
210aabe9 959 "mimetype, "
a3845369
MT
960 "capabilities, "
961 "digest_sha2_512, "
962 "digest_sha2_256, "
963 "digest_blake2b512, "
964 "digest_blake2s256, "
965 "digest_sha3_512, "
966 "digest_sha3_256"
967 ") "
210aabe9 968 "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
f5c77233
MT
969
970 // Prepare the statement
923d6794 971 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
f5c77233
MT
972 if (r) {
973 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
974 sql, sqlite3_errmsg(db->handle));
975 goto END;
976 }
977
94ff3014 978 for (unsigned int i = 0; i < pakfire_filelist_length(filelist); i++) {
5803b5f6 979 struct pakfire_file* file = pakfire_filelist_get(filelist, i);
5e9463ec 980
f5c77233
MT
981 // Bind package ID
982 r = sqlite3_bind_int64(stmt, 1, id);
983 if (r) {
984 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 985 pakfire_file_unref(file);
f5c77233
MT
986 goto END;
987 }
988
989 // Bind name
32485f6c 990 const char* path = pakfire_file_get_path(file);
f5c77233 991
32485f6c 992 r = sqlite3_bind_text(stmt, 2, path, -1, NULL);
f5c77233 993 if (r) {
32485f6c 994 ERROR(db->pakfire, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 995 pakfire_file_unref(file);
f5c77233
MT
996 goto END;
997 }
998
999 // Bind size
1000 size_t size = pakfire_file_get_size(file);
1001
1002 r = sqlite3_bind_int64(stmt, 3, size);
1003 if (r) {
1004 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1005 pakfire_file_unref(file);
f5c77233
MT
1006 goto END;
1007 }
1008
f5c77233 1009 // Bind config - XXX TODO
b72bae3f 1010 r = sqlite3_bind_null(stmt, 4);
f5c77233
MT
1011 if (r) {
1012 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1013 pakfire_file_unref(file);
f5c77233
MT
1014 goto END;
1015 }
1016
1017 // Bind datafile - XXX TODO
b72bae3f 1018 r = sqlite3_bind_null(stmt, 5);
f5c77233
MT
1019 if (r) {
1020 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1021 pakfire_file_unref(file);
f5c77233
MT
1022 goto END;
1023 }
1024
1025 // Bind mode
1026 mode_t mode = pakfire_file_get_mode(file);
1027
b72bae3f 1028 r = sqlite3_bind_int64(stmt, 6, mode);
f5c77233
MT
1029 if (r) {
1030 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1031 pakfire_file_unref(file);
f5c77233
MT
1032 goto END;
1033 }
1034
302e3253
MT
1035 // Bind uname
1036 const char* uname = pakfire_file_get_uname(file);
f5c77233 1037
302e3253 1038 r = sqlite3_bind_text(stmt, 7, uname, -1, NULL);
f5c77233 1039 if (r) {
302e3253 1040 ERROR(db->pakfire, "Could not bind uname: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1041 pakfire_file_unref(file);
f5c77233
MT
1042 goto END;
1043 }
1044
302e3253
MT
1045 // Bind gname
1046 const char* gname = pakfire_file_get_gname(file);
f5c77233 1047
302e3253 1048 r = sqlite3_bind_text(stmt, 8, gname, -1, NULL);
f5c77233 1049 if (r) {
302e3253 1050 ERROR(db->pakfire, "Could not bind gname: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1051 pakfire_file_unref(file);
f5c77233
MT
1052 goto END;
1053 }
1054
ef4e8460
MT
1055 // Bind ctime
1056 time_t ctime = pakfire_file_get_ctime(file);
1057
a7e5cf06 1058 r = sqlite3_bind_int64(stmt, 9, ctime);
ef4e8460
MT
1059 if (r) {
1060 ERROR(db->pakfire, "Could not bind ctime: %s\n", sqlite3_errmsg(db->handle));
1061 pakfire_file_unref(file);
1062 goto END;
1063 }
1064
f5c77233 1065 // Bind mtime
ef4e8460 1066 time_t mtime = pakfire_file_get_mtime(file);
f5c77233 1067
a7e5cf06 1068 r = sqlite3_bind_int64(stmt, 10, mtime);
f5c77233
MT
1069 if (r) {
1070 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1071 pakfire_file_unref(file);
f5c77233
MT
1072 goto END;
1073 }
1074
210aabe9
MT
1075 // Bind MIME type
1076 const char* mimetype = pakfire_file_get_mimetype(file);
1077
1078 if (mimetype) {
1079 r = sqlite3_bind_text(stmt, 11, mimetype, -1, NULL);
1080 if (r) {
1081 ERROR(db->pakfire, "Could not bind MIME type: %s\n",
1082 sqlite3_errmsg(db->handle));
1083 pakfire_file_unref(file);
1084 goto END;
1085 }
1086 } else {
1087 r = sqlite3_bind_null(stmt, 11);
1088 if (r) {
1089 ERROR(db->pakfire, "Could not bind an empty MIME type: %s\n",
1090 sqlite3_errmsg(db->handle));
1091 pakfire_file_unref(file);
1092 goto END;
1093 }
1094 }
1095
f5c77233 1096 // Bind capabilities - XXX TODO
210aabe9 1097 r = sqlite3_bind_null(stmt, 12);
f5c77233
MT
1098 if (r) {
1099 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1100 pakfire_file_unref(file);
f5c77233
MT
1101 goto END;
1102 }
1103
a3845369 1104 // SHA2-512 Digest
210aabe9 1105 r = pakfire_db_bind_digest(db, stmt, 13, file, PAKFIRE_DIGEST_SHA2_512);
a3845369
MT
1106 if (r) {
1107 ERROR(db->pakfire, "Could not bind SHA2-512 digest: %s\n",
1108 sqlite3_errmsg(db->handle));
1109 pakfire_file_unref(file);
1110 goto END;
1111 }
923d6794 1112
a3845369 1113 // SHA2-256 Digest
210aabe9 1114 r = pakfire_db_bind_digest(db, stmt, 14, file, PAKFIRE_DIGEST_SHA2_256);
a3845369
MT
1115 if (r) {
1116 ERROR(db->pakfire, "Could not bind SHA2-256 digest: %s\n",
1117 sqlite3_errmsg(db->handle));
1118 pakfire_file_unref(file);
1119 goto END;
923d6794 1120 }
a3845369
MT
1121
1122 // BLAKE2b512 Digest
210aabe9 1123 r = pakfire_db_bind_digest(db, stmt, 15, file, PAKFIRE_DIGEST_BLAKE2B512);
923d6794 1124 if (r) {
a3845369 1125 ERROR(db->pakfire, "Could not bind BLAKE2b512 digest: %s\n",
923d6794
MT
1126 sqlite3_errmsg(db->handle));
1127 pakfire_file_unref(file);
1128 goto END;
1129 }
1130
a3845369 1131 // BLAKE2s256 Digest
210aabe9 1132 r = pakfire_db_bind_digest(db, stmt, 16, file, PAKFIRE_DIGEST_BLAKE2S256);
a3845369
MT
1133 if (r) {
1134 ERROR(db->pakfire, "Could not bind BLAKE2s256 digest: %s\n",
1135 sqlite3_errmsg(db->handle));
1136 pakfire_file_unref(file);
1137 goto END;
1138 }
923d6794 1139
a3845369 1140 // SHA3-512 Digest
210aabe9 1141 r = pakfire_db_bind_digest(db, stmt, 17, file, PAKFIRE_DIGEST_SHA3_512);
a3845369
MT
1142 if (r) {
1143 ERROR(db->pakfire, "Could not bind SHA3-512 digest: %s\n",
1144 sqlite3_errmsg(db->handle));
1145 pakfire_file_unref(file);
1146 goto END;
923d6794 1147 }
a3845369
MT
1148
1149 // SHA3-256 Digest
210aabe9 1150 r = pakfire_db_bind_digest(db, stmt, 18, file, PAKFIRE_DIGEST_SHA3_256);
923d6794 1151 if (r) {
a3845369 1152 ERROR(db->pakfire, "Could not bind SHA3-256 digest: %s\n",
923d6794
MT
1153 sqlite3_errmsg(db->handle));
1154 pakfire_file_unref(file);
1155 goto END;
1156 }
1157
f5c77233
MT
1158 // Execute query
1159 do {
1160 r = sqlite3_step(stmt);
1161 } while (r == SQLITE_BUSY);
1162
5bae3112
MT
1163 // Check for errors
1164 if (r != SQLITE_DONE) {
1165 ERROR(db->pakfire, "Could not add file to database: %s\n",
1166 sqlite3_errmsg(db->handle));
a7e5cf06 1167 pakfire_file_unref(file);
5bae3112
MT
1168 goto END;
1169 }
1170
a7e5cf06
MT
1171 // Move on to next file
1172 pakfire_file_unref(file);
1173
1174 // Reset bound values
1175 sqlite3_reset(stmt);
f5c77233
MT
1176 }
1177
1178 // All okay
1179 r = 0;
1180
1181END:
1182 if (stmt)
1183 sqlite3_finalize(stmt);
5e9463ec
MT
1184 pakfire_filelist_unref(filelist);
1185
f5c77233
MT
1186 return r;
1187}
1188
900faa2f 1189static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
265f539a 1190 sqlite3_stmt* stmt = NULL;
a0097ba2 1191 size_t size;
265f539a
MT
1192 int r = 1;
1193
265f539a
MT
1194 const char* sql = "INSERT INTO scriptlets(pkg, type, scriptlet) VALUES(?, ?, ?)";
1195
1196 // Prepare the statement
1197 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
1198 if (r) {
1199 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1200 sql, sqlite3_errmsg(db->handle));
1201 goto END;
1202 }
1203
a0097ba2 1204 for (const char** type = pakfire_scriptlet_types; *type; type++) {
265f539a 1205 // Fetch the scriptlet
106d2edd 1206 struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(archive, *type);
a0097ba2 1207 if (!scriptlet)
265f539a 1208 continue;
265f539a
MT
1209
1210 // Bind package ID
1211 r = sqlite3_bind_int64(stmt, 1, id);
1212 if (r) {
1213 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1214 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1215 goto END;
1216 }
1217
1218 // Bind handle
a0097ba2 1219 r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
265f539a
MT
1220 if (r) {
1221 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1222 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1223 goto END;
1224 }
1225
a0097ba2
MT
1226 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
1227
265f539a 1228 // Bind scriptlet
a0097ba2 1229 r = sqlite3_bind_text(stmt, 3, data, size, NULL);
265f539a
MT
1230 if (r) {
1231 ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1232 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1233 goto END;
1234 }
1235
1236 // Execute query
1237 do {
1238 r = sqlite3_step(stmt);
1239 } while (r == SQLITE_BUSY);
1240
5bae3112
MT
1241 // Check for errors
1242 if (r != SQLITE_DONE) {
1243 ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
1244 sqlite3_errmsg(db->handle));
a0097ba2 1245 pakfire_scriptlet_unref(scriptlet);
5bae3112
MT
1246 goto END;
1247 }
1248
a0097ba2
MT
1249 pakfire_scriptlet_unref(scriptlet);
1250
265f539a
MT
1251 // Reset bound values
1252 sqlite3_reset(stmt);
265f539a
MT
1253 }
1254
1255 // All okay
1256 r = 0;
1257
1258END:
1259 if (stmt)
1260 sqlite3_finalize(stmt);
1261
1262 return r;
1263}
1264
9c78c483 1265int pakfire_db_add_package(struct pakfire_db* db,
900faa2f 1266 struct pakfire_package* pkg, struct pakfire_archive* archive, int userinstalled) {
e49b93d1
MT
1267 sqlite3_stmt* stmt = NULL;
1268 int r;
1269
d333480c
MT
1270 char** groups = NULL;
1271 char* __groups = NULL;
1272
e49b93d1
MT
1273 // Begin a new transaction
1274 r = pakfire_db_begin_transaction(db);
1275 if (r)
687961c3 1276 goto ERROR;
e49b93d1 1277
571539a7
MT
1278 const char* sql = "INSERT INTO "
1279 "packages("
1280 "name, "
1281 "evr, "
1282 "arch, "
1283 "groups, "
1284 "filename, "
1285 "size, "
1286 "inst_size, "
e082fb85 1287 "digest_type, "
571539a7
MT
1288 "digest, "
1289 "license, "
1290 "summary, "
1291 "description, "
1292 "uuid, "
1293 "vendor, "
1294 "build_host, "
1295 "build_time, "
1296 "installed, "
1297 "repository, "
1298 "userinstalled, "
1299 "source_name, "
1300 "source_evr, "
ca002cae
MT
1301 "source_arch, "
1302 "distribution"
571539a7
MT
1303 ") VALUES("
1304 "?, "
1305 "?, "
1306 "?, "
1307 "?, "
1308 "?, "
1309 "?, "
1310 "?, "
1311 "?, "
1312 "?, "
1313 "?, "
1314 "?, "
1315 "?, "
1316 "?, "
1317 "?, "
1318 "?, "
e082fb85 1319 "?, "
571539a7
MT
1320 "CURRENT_TIMESTAMP, "
1321 "?, "
1322 "?, "
1323 "?, "
1324 "?, "
ca002cae 1325 "?, "
571539a7
MT
1326 "?"
1327 ")";
e49b93d1
MT
1328
1329 // Prepare the statement
1330 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1331 if (r != SQLITE_OK) {
1332 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1333 sql, sqlite3_errmsg(db->handle));
687961c3 1334 goto ERROR;
e49b93d1
MT
1335 }
1336
1337 // Bind name
74468e4f 1338 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
e49b93d1
MT
1339
1340 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
1341 if (r) {
1342 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
687961c3 1343 goto ERROR;
e49b93d1
MT
1344 }
1345
6ed66687 1346 // Bind evr
74468e4f 1347 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
e49b93d1 1348
6ed66687 1349 r = sqlite3_bind_text(stmt, 2, evr, -1, NULL);
e49b93d1 1350 if (r) {
6ed66687 1351 ERROR(db->pakfire, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
687961c3 1352 goto ERROR;
e49b93d1
MT
1353 }
1354
1355 // Bind arch
74468e4f 1356 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
e49b93d1 1357
6ed66687 1358 r = sqlite3_bind_text(stmt, 3, arch, -1, NULL);
e49b93d1
MT
1359 if (r) {
1360 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
687961c3 1361 goto ERROR;
e49b93d1
MT
1362 }
1363
1364 // Bind groups
d333480c 1365 groups = pakfire_package_get_strings(pkg, PAKFIRE_PKG_GROUPS);
1eb7f40b 1366 if (groups) {
d333480c
MT
1367 // Join everything together as SQLite doesn't support arrays
1368 __groups = pakfire_string_join(groups, " ");
1369 if (!__groups) {
1370 r = 1;
1371 goto ERROR;
1372 }
1373
1374 r = sqlite3_bind_text(stmt, 4, __groups, -1, NULL);
1eb7f40b
MT
1375 if (r) {
1376 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
687961c3 1377 goto ERROR;
1eb7f40b 1378 }
e49b93d1 1379
1eb7f40b
MT
1380 // No groups
1381 } else {
6ed66687 1382 r = sqlite3_bind_null(stmt, 4);
1eb7f40b 1383 if (r)
687961c3 1384 goto ERROR;
e49b93d1
MT
1385 }
1386
1387 // Bind filename
0aade652 1388 const char* filename = pakfire_package_get_string(pkg, PAKFIRE_PKG_FILENAME);
e49b93d1 1389
6ed66687 1390 r = sqlite3_bind_text(stmt, 5, filename, -1, NULL);
e49b93d1
MT
1391 if (r) {
1392 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
687961c3 1393 goto ERROR;
e49b93d1
MT
1394 }
1395
1396 // Bind size
3f327c3c 1397 unsigned long long size = pakfire_package_get_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, 0);
e49b93d1 1398
6ed66687 1399 r = sqlite3_bind_int64(stmt, 6, size);
e49b93d1
MT
1400 if (r) {
1401 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
687961c3 1402 goto ERROR;
e49b93d1
MT
1403 }
1404
1405 // Bind installed size
3f327c3c 1406 unsigned long long inst_size = pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLSIZE, 0);
e49b93d1 1407
6ed66687 1408 r = sqlite3_bind_int64(stmt, 7, inst_size);
e49b93d1
MT
1409 if (r) {
1410 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
687961c3 1411 goto ERROR;
e49b93d1
MT
1412 }
1413
e082fb85 1414 const unsigned char* digest = NULL;
c52e0148 1415 enum pakfire_digest_types digest_type = 0;
e082fb85 1416 size_t digest_length = 0;
b28af23a 1417
e082fb85
MT
1418 // Fetch the digest
1419 digest = pakfire_package_get_digest(pkg, &digest_type, &digest_length);
1420 if (!digest) {
1421 ERROR(db->pakfire, "Could not fetch the package's digest: %m\n");
1422 r = 1;
1423 goto ERROR;
1424 }
e49b93d1 1425
e082fb85
MT
1426 // Set the digest type
1427 r = sqlite3_bind_int64(stmt, 8, digest_type);
1428 if (r) {
1429 ERROR(db->pakfire, "Could not bind digest type: %s\n", sqlite3_errmsg(db->handle));
1430 goto ERROR;
1431 }
1432
1433 // Set the digest
1434 r = sqlite3_bind_blob(stmt, 9, digest, digest_length, NULL);
1435 if (r) {
1436 ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle));
1437 goto ERROR;
e49b93d1
MT
1438 }
1439
1440 // Bind license
74468e4f 1441 const char* license = pakfire_package_get_string(pkg, PAKFIRE_PKG_LICENSE);
e49b93d1 1442
e082fb85 1443 r = sqlite3_bind_text(stmt, 10, license, -1, NULL);
e49b93d1
MT
1444 if (r) {
1445 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
687961c3 1446 goto ERROR;
e49b93d1
MT
1447 }
1448
1449 // Bind summary
74468e4f 1450 const char* summary = pakfire_package_get_string(pkg, PAKFIRE_PKG_SUMMARY);
e49b93d1 1451
e082fb85 1452 r = sqlite3_bind_text(stmt, 11, summary, -1, NULL);
e49b93d1
MT
1453 if (r) {
1454 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
687961c3 1455 goto ERROR;
e49b93d1
MT
1456 }
1457
1458 // Bind description
74468e4f 1459 const char* description = pakfire_package_get_string(pkg, PAKFIRE_PKG_DESCRIPTION);
e49b93d1 1460
e082fb85 1461 r = sqlite3_bind_text(stmt, 12, description, -1, NULL);
e49b93d1
MT
1462 if (r) {
1463 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
687961c3 1464 goto ERROR;
e49b93d1
MT
1465 }
1466
1467 // Bind uuid
74468e4f 1468 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
e49b93d1 1469
e082fb85 1470 r = sqlite3_bind_text(stmt, 13, uuid, -1, NULL);
e49b93d1
MT
1471 if (r) {
1472 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
687961c3 1473 goto ERROR;
e49b93d1
MT
1474 }
1475
1476 // Bind vendor
74468e4f 1477 const char* vendor = pakfire_package_get_string(pkg, PAKFIRE_PKG_VENDOR);
e49b93d1 1478
e082fb85 1479 r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
e49b93d1
MT
1480 if (r) {
1481 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
687961c3 1482 goto ERROR;
e49b93d1
MT
1483 }
1484
e49b93d1 1485 // Bind build_host
1f669e88 1486 const char* build_host = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_HOST);
e49b93d1 1487
e082fb85 1488 r = sqlite3_bind_text(stmt, 15, build_host, -1, NULL);
e49b93d1
MT
1489 if (r) {
1490 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
687961c3 1491 goto ERROR;
e49b93d1
MT
1492 }
1493
1494 // Bind build_time
3f327c3c 1495 time_t build_time = pakfire_package_get_num(pkg, PAKFIRE_PKG_BUILD_TIME, 0);
e49b93d1 1496
e082fb85 1497 r = sqlite3_bind_int64(stmt, 16, build_time);
e49b93d1
MT
1498 if (r) {
1499 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
687961c3 1500 goto ERROR;
e49b93d1
MT
1501 }
1502
1503 // Bind repository name
4651122b 1504 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
e49b93d1
MT
1505 if (repo) {
1506 const char* repo_name = pakfire_repo_get_name(repo);
1507 pakfire_repo_unref(repo);
1508
e082fb85 1509 r = sqlite3_bind_text(stmt, 17, repo_name, -1, NULL);
e49b93d1 1510 if (r)
687961c3 1511 goto ERROR;
e49b93d1
MT
1512
1513 // No repository?
1514 } else {
e082fb85 1515 r = sqlite3_bind_null(stmt, 17);
e49b93d1 1516 if (r)
687961c3 1517 goto ERROR;
e49b93d1
MT
1518 }
1519
dc0cae14 1520 // installed by the user?
e082fb85 1521 r = sqlite3_bind_int(stmt, 18, userinstalled);
dc0cae14
MT
1522 if (r) {
1523 ERROR(db->pakfire, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle));
687961c3 1524 goto ERROR;
dc0cae14 1525 }
e49b93d1 1526
571539a7 1527 // Source package name
988ce1bc 1528 const char* source_name = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_NAME);
571539a7 1529 if (source_name) {
e082fb85 1530 r = sqlite3_bind_text(stmt, 19, source_name, -1, NULL);
571539a7
MT
1531 if (r)
1532 goto ERROR;
1533 } else {
e082fb85 1534 r = sqlite3_bind_null(stmt, 19);
571539a7
MT
1535 if (r)
1536 goto ERROR;
1537 }
1538
1539 // Source EVR
988ce1bc 1540 const char* source_evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_EVR);
571539a7 1541 if (source_evr) {
e082fb85 1542 r = sqlite3_bind_text(stmt, 20, source_evr, -1, NULL);
571539a7
MT
1543 if (r)
1544 goto ERROR;
1545 } else {
e082fb85 1546 r = sqlite3_bind_null(stmt, 20);
571539a7
MT
1547 if (r)
1548 goto ERROR;
1549 }
1550
1551 // Source arch
988ce1bc 1552 const char* source_arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_ARCH);
571539a7 1553 if (source_arch) {
e082fb85 1554 r = sqlite3_bind_text(stmt, 21, source_arch, -1, NULL);
571539a7
MT
1555 if (r)
1556 goto ERROR;
1557 } else {
e082fb85 1558 r = sqlite3_bind_null(stmt, 21);
571539a7
MT
1559 if (r)
1560 goto ERROR;
1561 }
1562
ca002cae 1563 // Distribution
74468e4f 1564 const char* distribution = pakfire_package_get_string(pkg, PAKFIRE_PKG_DISTRO);
ca002cae 1565 if (distribution) {
e082fb85 1566 r = sqlite3_bind_text(stmt, 22, distribution, -1, NULL);
ca002cae
MT
1567 if (r)
1568 goto ERROR;
1569 } else {
e082fb85 1570 r = sqlite3_bind_null(stmt, 22);
ca002cae
MT
1571 if (r)
1572 goto ERROR;
1573 }
1574
e49b93d1
MT
1575 // Run query
1576 do {
1577 r = sqlite3_step(stmt);
1578 } while (r == SQLITE_BUSY);
1579
1580 if (r != SQLITE_DONE) {
1581 ERROR(db->pakfire, "Could not add package to database: %s\n",
1582 sqlite3_errmsg(db->handle));
687961c3
MT
1583 r = 1;
1584 goto ERROR;
e49b93d1
MT
1585 }
1586
f5c77233
MT
1587 // Save package ID
1588 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1589
1fb2b526
MT
1590 // Add dependencies
1591 r = pakfire_db_add_dependencies(db, packages_id, pkg);
1592 if (r)
687961c3 1593 goto ERROR;
1fb2b526 1594
f5c77233
MT
1595 // Add files
1596 r = pakfire_db_add_files(db, packages_id, archive);
1597 if (r)
687961c3 1598 goto ERROR;
e49b93d1 1599
265f539a
MT
1600 // Add scriptlets
1601 r = pakfire_db_add_scriptlets(db, packages_id, archive);
1602 if (r)
687961c3 1603 goto ERROR;
e49b93d1 1604
687961c3 1605ERROR:
d333480c
MT
1606 if (groups)
1607 pakfire_strings_free(groups);
1608 if (__groups)
1609 free(groups);
f5c77233
MT
1610 if (stmt)
1611 sqlite3_finalize(stmt);
e49b93d1 1612
687961c3
MT
1613 // Commit or rollback
1614 if (r)
1615 pakfire_db_rollback(db);
1616 else
1617 r = pakfire_db_commit(db);
e49b93d1 1618
687961c3 1619 return r;
eafbe2ce
MT
1620}
1621
31480bee 1622int pakfire_db_remove_package(struct pakfire_db* db, struct pakfire_package* pkg) {
432a328a
MT
1623 sqlite3_stmt* stmt = NULL;
1624 int r = 1;
1625
687961c3
MT
1626 // Begin a new transaction
1627 r = pakfire_db_begin_transaction(db);
1628 if (r)
1629 goto ERROR;
1630
432a328a 1631 // Fetch the package's UUID
74468e4f 1632 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
432a328a
MT
1633 if (!uuid) {
1634 ERROR(db->pakfire, "Package has no UUID\n");
687961c3 1635 r = 1;
432a328a
MT
1636 goto ERROR;
1637 }
1638
1639 r = sqlite3_prepare_v2(db->handle,
1640 "DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
1641 if (r) {
1642 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
1643 sqlite3_errmsg(db->handle));
1644 goto ERROR;
1645 }
1646
1647 // Bind UUID
1648 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1649 if (r) {
1650 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
687961c3 1651 goto ERROR;
432a328a
MT
1652 }
1653
1654 // Execute query
1655 do {
1656 r = sqlite3_step(stmt);
1657 } while (r == SQLITE_BUSY);
1658
1659 // Check if we have been successful
1660 if (r != SQLITE_DONE) {
1661 ERROR(db->pakfire, "Could not delete package %s\n", uuid);
1662 r = 1;
1663 goto ERROR;
1664 }
1665
687961c3 1666 // All done
432a328a
MT
1667 r = 0;
1668
1669ERROR:
1670 if (stmt)
1671 sqlite3_finalize(stmt);
1672
687961c3
MT
1673 // Commit or rollback
1674 if (r)
1675 pakfire_db_rollback(db);
1676 else
1677 r = pakfire_db_commit(db);
1678
432a328a 1679 return r;
eafbe2ce 1680}
f6942b34
MT
1681
1682struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
31480bee 1683 struct pakfire_package* pkg, const char* type) {
f6942b34
MT
1684 struct pakfire_scriptlet* scriptlet = NULL;
1685 sqlite3_stmt* stmt = NULL;
1686 int r = 1;
1687
1688 // Fetch the package's UUID
74468e4f 1689 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
f6942b34
MT
1690 if (!uuid) {
1691 ERROR(db->pakfire, "Package has no UUID\n");
1692 goto ERROR;
1693 }
1694
7bb92ae3 1695 const char* sql = "SELECT scriptlets.scriptlet FROM packages \
f6942b34
MT
1696 JOIN scriptlets ON packages.id = scriptlets.pkg \
1697 WHERE packages.uuid = ? AND scriptlets.type = ?";
1698
1699 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1700 if (r) {
1701 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1702 sql, sqlite3_errmsg(db->handle));
1703 goto ERROR;
1704 }
1705
1706 // Bind UUID
1707 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1708 if (r) {
1709 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1710 goto ERROR;
1711 }
1712
a0097ba2 1713 r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
f6942b34
MT
1714 if (r) {
1715 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
1716 goto ERROR;
1717 }
1718
a0097ba2 1719 DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
f6942b34
MT
1720
1721 // Execute query
1722 do {
1723 r = sqlite3_step(stmt);
1724 } while (r == SQLITE_BUSY);
1725
1726 // We have some payload
1727 if (r == SQLITE_ROW) {
1728 const void* data = sqlite3_column_blob(stmt, 1);
1729 ssize_t size = sqlite3_column_bytes(stmt, 1);
1730
1731 // Create a scriptlet object
a0097ba2
MT
1732 r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
1733 if (r)
f6942b34
MT
1734 goto ERROR;
1735 }
1736
1737ERROR:
1738 if (stmt)
1739 sqlite3_finalize(stmt);
1740
1741 return scriptlet;
1742}
361ca45f 1743
4651122b 1744static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* repo, sqlite3_stmt* stmt) {
31480bee 1745 struct pakfire_package* pkg = NULL;
361ca45f
MT
1746 int r = 1;
1747
1748 // Name
1749 const char* name = (const char*)sqlite3_column_text(stmt, 0);
1750 if (!name) {
1751 ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
1752 goto ERROR;
1753 }
1754
6ed66687
MT
1755 // EVR
1756 const char* evr = (const char*)sqlite3_column_text(stmt, 1);
1757 if (!evr) {
1758 ERROR(db->pakfire, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
361ca45f
MT
1759 goto ERROR;
1760 }
1761
1762 // Arch
6ed66687 1763 const char* arch = (const char*)sqlite3_column_text(stmt, 2);
361ca45f
MT
1764 if (!arch) {
1765 ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
1766 goto ERROR;
1767 }
1768
361ca45f 1769 // Create package
33ad2a01
MT
1770 r = pakfire_package_create(&pkg, db->pakfire, repo, name, evr, arch);
1771 if (r) {
5dee04f3 1772 ERROR(db->pakfire, "Could not create package '%s-%s.%s': %m\n", name, evr, arch);
361ca45f
MT
1773 goto ERROR;
1774 }
1775
ac71886a
MT
1776 // ID
1777 uint64_t id = sqlite3_column_int64(stmt, 3);
3f327c3c
MT
1778 if (id) {
1779 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_DBID, id);
1780 if (r)
1781 goto ERROR;
1782 }
ac71886a 1783
7f826034 1784 // Groups
ac71886a 1785 const char* groups = (const char*)sqlite3_column_text(stmt, 4);
7f826034 1786 if (groups) {
74468e4f
MT
1787 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_GROUPS, groups);
1788 if (r)
1789 goto ERROR;
7f826034
MT
1790 }
1791
1792 // Filename
ac71886a 1793 const char* filename = (const char*)sqlite3_column_text(stmt, 5);
7f826034 1794 if (filename) {
0aade652
MT
1795 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_FILENAME, filename);
1796 if (r)
1797 goto ERROR;
7f826034
MT
1798 }
1799
1800 // Size
ac71886a 1801 size_t size = sqlite3_column_int64(stmt, 6);
7f826034 1802 if (size) {
3f327c3c
MT
1803 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, size);
1804 if (r)
1805 goto ERROR;
7f826034
MT
1806 }
1807
1808 // Installed size
ac71886a 1809 size = sqlite3_column_int64(stmt, 7);
7f826034 1810 if (size) {
3f327c3c
MT
1811 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLSIZE, size);
1812 if (r)
1813 goto ERROR;
7f826034
MT
1814 }
1815
e082fb85
MT
1816 // Digest type
1817 enum pakfire_digest_types digest_type = sqlite3_column_int64(stmt, 8);
1818 size_t digest_length = 0;
b28af23a 1819
e082fb85
MT
1820 // Digest length
1821
1822 // Digest
1823 const unsigned char* digest = sqlite3_column_blob(stmt, 9);
1824 if (digest_type && digest) {
1825 pakfire_package_set_digest(pkg, digest_type, digest, digest_length);
7f826034
MT
1826 }
1827
1828 // License
e082fb85 1829 const char* license = (const char*)sqlite3_column_text(stmt, 10);
7f826034 1830 if (license) {
74468e4f
MT
1831 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_LICENSE, license);
1832 if (r)
1833 goto ERROR;
7f826034
MT
1834 }
1835
1836 // Summary
e082fb85 1837 const char* summary = (const char*)sqlite3_column_text(stmt, 11);
7f826034 1838 if (summary) {
74468e4f
MT
1839 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SUMMARY, summary);
1840 if (r)
1841 goto ERROR;
7f826034
MT
1842 }
1843
1844 // Description
e082fb85 1845 const char* description = (const char*)sqlite3_column_text(stmt, 12);
7f826034 1846 if (description) {
74468e4f
MT
1847 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
1848 if (r)
1849 goto ERROR;
7f826034
MT
1850 }
1851
1852 // UUID
e082fb85 1853 const char* uuid = (const char*)sqlite3_column_text(stmt, 13);
7f826034 1854 if (uuid) {
74468e4f
MT
1855 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_UUID, uuid);
1856 if (r)
1857 goto ERROR;
7f826034
MT
1858 }
1859
1860 // Vendor
e082fb85 1861 const char* vendor = (const char*)sqlite3_column_text(stmt, 14);
7f826034 1862 if (vendor) {
74468e4f
MT
1863 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_VENDOR, vendor);
1864 if (r)
1865 goto ERROR;
7f826034
MT
1866 }
1867
1868 // Build Host
e082fb85 1869 const char* build_host = (const char*)sqlite3_column_text(stmt, 15);
7f826034 1870 if (build_host) {
1f669e88
MT
1871 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_BUILD_HOST, build_host);
1872 if (r)
1873 goto ERROR;
7f826034
MT
1874 }
1875
1876 // Build Time
e082fb85 1877 time_t build_time = sqlite3_column_int64(stmt, 16);
7f826034 1878 if (build_time) {
3f327c3c
MT
1879 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_BUILD_TIME, build_time);
1880 if (r)
1881 goto ERROR;
7f826034
MT
1882 }
1883
af647c55 1884 // Install Time
e082fb85 1885 time_t install_time = sqlite3_column_int64(stmt, 17);
af647c55 1886 if (install_time) {
3f327c3c
MT
1887 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLTIME, install_time);
1888 if (r)
1889 goto ERROR;
af647c55
MT
1890 }
1891
c9c03e6a 1892 // installed by user?
e082fb85 1893 int userinstalled = sqlite3_column_int(stmt, 18);
c9c03e6a
MT
1894 if (userinstalled)
1895 pakfire_db_add_userinstalled(db->pakfire, name);
1896
d995f7fc 1897 // Files
e082fb85 1898 const char* files = (const char*)sqlite3_column_text(stmt, 19);
d995f7fc 1899 if (files) {
d995f7fc
MT
1900 r = pakfire_package_set_filelist_from_string(pkg, files);
1901 if (r)
1902 goto ERROR;
1903 }
1904
24be412a
MT
1905 // Dependencies
1906
1907 const struct dependency {
1908 unsigned int field;
6f3fad3b 1909 const enum pakfire_package_key key;
24be412a 1910 } dependencies[] = {
6f3fad3b
MT
1911 { 20, PAKFIRE_PKG_PROVIDES },
1912 { 21, PAKFIRE_PKG_PREREQUIRES },
1913 { 22, PAKFIRE_PKG_REQUIRES },
1914 { 23, PAKFIRE_PKG_CONFLICTS },
1915 { 24, PAKFIRE_PKG_OBSOLETES },
1916 { 25, PAKFIRE_PKG_RECOMMENDS },
1917 { 26, PAKFIRE_PKG_SUGGESTS },
1918 { 27, PAKFIRE_PKG_SUPPLEMENTS },
1919 { 28, PAKFIRE_PKG_ENHANCES },
1920 { 0 },
24be412a
MT
1921 };
1922
1923 for (const struct dependency* deps = dependencies; deps->field; deps++) {
1924 const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
1925 if (relations) {
6f3fad3b
MT
1926 r = pakfire_str2deps(db->pakfire, pkg, deps->key, relations);
1927 if (r)
1928 goto ERROR;
24be412a
MT
1929 }
1930 }
1931
571539a7 1932 // Source package
e082fb85 1933 const char* source_name = (const char*)sqlite3_column_text(stmt, 29);
988ce1bc
MT
1934 if (source_name) {
1935 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_NAME, source_name);
1936 if (r)
1937 goto ERROR;
1938 }
571539a7
MT
1939
1940 // Source EVR
e082fb85 1941 const char* source_evr = (const char*)sqlite3_column_text(stmt, 30);
988ce1bc
MT
1942 if (source_evr) {
1943 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_EVR, source_evr);
1944 if (r)
1945 goto ERROR;
1946 }
571539a7
MT
1947
1948 // Source arch
e082fb85 1949 const char* source_arch = (const char*)sqlite3_column_text(stmt, 31);
988ce1bc
MT
1950 if (source_arch) {
1951 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_ARCH, source_arch);
1952 if (r)
1953 goto ERROR;
1954 }
571539a7 1955
ca002cae 1956 // Distribution
e082fb85 1957 const char* distribution = (const char*)sqlite3_column_text(stmt, 32);
74468e4f
MT
1958 if (distribution) {
1959 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
1960 if (r)
1961 goto ERROR;
1962 }
ca002cae 1963
361ca45f
MT
1964 // Success
1965 r = 0;
1966
1967ERROR:
361ca45f
MT
1968 if (pkg)
1969 pakfire_package_unref(pkg);
1970
1971 return r;
1972}
1973
4651122b 1974int pakfire_db_load(struct pakfire_db* db, struct pakfire_repo* repo) {
361ca45f
MT
1975 sqlite3_stmt* stmt = NULL;
1976 int r = 1;
1977
1978 DEBUG(db->pakfire, "Loading package database...\n");
1979
7fe22178
MT
1980 // Drop contents of the repository
1981 pakfire_repo_clear(repo);
1982
788221bd
MT
1983 // Save starting time
1984 clock_t t_start = clock();
1985 clock_t t_end;
1986
361ca45f
MT
1987 const char* sql =
1988 "SELECT "
571539a7
MT
1989 "name, "
1990 "evr, "
1991 "arch, "
1992 "id, "
1993 "groups, "
1994 "filename, "
1995 "size, "
1996 "inst_size, "
e082fb85 1997 "digest_type, "
571539a7
MT
1998 "digest, "
1999 "license, "
2000 "summary, "
2001 "description, "
2002 "uuid, "
2003 "vendor, "
2004 "build_host, "
2005 "build_time, "
2006 "strftime('%s', installed) AS installed, "
2007 "userinstalled, "
d995f7fc 2008 "("
32485f6c 2009 "SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id"
24be412a
MT
2010 ") AS files, "
2011 "("
2012 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2013 "WHERE d.pkg = packages.id AND d.type = 'provides'"
2014 ") AS provides, "
2015 "("
2016 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2017 "WHERE d.pkg = packages.id AND d.type = 'prerequires'"
2018 ") AS prerequires, "
2019 "("
2020 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2021 "WHERE d.pkg = packages.id AND d.type = 'requires'"
2022 ") AS requires, "
2023 "("
2024 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2025 "WHERE d.pkg = packages.id AND d.type = 'conflicts'"
2026 ") AS conflicts, "
2027 "("
2028 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2029 "WHERE d.pkg = packages.id AND d.type = 'obsoletes'"
2030 ") AS obsoletes, "
2031 "("
2032 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2033 "WHERE d.pkg = packages.id AND d.type = 'recommends'"
2034 ") AS recommends, "
2035 "("
2036 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2037 "WHERE d.pkg = packages.id AND d.type = 'suggests'"
8fe2e4ba
MT
2038 ") AS suggests, "
2039 "("
2040 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2041 "WHERE d.pkg = packages.id AND d.type = 'supplements'"
2042 ") AS supplements, "
2043 "("
2044 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2045 "WHERE d.pkg = packages.id AND d.type = 'enhances'"
571539a7
MT
2046 ") AS enhances, "
2047 "source_name, "
2048 "source_evr, "
ca002cae
MT
2049 "source_arch, "
2050 "distribution "
361ca45f
MT
2051 "FROM "
2052 "packages"
2053 ";";
2054
2055 // Prepare the statement
2056 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2057 if (r) {
2058 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2059 sql, sqlite3_errmsg(db->handle));
2060 goto ERROR;
2061 }
2062
2063 for (;;) {
2064 // Execute query
2065 r = sqlite3_step(stmt);
2066
2067 switch (r) {
2068 // Retry if the database was busy
2069 case SQLITE_BUSY:
2070 continue;
2071
2072 // Read a row
2073 case SQLITE_ROW:
2074 r = pakfire_db_load_package(db, repo, stmt);
2075 if (r)
2076 goto ERROR;
2077 break;
2078
2079 // All rows have been processed
2080 case SQLITE_DONE:
2081 goto END;
2082
2083 // Go to error in any other cases
2084 default:
2085 goto ERROR;
2086 }
2087 }
2088
2089END:
788221bd
MT
2090 // Save time when we finished
2091 t_end = clock();
2092
2093 DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
2094 (double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
361ca45f 2095
9eba3d65
MT
2096 // Mark repository as changed
2097 pakfire_repo_has_changed(repo);
05336f5e 2098
361ca45f
MT
2099 // All done
2100 r = 0;
2101
2102ERROR:
b027597a 2103 if (r) {
5dee04f3 2104 ERROR(db->pakfire, "Failed reading package database: %m\n");
b027597a
MT
2105 pakfire_repo_clear(repo);
2106 }
361ca45f
MT
2107
2108 if (stmt)
2109 sqlite3_finalize(stmt);
2110
2111 return r;
2112}
ac71886a 2113
923d6794 2114static int pakfire_db_load_file_digest(struct pakfire_db* db, struct pakfire_file* file,
c52e0148 2115 sqlite3_stmt* stmt, const enum pakfire_digest_types type, const int field) {
923d6794
MT
2116 // Fetch digest
2117 const unsigned char* digest = sqlite3_column_blob(stmt, field);
2118
2119 // Nothing further to do if field is NULL
2120 if (!digest)
2121 return 0;
2122
2123 // Length of the stored value
2124 const size_t length = sqlite3_column_bytes(stmt, field);
2125
923d6794 2126 // Store digest
399d14c2 2127 return pakfire_file_set_digest(file, type, digest, length);
923d6794
MT
2128}
2129
1bbbfb9e 2130static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* filelist,
ac71886a
MT
2131 sqlite3_stmt* stmt) {
2132 struct pakfire_file* file = NULL;
1fab76a4 2133 char abspath[PATH_MAX];
ac71886a
MT
2134 int r;
2135
2136 // Create a new file object
2137 r = pakfire_file_create(&file, db->pakfire);
2138 if (r)
2139 goto ERROR;
2140
2141 // Path
2142 const char* path = (const char*)sqlite3_column_text(stmt, 0);
f04369e6
MT
2143
2144 // Abort if no path is set
2145 if (!path) {
2146 ERROR(db->pakfire, "File has no path\n");
2147 r = 1;
2148 goto ERROR;
2149 }
2150
2151 // Set path
2152 r = pakfire_file_set_path(file, path);
2153 if (r) {
2154 ERROR(db->pakfire, "%s: Could not set path '%s': %m\n", path, path);
2155 goto ERROR;
2156 }
ac71886a 2157
1fab76a4
MT
2158 // Make the absolute path
2159 r = pakfire_path(db->pakfire, abspath, "%s", path);
2160 if (r) {
2161 ERROR(db->pakfire, "%s: Could not make absolute path: %m\n", path);
2162 goto ERROR;
2163 }
2164
2165 // Set the absolute path
2166 r = pakfire_file_set_abspath(file, abspath);
2167 if (r) {
2168 ERROR(db->pakfire, "%s: Could not set absolute path %s: %m\n", path, abspath);
2169 goto ERROR;
2170 }
2171
ac71886a
MT
2172 // Size
2173 size_t size = sqlite3_column_int64(stmt, 1);
2174 if (size)
2175 pakfire_file_set_size(file, size);
2176
2177 // Mode
2178 mode_t mode = sqlite3_column_int(stmt, 2);
2179 if (mode)
2180 pakfire_file_set_mode(file, mode);
2181
302e3253
MT
2182 // uname
2183 const char* uname = (const char*)sqlite3_column_text(stmt, 3);
f04369e6
MT
2184
2185 // Abort if no user is set
302e3253 2186 if (!uname) {
f04369e6
MT
2187 ERROR(db->pakfire, "%s: No user\n", path);
2188 r = 1;
2189 goto ERROR;
2190 }
2191
302e3253
MT
2192 // Set uname
2193 r = pakfire_file_set_uname(file, uname);
f04369e6 2194 if (r) {
302e3253 2195 ERROR(db->pakfire, "%s: Could not set user '%s': %m\n", path, uname);
f04369e6
MT
2196 goto ERROR;
2197 }
ac71886a 2198
302e3253
MT
2199 // gname
2200 const char* gname = (const char*)sqlite3_column_text(stmt, 4);
f04369e6
MT
2201
2202 // Abort if no group is set
302e3253 2203 if (!gname) {
f04369e6
MT
2204 ERROR(db->pakfire, "%s: No group\n", path);
2205 r = 1;
2206 goto ERROR;
2207 }
2208
302e3253
MT
2209 // Set gname
2210 r = pakfire_file_set_gname(file, gname);
f04369e6 2211 if (r) {
302e3253 2212 ERROR(db->pakfire, "%s: Could not set group '%s': %m\n", path, gname);
f04369e6
MT
2213 goto ERROR;
2214 }
ac71886a
MT
2215
2216 // ctime
2217 time_t ctime = sqlite3_column_int64(stmt, 5);
2218 if (ctime)
2219 pakfire_file_set_ctime(file, ctime);
2220
2221 // mtime
2222 time_t mtime = sqlite3_column_int64(stmt, 6);
2223 if (mtime)
2224 pakfire_file_set_mtime(file, mtime);
2225
210aabe9
MT
2226 const char* mimetype = (const char*)sqlite3_column_text(stmt, 7);
2227
2228 // MIME type
2229 r = pakfire_file_set_mimetype(file, mimetype);
2230 if (r)
2231 goto ERROR;
2232
a3845369 2233 // SHA2-512 Digest
210aabe9 2234 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_512, 8);
923d6794
MT
2235 if (r)
2236 goto ERROR;
2237
a3845369 2238 // SHA2-256 Digest
210aabe9 2239 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_256, 9);
923d6794
MT
2240 if (r)
2241 goto ERROR;
2242
a3845369 2243 // BLAKE2b512 Digest
210aabe9 2244 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2B512, 10);
a3845369
MT
2245 if (r)
2246 goto ERROR;
2247
2248 // BLAKE2s256 Digest
210aabe9 2249 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2S256, 11);
a3845369
MT
2250 if (r)
2251 goto ERROR;
2252
2253 // SHA3-512 Digest
210aabe9 2254 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_512, 12);
a3845369
MT
2255 if (r)
2256 goto ERROR;
2257
2258 // SHA3-256 Digest
210aabe9 2259 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_256, 13);
a3845369
MT
2260 if (r)
2261 goto ERROR;
2262
ac71886a 2263 // Append the file to the filelist
2f88682d 2264 r = pakfire_filelist_add(filelist, file);
f04369e6
MT
2265 if (r)
2266 goto ERROR;
ac71886a
MT
2267
2268ERROR:
2269 if (file)
2270 pakfire_file_unref(file);
2271
2272 return r;
2273}
2274
3f310c26
MT
2275int pakfire_db_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist) {
2276 struct pakfire_filelist* list = NULL;
2277 sqlite3_stmt* stmt = NULL;
2278 int r;
2279
2280 const char* sql =
2281 "SELECT "
2282 "path, "
2283 "size, "
2284 "mode, "
ca8fe553
MT
2285 "uname, "
2286 "gname, "
3f310c26 2287 "ctime, "
923d6794 2288 "mtime, "
210aabe9 2289 "mimetype, "
a3845369
MT
2290 "digest_sha2_512, "
2291 "digest_sha2_256, "
2292 "digest_blake2b512, "
2293 "digest_blake2s256, "
2294 "digest_sha3_512, "
2295 "digest_sha3_256 "
3f310c26
MT
2296 "FROM files "
2297 "ORDER BY path"
2298 ";";
2299
2300 // Prepare the statement
2301 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2302 if (r) {
2303 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2304 sql, sqlite3_errmsg(db->handle));
2305 goto ERROR;
2306 }
2307
2308 // Create a new filelist
2309 r = pakfire_filelist_create(&list, db->pakfire);
2310 if (r)
2311 goto ERROR;
2312
2313 // Iterate over all rows
2314 for (;;) {
2315 // Execute query
2316 r = sqlite3_step(stmt);
2317
2318 switch (r) {
2319 // Retry if the database was busy
2320 case SQLITE_BUSY:
2321 continue;
2322
2323 // Read a row
2324 case SQLITE_ROW:
2325 r = pakfire_db_load_file(db, list, stmt);
2326 if (r)
2327 goto ERROR;
2328 break;
2329
2330 // All rows have been processed
2331 case SQLITE_DONE:
2332 r = 0;
2333 goto END;
2334
2335 // Go to error in any other cases
2336 default:
2337 goto ERROR;
2338 }
2339 }
2340
2341END:
2342 // Return the filelist
2343 *filelist = pakfire_filelist_ref(list);
2344
2345ERROR:
2346 if (r)
2347 ERROR(db->pakfire, "Could not fetch filelist: %m\n");
2348
2349 if (stmt)
2350 sqlite3_finalize(stmt);
2351 if (list)
2352 pakfire_filelist_unref(list);
2353
2354 return r;
2355}
2356
1bbbfb9e 2357int pakfire_db_package_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist,
31480bee 2358 struct pakfire_package* pkg) {
1bbbfb9e 2359 struct pakfire_filelist* fl = NULL;
ac71886a
MT
2360 sqlite3_stmt* stmt = NULL;
2361 int r = 1;
2362
2363 // Fetch the package ID
3f327c3c 2364 uint64_t id = pakfire_package_get_num(pkg, PAKFIRE_PKG_DBID, 0);
ac71886a
MT
2365 if (!id) {
2366 ERROR(db->pakfire, "Package did not have an ID\n");
2367 return 1;
2368 }
2369
2370 // Create a new filelist
2371 r = pakfire_filelist_create(&fl, db->pakfire);
2372 if (r) {
2373 ERROR(db->pakfire, "Could not create filelist: %m\n");
2374 goto ERROR;
2375 }
2376
2377 const char* sql =
2378 "SELECT "
2379 "path, "
2380 "size, "
2381 "mode, "
ca8fe553
MT
2382 "uname, "
2383 "gname, "
ac71886a 2384 "ctime, "
923d6794 2385 "mtime, "
210aabe9 2386 "mimetype, "
ca8fe553
MT
2387 "digest_sha2_512, "
2388 "digest_sha2_256, "
2389 "digest_blake2b512, "
2390 "digest_blake2s256, "
2391 "digest_sha3_512, "
2392 "digest_sha3_256 "
ac71886a
MT
2393 "FROM files "
2394
2395 // Select all files that belong to this package
2396 "WHERE "
2397 "pkg = ? "
2398
2399 // Filter out any files that are also in a different package (i.e. an update
2400 // that has already been installed and this is the cleanup of the obsolete pkg)
2401 "AND "
2402 "NOT EXISTS ("
2403 "SELECT "
2404 "1 "
2405 "FROM files AS duplicates "
2406 "WHERE "
2407 "files.path = duplicates.path "
2408 "AND "
2409 "files.pkg != duplicates.pkg"
2410 ") "
2411
6da744eb
MT
2412 // Return ordered by path
2413 "ORDER BY path"
ac71886a
MT
2414 ";";
2415
2416 // Prepare the statement
2417 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2418 if (r) {
2419 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2420 sql, sqlite3_errmsg(db->handle));
2421 goto ERROR;
2422 }
2423
2424 // Bind package ID
2425 r = sqlite3_bind_int64(stmt, 1, id);
2426 if (r) {
2427 ERROR(db->pakfire, "Could not bind package ID: %s\n", sqlite3_errmsg(db->handle));
2428 goto ERROR;
2429 }
2430
2431 for (;;) {
2432 // Execute query
2433 r = sqlite3_step(stmt);
2434
2435 switch (r) {
2436 // Retry if the database was busy
2437 case SQLITE_BUSY:
2438 continue;
2439
2440 // Read a row
2441 case SQLITE_ROW:
2442 r = pakfire_db_load_file(db, fl, stmt);
2443 if (r)
2444 goto ERROR;
2445 break;
2446
2447 // All rows have been processed
2448 case SQLITE_DONE:
2449 goto END;
2450
2451 // Go to error in any other cases
2452 default:
2453 goto ERROR;
2454 }
2455 }
2456
2457END:
2458 *filelist = pakfire_filelist_ref(fl);
2459 r = 0;
2460
2461ERROR:
2462 if (stmt)
2463 sqlite3_finalize(stmt);
2464 if (fl)
2465 pakfire_filelist_unref(fl);
2466
2467 return r;
2468}