]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
packages: Make pakfire_package_is_installed private
[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, "
424 "capabilities TEXT, "
425 "digest_sha2_512 BLOB, "
426 "digest_sha2_256 BLOB, "
427 "digest_blake2b512 BLOB, "
428 "digest_blake2s256 BLOB, "
429 "digest_sha3_512 BLOB, "
430 "digest_sha3_256 BLOB, "
432a328a 431 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
68036506
MT
432 ")");
433 if (r)
434 return 1;
435
436 // files: Add index over packages
437 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
438 if (r)
439 return 1;
440
ab1aa17a
MT
441 // files: Add index over path
442 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_path_index ON files(path)");
443 if (r)
444 return 1;
445
d83414aa
MT
446 // Create scriptlets table
447 r = pakfire_db_execute(db,
448 "CREATE TABLE IF NOT EXISTS scriptlets("
449 "id INTEGER PRIMARY KEY, "
450 "pkg INTEGER, "
265f539a 451 "type TEXT, "
46257c5f 452 "scriptlet TEXT, "
432a328a 453 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
d83414aa
MT
454 ")");
455 if (r)
456 return 1;
457
458 // scriptlets: Add index over packages
459 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
460 if (r)
461 return 1;
462
33b38daa
MT
463 const char* arch = pakfire_get_arch(db->pakfire);
464
465 // Set architecture
466 r = pakfire_db_set_string(db, "arch", arch);
467 if (r) {
468 ERROR(db->pakfire, "Could not set architecture\n");
469 return r;
470 }
471
c745fb2d
MT
472 return 0;
473}
474
46257c5f 475static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
5ba550fe
MT
476 // packages: Drop build_id column
477
46257c5f
MT
478 // Add foreign keys
479 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
480 // need to recreate the whole table and rename it afterwards. Annoying.
481
482 return 0;
483}
484
c745fb2d
MT
485static int pakfire_db_migrate_schema(struct pakfire_db* db) {
486 int r;
487
488 while (db->schema < CURRENT_SCHEMA) {
489 // Begin a new transaction
490 r = pakfire_db_begin_transaction(db);
491 if (r)
492 goto ROLLBACK;
493
494 switch (db->schema) {
495 // No schema exists
f168dd0c 496 case -1:
c745fb2d
MT
497 r = pakfire_db_create_schema(db);
498 if (r)
499 goto ROLLBACK;
500
501 db->schema = CURRENT_SCHEMA;
502 break;
503
46257c5f
MT
504 case 7:
505 r = pakfire_db_migrate_to_schema_8(db);
506 if (r)
507 goto ROLLBACK;
508
509 db->schema++;
510 break;
511
c745fb2d
MT
512 default:
513 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
514 goto ROLLBACK;
515 }
516
517 // Update the schema version
518 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
519 if (r)
520 goto ROLLBACK;
521
522 // All done, commit!
523 r = pakfire_db_commit(db);
524 if (r)
525 goto ROLLBACK;
526 }
527
528 return 0;
529
530ROLLBACK:
531 pakfire_db_rollback(db);
532
533 return 1;
534}
535
33b38daa
MT
536static int pakfire_db_check_arch(struct pakfire_db* db) {
537 int r = 1;
538
539 // Fetch database architecture
540 char* db_arch = pakfire_db_get_string(db, "arch");
541 if (!db_arch) {
542 ERROR(db->pakfire, "Database is of an unknown architecture\n");
543 goto ERROR;
544 }
545
546 // Fetch the running architecture
547 const char* arch = pakfire_get_arch(db->pakfire);
548 if (!arch)
549 goto ERROR;
550
551 // They should match
552 if (strcmp(db_arch, arch) == 0)
553 r = 0;
554
555ERROR:
556 if (db_arch)
557 free(db_arch);
558
559 return r;
560}
561
9c5938ea 562static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
563 int r;
564
9c5938ea
MT
565 // Setup logging
566 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
567
46257c5f
MT
568 // Enable foreign keys
569 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
570
0076c50d
MT
571 // Make LIKE case-sensitive
572 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
573
c745fb2d
MT
574 // Fetch the current schema
575 db->schema = pakfire_db_get_schema(db);
576
577 // Check if the schema is recent enough
578 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
579 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
580 db->schema);
581 return 1;
582 }
583
7b4df765
MT
584 // Read modification timestamp
585 db->last_modified_at = pakfire_read_modification_time(db);
586
587 DEBUG(db->pakfire, "The database was last modified at %ld\n", db->last_modified_at);
588
9c5938ea
MT
589 // Done when not in read-write mode
590 if (db->mode != PAKFIRE_DB_READWRITE)
591 return 0;
592
0076c50d
MT
593 // Disable secure delete
594 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
595
25753290
MT
596 // Set database journal to WAL
597 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
598 if (r != SQLITE_OK) {
599 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
600 sqlite3_errmsg(db->handle));
601 return 1;
602 }
603
604 // Disable autocheckpoint
605 r = sqlite3_wal_autocheckpoint(db->handle, 0);
606 if (r != SQLITE_OK) {
607 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
608 sqlite3_errmsg(db->handle));
609 return 1;
610 }
611
c745fb2d
MT
612 // Create or migrate schema
613 r = pakfire_db_migrate_schema(db);
614 if (r)
615 return r;
9c5938ea
MT
616
617 return 0;
618}
619
ac4c607b 620int pakfire_db_open(struct pakfire_db** db, struct pakfire* pakfire, int flags) {
26affd69
MT
621 int r = 1;
622
90312f5c 623 struct pakfire_db* o = calloc(1, sizeof(*o));
33d55ab4
MT
624 if (!o)
625 return -ENOMEM;
626
33d55ab4
MT
627 o->pakfire = pakfire_ref(pakfire);
628 o->nrefs = 1;
629
26affd69
MT
630 int sqlite3_flags = 0;
631
632 // Store mode & forward it to sqlite3
633 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 634 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
635 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
636 } else {
77a4b3a3 637 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
638 sqlite3_flags |= SQLITE_OPEN_READONLY;
639 }
640
641 // Make the filename
77e26129
MT
642 r = pakfire_path(o->pakfire, o->path, "%s", DATABASE_PATH);
643 if (r)
26affd69
MT
644 goto END;
645
646 // Try to open the sqlite3 database file
097b6ca6 647 r = sqlite3_open_v2(o->path, &o->handle, sqlite3_flags, NULL);
26affd69
MT
648 if (r != SQLITE_OK) {
649 ERROR(pakfire, "Could not open database %s: %s\n",
097b6ca6 650 o->path, sqlite3_errmsg(o->handle));
26affd69
MT
651
652 r = 1;
653 goto END;
654 }
77a4b3a3 655
9c5938ea
MT
656 // Setup the database
657 r = pakfire_db_setup(o);
658 if (r)
659 goto END;
660
33b38daa
MT
661 // Check for compatible architecture
662 r = pakfire_db_check_arch(o);
663 if (r)
664 goto END;
665
33d55ab4 666 *db = o;
26affd69
MT
667 r = 0;
668
669END:
670 if (r)
671 pakfire_db_free(o);
33d55ab4 672
26affd69 673 return r;
33d55ab4
MT
674}
675
9c78c483 676struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
33d55ab4
MT
677 db->nrefs++;
678
679 return db;
680}
681
9c78c483 682struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
33d55ab4
MT
683 if (--db->nrefs > 0)
684 return db;
685
686 pakfire_db_free(db);
687
688 return NULL;
689}
eafbe2ce 690
a1571786
MT
691static unsigned long pakfire_db_integrity_check(struct pakfire_db* db) {
692 sqlite3_stmt* stmt = NULL;
693 int r;
694
695 r = sqlite3_prepare_v2(db->handle, "PRAGMA integrity_check", -1, &stmt, NULL);
696 if (r) {
697 ERROR(db->pakfire, "Could not prepare integrity check: %s\n",
698 sqlite3_errmsg(db->handle));
699 return 1;
700 }
701
702 // Count any errors
703 unsigned long errors = 0;
704
705 while (1) {
706 do {
707 r = sqlite3_step(stmt);
708 } while (r == SQLITE_BUSY);
709
710 if (r == SQLITE_ROW) {
711 const char* error = (const char*)sqlite3_column_text(stmt, 0);
712
713 // If the message is "ok", the database has passed the check
714 if (strcmp(error, "ok") == 0)
715 continue;
716
717 // Increment error counter
718 errors++;
719
720 // Log the message
721 ERROR(db->pakfire, "%s\n", error);
722
723 // Break on anything else
724 } else
725 break;
726 }
727
728 sqlite3_finalize(stmt);
729
730 if (errors)
731 ERROR(db->pakfire, "Database integrity check failed\n");
732 else
733 INFO(db->pakfire, "Database integrity check passed\n");
734
735 return errors;
736}
737
738static unsigned long pakfire_db_foreign_key_check(struct pakfire_db* db) {
739 sqlite3_stmt* stmt = NULL;
740 int r;
741
742 r = sqlite3_prepare_v2(db->handle, "PRAGMA foreign_key_check", -1, &stmt, NULL);
743 if (r) {
744 ERROR(db->pakfire, "Could not prepare foreign key check: %s\n",
745 sqlite3_errmsg(db->handle));
746 return 1;
747 }
748
749 // Count any errors
750 unsigned long errors = 0;
751
752 while (1) {
753 do {
754 r = sqlite3_step(stmt);
755 } while (r == SQLITE_BUSY);
756
757 if (r == SQLITE_ROW) {
758 const unsigned char* table = sqlite3_column_text(stmt, 0);
759 unsigned long rowid = sqlite3_column_int64(stmt, 1);
760 const unsigned char* foreign_table = sqlite3_column_text(stmt, 2);
761 unsigned long foreign_rowid = sqlite3_column_int64(stmt, 3);
762
763 // Increment error counter
764 errors++;
765
766 // Log the message
767 ERROR(db->pakfire, "Foreign key violation found in %s, row %lu: "
768 "%lu does not exist in table %s\n", table, rowid, foreign_rowid, foreign_table);
769
770 // Break on anything else
771 } else
772 break;
773 }
774
775 sqlite3_finalize(stmt);
776
777 if (errors)
778 ERROR(db->pakfire, "Foreign key check failed\n");
779 else
780 INFO(db->pakfire, "Foreign key check passed\n");
781
782 return errors;
783}
784
785/*
786 This function performs an integrity check of the database
787*/
9c78c483 788int pakfire_db_check(struct pakfire_db* db) {
a1571786
MT
789 int r;
790
791 // Perform integrity check
792 r = pakfire_db_integrity_check(db);
793 if (r)
794 return 1;
795
796 // Perform foreign key check
797 r = pakfire_db_foreign_key_check(db);
798 if (r)
799 return 1;
800
801 return 0;
802}
803
817757f4 804// Returns the number of packages installed
9c78c483 805ssize_t pakfire_db_packages(struct pakfire_db* db) {
817757f4
MT
806 sqlite3_stmt* stmt = NULL;
807 ssize_t packages = -1;
808
809 int r = sqlite3_prepare_v2(db->handle, "SELECT COUNT(*) FROM packages", -1, &stmt, NULL);
810 if (r) {
811 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
812 sqlite3_errmsg(db->handle));
813 return -1;
814 }
815
816 // Execute query
817 do {
818 r = sqlite3_step(stmt);
819 } while (r == SQLITE_BUSY);
820
821 if (r == SQLITE_ROW) {
822 packages = sqlite3_column_int64(stmt, 0);
823 }
824
825 sqlite3_finalize(stmt);
826
827 return packages;
828}
829
ac4c607b 830static void pakfire_db_add_userinstalled(struct pakfire* pakfire, const char* name) {
c9c03e6a
MT
831 Pool* pool = pakfire_get_solv_pool(pakfire);
832
833 // Convert name to ID
834 Id id = pool_str2id(pool, name, 1);
835
836 // Append it to pooljobs
837 queue_push2(&pool->pooljobs, SOLVER_USERINSTALLED|SOLVER_SOLVABLE_NAME, id);
838}
839
31480bee 840static int pakfire_db_add_dependencies(struct pakfire_db* db, unsigned long id, struct pakfire_package* pkg) {
1fb2b526
MT
841 sqlite3_stmt* stmt = NULL;
842 int r = 1;
843
844 const char* sql = "INSERT INTO dependencies(pkg, type, dependency) VALUES(?, ?, ?)";
845
846 // Prepare the statement
847 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
848 if (r) {
849 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
850 sql, sqlite3_errmsg(db->handle));
851 goto END;
852 }
853
854 const struct __relation {
855 const char* type;
31480bee 856 char** (*func)(struct pakfire_package*);
1fb2b526
MT
857 } relations[] = {
858 { "provides", pakfire_package_get_provides },
859 { "prerequires", pakfire_package_get_prerequires },
860 { "requires", pakfire_package_get_requires },
861 { "conflicts", pakfire_package_get_conflicts },
862 { "obsoletes", pakfire_package_get_obsoletes },
863 { "recommends", pakfire_package_get_recommends },
864 { "suggests", pakfire_package_get_suggests },
8fe2e4ba
MT
865 { "supplements", pakfire_package_get_supplements },
866 { "enhances", pakfire_package_get_enhances },
1fb2b526
MT
867 { NULL, NULL },
868 };
869
870 for (const struct __relation* relation = relations; relation->type; relation++) {
452d3833 871 char** list = relation->func(pkg);
1fb2b526
MT
872 if (!list)
873 continue;
874
452d3833 875 for (char** dep = list; *dep; dep++) {
1fb2b526
MT
876 // Bind package ID
877 r = sqlite3_bind_int64(stmt, 1, id);
878 if (r) {
879 ERROR(db->pakfire, "Could not bind id: %s\n",
880 sqlite3_errmsg(db->handle));
1fb2b526
MT
881 goto END;
882 }
883
884 // Bind type
885 r = sqlite3_bind_text(stmt, 2, relation->type, -1, NULL);
886 if (r) {
887 ERROR(db->pakfire, "Could not bind type: %s\n",
888 sqlite3_errmsg(db->handle));
1fb2b526
MT
889 goto END;
890 }
891
892 // Bind dependency
452d3833 893 r = sqlite3_bind_text(stmt, 3, *dep, -1, NULL);
1fb2b526
MT
894 if (r) {
895 ERROR(db->pakfire, "Could not bind dependency: %s\n",
896 sqlite3_errmsg(db->handle));
1fb2b526
MT
897 goto END;
898 }
899
900 // Execute query
901 do {
902 r = sqlite3_step(stmt);
903 } while (r == SQLITE_BUSY);
904
452d3833 905 free(*dep);
1fb2b526
MT
906
907 // Reset bound values
908 sqlite3_reset(stmt);
909 }
910
452d3833 911 free(list);
1fb2b526
MT
912 }
913
914 // All okay
915 r = 0;
916
917END:
918 if (stmt)
919 sqlite3_finalize(stmt);
920
921 return r;
922}
923
a3845369
MT
924static int pakfire_db_bind_digest(struct pakfire_db* db, sqlite3_stmt* stmt, const int field,
925 struct pakfire_file* file, const enum pakfire_digest_types type) {
926 const unsigned char* digest = NULL;
927 size_t length = 0;
928
929 // Fetch the digest
930 digest = pakfire_file_get_digest(file, type, &length);
931
932 // If this digest isn't set, just bind NULL
933 if (!digest)
934 return sqlite3_bind_null(stmt, field);
935
936 // Otherwise bind the data blob
937 return sqlite3_bind_blob(stmt, field, digest, length, NULL);
938}
939
900faa2f 940static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
f5c77233 941 sqlite3_stmt* stmt = NULL;
dccd04a4 942 int r = 1;
f5c77233
MT
943
944 // Get the filelist from the archive
1bbbfb9e 945 struct pakfire_filelist* filelist = pakfire_archive_get_filelist(archive);
5e9463ec 946 if (!filelist) {
f5c77233
MT
947 ERROR(db->pakfire, "Could not fetch filelist from archive\n");
948 return 1;
949 }
950
5e9463ec 951 // Nothing to do if the list is empty
9a6e3e2d
MT
952 if (pakfire_filelist_is_empty(filelist)) {
953 r = 0;
5e9463ec 954 goto END;
9a6e3e2d 955 }
5e9463ec 956
a3845369
MT
957 const char* sql =
958 "INSERT INTO "
959 " files("
960 "pkg, "
961 "path, "
962 "size, "
963 "config, "
964 "datafile, "
965 "mode, "
df824b86
MT
966 "uname, "
967 "gname, "
a3845369
MT
968 "ctime, "
969 "mtime, "
970 "capabilities, "
971 "digest_sha2_512, "
972 "digest_sha2_256, "
973 "digest_blake2b512, "
974 "digest_blake2s256, "
975 "digest_sha3_512, "
976 "digest_sha3_256"
977 ") "
978 "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
f5c77233
MT
979
980 // Prepare the statement
923d6794 981 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
f5c77233
MT
982 if (r) {
983 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
984 sql, sqlite3_errmsg(db->handle));
985 goto END;
986 }
987
5e9463ec 988 for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
5803b5f6 989 struct pakfire_file* file = pakfire_filelist_get(filelist, i);
5e9463ec 990
f5c77233
MT
991 // Bind package ID
992 r = sqlite3_bind_int64(stmt, 1, id);
993 if (r) {
994 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 995 pakfire_file_unref(file);
f5c77233
MT
996 goto END;
997 }
998
999 // Bind name
32485f6c 1000 const char* path = pakfire_file_get_path(file);
f5c77233 1001
32485f6c 1002 r = sqlite3_bind_text(stmt, 2, path, -1, NULL);
f5c77233 1003 if (r) {
32485f6c 1004 ERROR(db->pakfire, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1005 pakfire_file_unref(file);
f5c77233
MT
1006 goto END;
1007 }
1008
1009 // Bind size
1010 size_t size = pakfire_file_get_size(file);
1011
1012 r = sqlite3_bind_int64(stmt, 3, size);
1013 if (r) {
1014 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1015 pakfire_file_unref(file);
f5c77233
MT
1016 goto END;
1017 }
1018
f5c77233 1019 // Bind config - XXX TODO
b72bae3f 1020 r = sqlite3_bind_null(stmt, 4);
f5c77233
MT
1021 if (r) {
1022 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1023 pakfire_file_unref(file);
f5c77233
MT
1024 goto END;
1025 }
1026
1027 // Bind datafile - XXX TODO
b72bae3f 1028 r = sqlite3_bind_null(stmt, 5);
f5c77233
MT
1029 if (r) {
1030 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1031 pakfire_file_unref(file);
f5c77233
MT
1032 goto END;
1033 }
1034
1035 // Bind mode
1036 mode_t mode = pakfire_file_get_mode(file);
1037
b72bae3f 1038 r = sqlite3_bind_int64(stmt, 6, mode);
f5c77233
MT
1039 if (r) {
1040 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1041 pakfire_file_unref(file);
f5c77233
MT
1042 goto END;
1043 }
1044
302e3253
MT
1045 // Bind uname
1046 const char* uname = pakfire_file_get_uname(file);
f5c77233 1047
302e3253 1048 r = sqlite3_bind_text(stmt, 7, uname, -1, NULL);
f5c77233 1049 if (r) {
302e3253 1050 ERROR(db->pakfire, "Could not bind uname: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1051 pakfire_file_unref(file);
f5c77233
MT
1052 goto END;
1053 }
1054
302e3253
MT
1055 // Bind gname
1056 const char* gname = pakfire_file_get_gname(file);
f5c77233 1057
302e3253 1058 r = sqlite3_bind_text(stmt, 8, gname, -1, NULL);
f5c77233 1059 if (r) {
302e3253 1060 ERROR(db->pakfire, "Could not bind gname: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1061 pakfire_file_unref(file);
f5c77233
MT
1062 goto END;
1063 }
1064
ef4e8460
MT
1065 // Bind ctime
1066 time_t ctime = pakfire_file_get_ctime(file);
1067
a7e5cf06 1068 r = sqlite3_bind_int64(stmt, 9, ctime);
ef4e8460
MT
1069 if (r) {
1070 ERROR(db->pakfire, "Could not bind ctime: %s\n", sqlite3_errmsg(db->handle));
1071 pakfire_file_unref(file);
1072 goto END;
1073 }
1074
f5c77233 1075 // Bind mtime
ef4e8460 1076 time_t mtime = pakfire_file_get_mtime(file);
f5c77233 1077
a7e5cf06 1078 r = sqlite3_bind_int64(stmt, 10, mtime);
f5c77233
MT
1079 if (r) {
1080 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1081 pakfire_file_unref(file);
f5c77233
MT
1082 goto END;
1083 }
1084
1085 // Bind capabilities - XXX TODO
a7e5cf06 1086 r = sqlite3_bind_null(stmt, 11);
f5c77233
MT
1087 if (r) {
1088 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1089 pakfire_file_unref(file);
f5c77233
MT
1090 goto END;
1091 }
1092
a3845369
MT
1093 // SHA2-512 Digest
1094 r = pakfire_db_bind_digest(db, stmt, 12, file, PAKFIRE_DIGEST_SHA2_512);
1095 if (r) {
1096 ERROR(db->pakfire, "Could not bind SHA2-512 digest: %s\n",
1097 sqlite3_errmsg(db->handle));
1098 pakfire_file_unref(file);
1099 goto END;
1100 }
923d6794 1101
a3845369
MT
1102 // SHA2-256 Digest
1103 r = pakfire_db_bind_digest(db, stmt, 13, file, PAKFIRE_DIGEST_SHA2_256);
1104 if (r) {
1105 ERROR(db->pakfire, "Could not bind SHA2-256 digest: %s\n",
1106 sqlite3_errmsg(db->handle));
1107 pakfire_file_unref(file);
1108 goto END;
923d6794 1109 }
a3845369
MT
1110
1111 // BLAKE2b512 Digest
1112 r = pakfire_db_bind_digest(db, stmt, 14, file, PAKFIRE_DIGEST_BLAKE2B512);
923d6794 1113 if (r) {
a3845369 1114 ERROR(db->pakfire, "Could not bind BLAKE2b512 digest: %s\n",
923d6794
MT
1115 sqlite3_errmsg(db->handle));
1116 pakfire_file_unref(file);
1117 goto END;
1118 }
1119
a3845369
MT
1120 // BLAKE2s256 Digest
1121 r = pakfire_db_bind_digest(db, stmt, 15, file, PAKFIRE_DIGEST_BLAKE2S256);
1122 if (r) {
1123 ERROR(db->pakfire, "Could not bind BLAKE2s256 digest: %s\n",
1124 sqlite3_errmsg(db->handle));
1125 pakfire_file_unref(file);
1126 goto END;
1127 }
923d6794 1128
a3845369
MT
1129 // SHA3-512 Digest
1130 r = pakfire_db_bind_digest(db, stmt, 16, file, PAKFIRE_DIGEST_SHA3_512);
1131 if (r) {
1132 ERROR(db->pakfire, "Could not bind SHA3-512 digest: %s\n",
1133 sqlite3_errmsg(db->handle));
1134 pakfire_file_unref(file);
1135 goto END;
923d6794 1136 }
a3845369
MT
1137
1138 // SHA3-256 Digest
1139 r = pakfire_db_bind_digest(db, stmt, 17, file, PAKFIRE_DIGEST_SHA3_256);
923d6794 1140 if (r) {
a3845369 1141 ERROR(db->pakfire, "Could not bind SHA3-256 digest: %s\n",
923d6794
MT
1142 sqlite3_errmsg(db->handle));
1143 pakfire_file_unref(file);
1144 goto END;
1145 }
1146
f5c77233
MT
1147 // Execute query
1148 do {
1149 r = sqlite3_step(stmt);
1150 } while (r == SQLITE_BUSY);
1151
5bae3112
MT
1152 // Check for errors
1153 if (r != SQLITE_DONE) {
1154 ERROR(db->pakfire, "Could not add file to database: %s\n",
1155 sqlite3_errmsg(db->handle));
a7e5cf06 1156 pakfire_file_unref(file);
5bae3112
MT
1157 goto END;
1158 }
1159
a7e5cf06
MT
1160 // Move on to next file
1161 pakfire_file_unref(file);
1162
1163 // Reset bound values
1164 sqlite3_reset(stmt);
f5c77233
MT
1165 }
1166
1167 // All okay
1168 r = 0;
1169
1170END:
1171 if (stmt)
1172 sqlite3_finalize(stmt);
5e9463ec
MT
1173 pakfire_filelist_unref(filelist);
1174
f5c77233
MT
1175 return r;
1176}
1177
900faa2f 1178static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
265f539a 1179 sqlite3_stmt* stmt = NULL;
a0097ba2 1180 size_t size;
265f539a
MT
1181 int r = 1;
1182
265f539a
MT
1183 const char* sql = "INSERT INTO scriptlets(pkg, type, scriptlet) VALUES(?, ?, ?)";
1184
1185 // Prepare the statement
1186 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
1187 if (r) {
1188 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1189 sql, sqlite3_errmsg(db->handle));
1190 goto END;
1191 }
1192
a0097ba2 1193 for (const char** type = pakfire_scriptlet_types; *type; type++) {
265f539a 1194 // Fetch the scriptlet
106d2edd 1195 struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(archive, *type);
a0097ba2 1196 if (!scriptlet)
265f539a 1197 continue;
265f539a
MT
1198
1199 // Bind package ID
1200 r = sqlite3_bind_int64(stmt, 1, id);
1201 if (r) {
1202 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1203 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1204 goto END;
1205 }
1206
1207 // Bind handle
a0097ba2 1208 r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
265f539a
MT
1209 if (r) {
1210 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1211 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1212 goto END;
1213 }
1214
a0097ba2
MT
1215 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
1216
265f539a 1217 // Bind scriptlet
a0097ba2 1218 r = sqlite3_bind_text(stmt, 3, data, size, NULL);
265f539a
MT
1219 if (r) {
1220 ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1221 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1222 goto END;
1223 }
1224
1225 // Execute query
1226 do {
1227 r = sqlite3_step(stmt);
1228 } while (r == SQLITE_BUSY);
1229
5bae3112
MT
1230 // Check for errors
1231 if (r != SQLITE_DONE) {
1232 ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
1233 sqlite3_errmsg(db->handle));
a0097ba2 1234 pakfire_scriptlet_unref(scriptlet);
5bae3112
MT
1235 goto END;
1236 }
1237
a0097ba2
MT
1238 pakfire_scriptlet_unref(scriptlet);
1239
265f539a
MT
1240 // Reset bound values
1241 sqlite3_reset(stmt);
265f539a
MT
1242 }
1243
1244 // All okay
1245 r = 0;
1246
1247END:
1248 if (stmt)
1249 sqlite3_finalize(stmt);
1250
1251 return r;
1252}
1253
9c78c483 1254int pakfire_db_add_package(struct pakfire_db* db,
900faa2f 1255 struct pakfire_package* pkg, struct pakfire_archive* archive, int userinstalled) {
e49b93d1
MT
1256 sqlite3_stmt* stmt = NULL;
1257 int r;
1258
1259 // Begin a new transaction
1260 r = pakfire_db_begin_transaction(db);
1261 if (r)
687961c3 1262 goto ERROR;
e49b93d1 1263
571539a7
MT
1264 const char* sql = "INSERT INTO "
1265 "packages("
1266 "name, "
1267 "evr, "
1268 "arch, "
1269 "groups, "
1270 "filename, "
1271 "size, "
1272 "inst_size, "
e082fb85 1273 "digest_type, "
571539a7
MT
1274 "digest, "
1275 "license, "
1276 "summary, "
1277 "description, "
1278 "uuid, "
1279 "vendor, "
1280 "build_host, "
1281 "build_time, "
1282 "installed, "
1283 "repository, "
1284 "userinstalled, "
1285 "source_name, "
1286 "source_evr, "
ca002cae
MT
1287 "source_arch, "
1288 "distribution"
571539a7
MT
1289 ") VALUES("
1290 "?, "
1291 "?, "
1292 "?, "
1293 "?, "
1294 "?, "
1295 "?, "
1296 "?, "
1297 "?, "
1298 "?, "
1299 "?, "
1300 "?, "
1301 "?, "
1302 "?, "
1303 "?, "
1304 "?, "
e082fb85 1305 "?, "
571539a7
MT
1306 "CURRENT_TIMESTAMP, "
1307 "?, "
1308 "?, "
1309 "?, "
1310 "?, "
ca002cae 1311 "?, "
571539a7
MT
1312 "?"
1313 ")";
e49b93d1
MT
1314
1315 // Prepare the statement
1316 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1317 if (r != SQLITE_OK) {
1318 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1319 sql, sqlite3_errmsg(db->handle));
687961c3 1320 goto ERROR;
e49b93d1
MT
1321 }
1322
1323 // Bind name
74468e4f 1324 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
e49b93d1
MT
1325
1326 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
1327 if (r) {
1328 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
687961c3 1329 goto ERROR;
e49b93d1
MT
1330 }
1331
6ed66687 1332 // Bind evr
74468e4f 1333 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
e49b93d1 1334
6ed66687 1335 r = sqlite3_bind_text(stmt, 2, evr, -1, NULL);
e49b93d1 1336 if (r) {
6ed66687 1337 ERROR(db->pakfire, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
687961c3 1338 goto ERROR;
e49b93d1
MT
1339 }
1340
1341 // Bind arch
74468e4f 1342 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
e49b93d1 1343
6ed66687 1344 r = sqlite3_bind_text(stmt, 3, arch, -1, NULL);
e49b93d1
MT
1345 if (r) {
1346 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
687961c3 1347 goto ERROR;
e49b93d1
MT
1348 }
1349
1350 // Bind groups
74468e4f
MT
1351 const char* groups = pakfire_package_get_string(pkg, PAKFIRE_PKG_GROUPS);
1352
1eb7f40b 1353 if (groups) {
6ed66687 1354 r = sqlite3_bind_text(stmt, 4, groups, -1, NULL);
1eb7f40b
MT
1355 if (r) {
1356 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
687961c3 1357 goto ERROR;
1eb7f40b 1358 }
e49b93d1 1359
1eb7f40b
MT
1360 // No groups
1361 } else {
6ed66687 1362 r = sqlite3_bind_null(stmt, 4);
1eb7f40b 1363 if (r)
687961c3 1364 goto ERROR;
e49b93d1
MT
1365 }
1366
1367 // Bind filename
0aade652 1368 const char* filename = pakfire_package_get_string(pkg, PAKFIRE_PKG_FILENAME);
e49b93d1 1369
6ed66687 1370 r = sqlite3_bind_text(stmt, 5, filename, -1, NULL);
e49b93d1
MT
1371 if (r) {
1372 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
687961c3 1373 goto ERROR;
e49b93d1
MT
1374 }
1375
1376 // Bind size
1377 unsigned long long size = pakfire_package_get_downloadsize(pkg);
1378
6ed66687 1379 r = sqlite3_bind_int64(stmt, 6, size);
e49b93d1
MT
1380 if (r) {
1381 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
687961c3 1382 goto ERROR;
e49b93d1
MT
1383 }
1384
1385 // Bind installed size
1386 unsigned long long inst_size = pakfire_package_get_installsize(pkg);
1387
6ed66687 1388 r = sqlite3_bind_int64(stmt, 7, inst_size);
e49b93d1
MT
1389 if (r) {
1390 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
687961c3 1391 goto ERROR;
e49b93d1
MT
1392 }
1393
e082fb85 1394 const unsigned char* digest = NULL;
c52e0148 1395 enum pakfire_digest_types digest_type = 0;
e082fb85 1396 size_t digest_length = 0;
b28af23a 1397
e082fb85
MT
1398 // Fetch the digest
1399 digest = pakfire_package_get_digest(pkg, &digest_type, &digest_length);
1400 if (!digest) {
1401 ERROR(db->pakfire, "Could not fetch the package's digest: %m\n");
1402 r = 1;
1403 goto ERROR;
1404 }
e49b93d1 1405
e082fb85
MT
1406 // Set the digest type
1407 r = sqlite3_bind_int64(stmt, 8, digest_type);
1408 if (r) {
1409 ERROR(db->pakfire, "Could not bind digest type: %s\n", sqlite3_errmsg(db->handle));
1410 goto ERROR;
1411 }
1412
1413 // Set the digest
1414 r = sqlite3_bind_blob(stmt, 9, digest, digest_length, NULL);
1415 if (r) {
1416 ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle));
1417 goto ERROR;
e49b93d1
MT
1418 }
1419
1420 // Bind license
74468e4f 1421 const char* license = pakfire_package_get_string(pkg, PAKFIRE_PKG_LICENSE);
e49b93d1 1422
e082fb85 1423 r = sqlite3_bind_text(stmt, 10, license, -1, NULL);
e49b93d1
MT
1424 if (r) {
1425 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
687961c3 1426 goto ERROR;
e49b93d1
MT
1427 }
1428
1429 // Bind summary
74468e4f 1430 const char* summary = pakfire_package_get_string(pkg, PAKFIRE_PKG_SUMMARY);
e49b93d1 1431
e082fb85 1432 r = sqlite3_bind_text(stmt, 11, summary, -1, NULL);
e49b93d1
MT
1433 if (r) {
1434 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
687961c3 1435 goto ERROR;
e49b93d1
MT
1436 }
1437
1438 // Bind description
74468e4f 1439 const char* description = pakfire_package_get_string(pkg, PAKFIRE_PKG_DESCRIPTION);
e49b93d1 1440
e082fb85 1441 r = sqlite3_bind_text(stmt, 12, description, -1, NULL);
e49b93d1
MT
1442 if (r) {
1443 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
687961c3 1444 goto ERROR;
e49b93d1
MT
1445 }
1446
1447 // Bind uuid
74468e4f 1448 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
e49b93d1 1449
e082fb85 1450 r = sqlite3_bind_text(stmt, 13, uuid, -1, NULL);
e49b93d1
MT
1451 if (r) {
1452 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
687961c3 1453 goto ERROR;
e49b93d1
MT
1454 }
1455
1456 // Bind vendor
74468e4f 1457 const char* vendor = pakfire_package_get_string(pkg, PAKFIRE_PKG_VENDOR);
e49b93d1 1458
e082fb85 1459 r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
e49b93d1
MT
1460 if (r) {
1461 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
687961c3 1462 goto ERROR;
e49b93d1
MT
1463 }
1464
e49b93d1 1465 // Bind build_host
2ffc704d 1466 const char* build_host = pakfire_package_get_build_host(pkg);
e49b93d1 1467
e082fb85 1468 r = sqlite3_bind_text(stmt, 15, build_host, -1, NULL);
e49b93d1
MT
1469 if (r) {
1470 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
687961c3 1471 goto ERROR;
e49b93d1
MT
1472 }
1473
1474 // Bind build_time
2ffc704d 1475 time_t build_time = pakfire_package_get_build_time(pkg);
e49b93d1 1476
e082fb85 1477 r = sqlite3_bind_int64(stmt, 16, build_time);
e49b93d1
MT
1478 if (r) {
1479 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
687961c3 1480 goto ERROR;
e49b93d1
MT
1481 }
1482
1483 // Bind repository name
4651122b 1484 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
e49b93d1
MT
1485 if (repo) {
1486 const char* repo_name = pakfire_repo_get_name(repo);
1487 pakfire_repo_unref(repo);
1488
e082fb85 1489 r = sqlite3_bind_text(stmt, 17, repo_name, -1, NULL);
e49b93d1 1490 if (r)
687961c3 1491 goto ERROR;
e49b93d1
MT
1492
1493 // No repository?
1494 } else {
e082fb85 1495 r = sqlite3_bind_null(stmt, 17);
e49b93d1 1496 if (r)
687961c3 1497 goto ERROR;
e49b93d1
MT
1498 }
1499
dc0cae14 1500 // installed by the user?
e082fb85 1501 r = sqlite3_bind_int(stmt, 18, userinstalled);
dc0cae14
MT
1502 if (r) {
1503 ERROR(db->pakfire, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle));
687961c3 1504 goto ERROR;
dc0cae14 1505 }
e49b93d1 1506
571539a7
MT
1507 // Source package name
1508 const char* source_name = pakfire_package_get_source_name(pkg);
1509 if (source_name) {
e082fb85 1510 r = sqlite3_bind_text(stmt, 19, source_name, -1, NULL);
571539a7
MT
1511 if (r)
1512 goto ERROR;
1513 } else {
e082fb85 1514 r = sqlite3_bind_null(stmt, 19);
571539a7
MT
1515 if (r)
1516 goto ERROR;
1517 }
1518
1519 // Source EVR
1520 const char* source_evr = pakfire_package_get_source_evr(pkg);
1521 if (source_evr) {
e082fb85 1522 r = sqlite3_bind_text(stmt, 20, source_evr, -1, NULL);
571539a7
MT
1523 if (r)
1524 goto ERROR;
1525 } else {
e082fb85 1526 r = sqlite3_bind_null(stmt, 20);
571539a7
MT
1527 if (r)
1528 goto ERROR;
1529 }
1530
1531 // Source arch
1532 const char* source_arch = pakfire_package_get_source_arch(pkg);
1533 if (source_arch) {
e082fb85 1534 r = sqlite3_bind_text(stmt, 21, source_arch, -1, NULL);
571539a7
MT
1535 if (r)
1536 goto ERROR;
1537 } else {
e082fb85 1538 r = sqlite3_bind_null(stmt, 21);
571539a7
MT
1539 if (r)
1540 goto ERROR;
1541 }
1542
ca002cae 1543 // Distribution
74468e4f 1544 const char* distribution = pakfire_package_get_string(pkg, PAKFIRE_PKG_DISTRO);
ca002cae 1545 if (distribution) {
e082fb85 1546 r = sqlite3_bind_text(stmt, 22, distribution, -1, NULL);
ca002cae
MT
1547 if (r)
1548 goto ERROR;
1549 } else {
e082fb85 1550 r = sqlite3_bind_null(stmt, 22);
ca002cae
MT
1551 if (r)
1552 goto ERROR;
1553 }
1554
e49b93d1
MT
1555 // Run query
1556 do {
1557 r = sqlite3_step(stmt);
1558 } while (r == SQLITE_BUSY);
1559
1560 if (r != SQLITE_DONE) {
1561 ERROR(db->pakfire, "Could not add package to database: %s\n",
1562 sqlite3_errmsg(db->handle));
687961c3
MT
1563 r = 1;
1564 goto ERROR;
e49b93d1
MT
1565 }
1566
f5c77233
MT
1567 // Save package ID
1568 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1569
1fb2b526
MT
1570 // Add dependencies
1571 r = pakfire_db_add_dependencies(db, packages_id, pkg);
1572 if (r)
687961c3 1573 goto ERROR;
1fb2b526 1574
f5c77233
MT
1575 // Add files
1576 r = pakfire_db_add_files(db, packages_id, archive);
1577 if (r)
687961c3 1578 goto ERROR;
e49b93d1 1579
265f539a
MT
1580 // Add scriptlets
1581 r = pakfire_db_add_scriptlets(db, packages_id, archive);
1582 if (r)
687961c3 1583 goto ERROR;
e49b93d1 1584
687961c3 1585ERROR:
f5c77233
MT
1586 if (stmt)
1587 sqlite3_finalize(stmt);
e49b93d1 1588
687961c3
MT
1589 // Commit or rollback
1590 if (r)
1591 pakfire_db_rollback(db);
1592 else
1593 r = pakfire_db_commit(db);
e49b93d1 1594
687961c3 1595 return r;
eafbe2ce
MT
1596}
1597
31480bee 1598int pakfire_db_remove_package(struct pakfire_db* db, struct pakfire_package* pkg) {
432a328a
MT
1599 sqlite3_stmt* stmt = NULL;
1600 int r = 1;
1601
687961c3
MT
1602 // Begin a new transaction
1603 r = pakfire_db_begin_transaction(db);
1604 if (r)
1605 goto ERROR;
1606
432a328a 1607 // Fetch the package's UUID
74468e4f 1608 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
432a328a
MT
1609 if (!uuid) {
1610 ERROR(db->pakfire, "Package has no UUID\n");
687961c3 1611 r = 1;
432a328a
MT
1612 goto ERROR;
1613 }
1614
1615 r = sqlite3_prepare_v2(db->handle,
1616 "DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
1617 if (r) {
1618 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
1619 sqlite3_errmsg(db->handle));
1620 goto ERROR;
1621 }
1622
1623 // Bind UUID
1624 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1625 if (r) {
1626 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
687961c3 1627 goto ERROR;
432a328a
MT
1628 }
1629
1630 // Execute query
1631 do {
1632 r = sqlite3_step(stmt);
1633 } while (r == SQLITE_BUSY);
1634
1635 // Check if we have been successful
1636 if (r != SQLITE_DONE) {
1637 ERROR(db->pakfire, "Could not delete package %s\n", uuid);
1638 r = 1;
1639 goto ERROR;
1640 }
1641
687961c3 1642 // All done
432a328a
MT
1643 r = 0;
1644
1645ERROR:
1646 if (stmt)
1647 sqlite3_finalize(stmt);
1648
687961c3
MT
1649 // Commit or rollback
1650 if (r)
1651 pakfire_db_rollback(db);
1652 else
1653 r = pakfire_db_commit(db);
1654
432a328a 1655 return r;
eafbe2ce 1656}
f6942b34
MT
1657
1658struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
31480bee 1659 struct pakfire_package* pkg, const char* type) {
f6942b34
MT
1660 struct pakfire_scriptlet* scriptlet = NULL;
1661 sqlite3_stmt* stmt = NULL;
1662 int r = 1;
1663
1664 // Fetch the package's UUID
74468e4f 1665 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
f6942b34
MT
1666 if (!uuid) {
1667 ERROR(db->pakfire, "Package has no UUID\n");
1668 goto ERROR;
1669 }
1670
7bb92ae3 1671 const char* sql = "SELECT scriptlets.scriptlet FROM packages \
f6942b34
MT
1672 JOIN scriptlets ON packages.id = scriptlets.pkg \
1673 WHERE packages.uuid = ? AND scriptlets.type = ?";
1674
1675 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1676 if (r) {
1677 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1678 sql, sqlite3_errmsg(db->handle));
1679 goto ERROR;
1680 }
1681
1682 // Bind UUID
1683 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1684 if (r) {
1685 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1686 goto ERROR;
1687 }
1688
a0097ba2 1689 r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
f6942b34
MT
1690 if (r) {
1691 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
1692 goto ERROR;
1693 }
1694
a0097ba2 1695 DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
f6942b34
MT
1696
1697 // Execute query
1698 do {
1699 r = sqlite3_step(stmt);
1700 } while (r == SQLITE_BUSY);
1701
1702 // We have some payload
1703 if (r == SQLITE_ROW) {
1704 const void* data = sqlite3_column_blob(stmt, 1);
1705 ssize_t size = sqlite3_column_bytes(stmt, 1);
1706
1707 // Create a scriptlet object
a0097ba2
MT
1708 r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
1709 if (r)
f6942b34
MT
1710 goto ERROR;
1711 }
1712
1713ERROR:
1714 if (stmt)
1715 sqlite3_finalize(stmt);
1716
1717 return scriptlet;
1718}
361ca45f 1719
4651122b 1720static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* repo, sqlite3_stmt* stmt) {
31480bee 1721 struct pakfire_package* pkg = NULL;
361ca45f
MT
1722 int r = 1;
1723
1724 // Name
1725 const char* name = (const char*)sqlite3_column_text(stmt, 0);
1726 if (!name) {
1727 ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
1728 goto ERROR;
1729 }
1730
6ed66687
MT
1731 // EVR
1732 const char* evr = (const char*)sqlite3_column_text(stmt, 1);
1733 if (!evr) {
1734 ERROR(db->pakfire, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
361ca45f
MT
1735 goto ERROR;
1736 }
1737
1738 // Arch
6ed66687 1739 const char* arch = (const char*)sqlite3_column_text(stmt, 2);
361ca45f
MT
1740 if (!arch) {
1741 ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
1742 goto ERROR;
1743 }
1744
361ca45f 1745 // Create package
33ad2a01
MT
1746 r = pakfire_package_create(&pkg, db->pakfire, repo, name, evr, arch);
1747 if (r) {
361ca45f
MT
1748 ERROR(db->pakfire, "Could not create package\n");
1749 goto ERROR;
1750 }
1751
ac71886a
MT
1752 // ID
1753 uint64_t id = sqlite3_column_int64(stmt, 3);
1754 if (id)
1755 pakfire_package_set_dbid(pkg, id);
1756
7f826034 1757 // Groups
ac71886a 1758 const char* groups = (const char*)sqlite3_column_text(stmt, 4);
7f826034 1759 if (groups) {
74468e4f
MT
1760 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_GROUPS, groups);
1761 if (r)
1762 goto ERROR;
7f826034
MT
1763 }
1764
1765 // Filename
ac71886a 1766 const char* filename = (const char*)sqlite3_column_text(stmt, 5);
7f826034 1767 if (filename) {
0aade652
MT
1768 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_FILENAME, filename);
1769 if (r)
1770 goto ERROR;
7f826034
MT
1771 }
1772
1773 // Size
ac71886a 1774 size_t size = sqlite3_column_int64(stmt, 6);
7f826034
MT
1775 if (size) {
1776 pakfire_package_set_downloadsize(pkg, size);
1777 }
1778
1779 // Installed size
ac71886a 1780 size = sqlite3_column_int64(stmt, 7);
7f826034
MT
1781 if (size) {
1782 pakfire_package_set_installsize(pkg, size);
1783 }
1784
e082fb85
MT
1785 // Digest type
1786 enum pakfire_digest_types digest_type = sqlite3_column_int64(stmt, 8);
1787 size_t digest_length = 0;
b28af23a 1788
e082fb85
MT
1789 // Digest length
1790
1791 // Digest
1792 const unsigned char* digest = sqlite3_column_blob(stmt, 9);
1793 if (digest_type && digest) {
1794 pakfire_package_set_digest(pkg, digest_type, digest, digest_length);
7f826034
MT
1795 }
1796
1797 // License
e082fb85 1798 const char* license = (const char*)sqlite3_column_text(stmt, 10);
7f826034 1799 if (license) {
74468e4f
MT
1800 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_LICENSE, license);
1801 if (r)
1802 goto ERROR;
7f826034
MT
1803 }
1804
1805 // Summary
e082fb85 1806 const char* summary = (const char*)sqlite3_column_text(stmt, 11);
7f826034 1807 if (summary) {
74468e4f
MT
1808 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SUMMARY, summary);
1809 if (r)
1810 goto ERROR;
7f826034
MT
1811 }
1812
1813 // Description
e082fb85 1814 const char* description = (const char*)sqlite3_column_text(stmt, 12);
7f826034 1815 if (description) {
74468e4f
MT
1816 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
1817 if (r)
1818 goto ERROR;
7f826034
MT
1819 }
1820
1821 // UUID
e082fb85 1822 const char* uuid = (const char*)sqlite3_column_text(stmt, 13);
7f826034 1823 if (uuid) {
74468e4f
MT
1824 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_UUID, uuid);
1825 if (r)
1826 goto ERROR;
7f826034
MT
1827 }
1828
1829 // Vendor
e082fb85 1830 const char* vendor = (const char*)sqlite3_column_text(stmt, 14);
7f826034 1831 if (vendor) {
74468e4f
MT
1832 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_VENDOR, vendor);
1833 if (r)
1834 goto ERROR;
7f826034
MT
1835 }
1836
1837 // Build Host
e082fb85 1838 const char* build_host = (const char*)sqlite3_column_text(stmt, 15);
7f826034 1839 if (build_host) {
2ffc704d 1840 pakfire_package_set_build_host(pkg, build_host);
7f826034
MT
1841 }
1842
1843 // Build Time
e082fb85 1844 time_t build_time = sqlite3_column_int64(stmt, 16);
7f826034 1845 if (build_time) {
2ffc704d 1846 pakfire_package_set_build_time(pkg, build_time);
7f826034
MT
1847 }
1848
af647c55 1849 // Install Time
e082fb85 1850 time_t install_time = sqlite3_column_int64(stmt, 17);
af647c55
MT
1851 if (install_time) {
1852 pakfire_package_set_install_time(pkg, install_time);
1853 }
1854
c9c03e6a 1855 // installed by user?
e082fb85 1856 int userinstalled = sqlite3_column_int(stmt, 18);
c9c03e6a
MT
1857 if (userinstalled)
1858 pakfire_db_add_userinstalled(db->pakfire, name);
1859
d995f7fc 1860 // Files
e082fb85 1861 const char* files = (const char*)sqlite3_column_text(stmt, 19);
d995f7fc 1862 if (files) {
d995f7fc
MT
1863 r = pakfire_package_set_filelist_from_string(pkg, files);
1864 if (r)
1865 goto ERROR;
1866 }
1867
24be412a
MT
1868 // Dependencies
1869
1870 const struct dependency {
1871 unsigned int field;
31480bee 1872 void (*func)(struct pakfire_package* pkg, const char* dep);
24be412a 1873 } dependencies[] = {
e082fb85
MT
1874 { 20, pakfire_package_add_provides },
1875 { 21, pakfire_package_add_prerequires },
1876 { 22, pakfire_package_add_requires },
1877 { 23, pakfire_package_add_conflicts },
1878 { 24, pakfire_package_add_obsoletes },
1879 { 25, pakfire_package_add_recommends },
1880 { 26, pakfire_package_add_suggests },
1881 { 27, pakfire_package_add_supplements },
1882 { 28, pakfire_package_add_enhances },
24be412a
MT
1883 { 0, NULL },
1884 };
1885
1886 for (const struct dependency* deps = dependencies; deps->field; deps++) {
1887 const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
1888 if (relations) {
4abdf39d 1889 pakfire_str2deps(db->pakfire, pkg, deps->func, relations);
24be412a
MT
1890 }
1891 }
1892
571539a7 1893 // Source package
e082fb85 1894 const char* source_name = (const char*)sqlite3_column_text(stmt, 29);
571539a7
MT
1895 if (source_name)
1896 pakfire_package_set_source_name(pkg, source_name);
1897
1898 // Source EVR
e082fb85 1899 const char* source_evr = (const char*)sqlite3_column_text(stmt, 30);
571539a7
MT
1900 if (source_evr)
1901 pakfire_package_set_source_evr(pkg, source_evr);
1902
1903 // Source arch
e082fb85 1904 const char* source_arch = (const char*)sqlite3_column_text(stmt, 31);
571539a7
MT
1905 if (source_arch)
1906 pakfire_package_set_source_arch(pkg, source_arch);
1907
ca002cae 1908 // Distribution
e082fb85 1909 const char* distribution = (const char*)sqlite3_column_text(stmt, 32);
74468e4f
MT
1910 if (distribution) {
1911 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
1912 if (r)
1913 goto ERROR;
1914 }
ca002cae 1915
361ca45f
MT
1916 // Success
1917 r = 0;
1918
1919ERROR:
361ca45f
MT
1920 if (pkg)
1921 pakfire_package_unref(pkg);
1922
1923 return r;
1924}
1925
4651122b 1926int pakfire_db_load(struct pakfire_db* db, struct pakfire_repo* repo) {
361ca45f
MT
1927 sqlite3_stmt* stmt = NULL;
1928 int r = 1;
1929
1930 DEBUG(db->pakfire, "Loading package database...\n");
1931
7fe22178
MT
1932 // Drop contents of the repository
1933 pakfire_repo_clear(repo);
1934
788221bd
MT
1935 // Save starting time
1936 clock_t t_start = clock();
1937 clock_t t_end;
1938
361ca45f
MT
1939 const char* sql =
1940 "SELECT "
571539a7
MT
1941 "name, "
1942 "evr, "
1943 "arch, "
1944 "id, "
1945 "groups, "
1946 "filename, "
1947 "size, "
1948 "inst_size, "
e082fb85 1949 "digest_type, "
571539a7
MT
1950 "digest, "
1951 "license, "
1952 "summary, "
1953 "description, "
1954 "uuid, "
1955 "vendor, "
1956 "build_host, "
1957 "build_time, "
1958 "strftime('%s', installed) AS installed, "
1959 "userinstalled, "
d995f7fc 1960 "("
32485f6c 1961 "SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id"
24be412a
MT
1962 ") AS files, "
1963 "("
1964 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1965 "WHERE d.pkg = packages.id AND d.type = 'provides'"
1966 ") AS provides, "
1967 "("
1968 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1969 "WHERE d.pkg = packages.id AND d.type = 'prerequires'"
1970 ") AS prerequires, "
1971 "("
1972 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1973 "WHERE d.pkg = packages.id AND d.type = 'requires'"
1974 ") AS requires, "
1975 "("
1976 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1977 "WHERE d.pkg = packages.id AND d.type = 'conflicts'"
1978 ") AS conflicts, "
1979 "("
1980 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1981 "WHERE d.pkg = packages.id AND d.type = 'obsoletes'"
1982 ") AS obsoletes, "
1983 "("
1984 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1985 "WHERE d.pkg = packages.id AND d.type = 'recommends'"
1986 ") AS recommends, "
1987 "("
1988 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1989 "WHERE d.pkg = packages.id AND d.type = 'suggests'"
8fe2e4ba
MT
1990 ") AS suggests, "
1991 "("
1992 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1993 "WHERE d.pkg = packages.id AND d.type = 'supplements'"
1994 ") AS supplements, "
1995 "("
1996 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1997 "WHERE d.pkg = packages.id AND d.type = 'enhances'"
571539a7
MT
1998 ") AS enhances, "
1999 "source_name, "
2000 "source_evr, "
ca002cae
MT
2001 "source_arch, "
2002 "distribution "
361ca45f
MT
2003 "FROM "
2004 "packages"
2005 ";";
2006
2007 // Prepare the statement
2008 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2009 if (r) {
2010 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2011 sql, sqlite3_errmsg(db->handle));
2012 goto ERROR;
2013 }
2014
2015 for (;;) {
2016 // Execute query
2017 r = sqlite3_step(stmt);
2018
2019 switch (r) {
2020 // Retry if the database was busy
2021 case SQLITE_BUSY:
2022 continue;
2023
2024 // Read a row
2025 case SQLITE_ROW:
2026 r = pakfire_db_load_package(db, repo, stmt);
2027 if (r)
2028 goto ERROR;
2029 break;
2030
2031 // All rows have been processed
2032 case SQLITE_DONE:
2033 goto END;
2034
2035 // Go to error in any other cases
2036 default:
2037 goto ERROR;
2038 }
2039 }
2040
2041END:
788221bd
MT
2042 // Save time when we finished
2043 t_end = clock();
2044
2045 DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
2046 (double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
361ca45f 2047
9eba3d65
MT
2048 // Mark repository as changed
2049 pakfire_repo_has_changed(repo);
05336f5e 2050
361ca45f
MT
2051 // All done
2052 r = 0;
2053
2054ERROR:
b027597a 2055 if (r) {
361ca45f 2056 ERROR(db->pakfire, "Failed reading package database: %d\n", r);
b027597a
MT
2057 pakfire_repo_clear(repo);
2058 }
361ca45f
MT
2059
2060 if (stmt)
2061 sqlite3_finalize(stmt);
2062
2063 return r;
2064}
ac71886a 2065
923d6794 2066static int pakfire_db_load_file_digest(struct pakfire_db* db, struct pakfire_file* file,
c52e0148 2067 sqlite3_stmt* stmt, const enum pakfire_digest_types type, const int field) {
923d6794
MT
2068 // Fetch digest
2069 const unsigned char* digest = sqlite3_column_blob(stmt, field);
2070
2071 // Nothing further to do if field is NULL
2072 if (!digest)
2073 return 0;
2074
2075 // Length of the stored value
2076 const size_t length = sqlite3_column_bytes(stmt, field);
2077
923d6794 2078 // Store digest
399d14c2 2079 return pakfire_file_set_digest(file, type, digest, length);
923d6794
MT
2080}
2081
1bbbfb9e 2082static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* filelist,
ac71886a
MT
2083 sqlite3_stmt* stmt) {
2084 struct pakfire_file* file = NULL;
ac71886a
MT
2085 int r;
2086
2087 // Create a new file object
2088 r = pakfire_file_create(&file, db->pakfire);
2089 if (r)
2090 goto ERROR;
2091
2092 // Path
2093 const char* path = (const char*)sqlite3_column_text(stmt, 0);
f04369e6
MT
2094
2095 // Abort if no path is set
2096 if (!path) {
2097 ERROR(db->pakfire, "File has no path\n");
2098 r = 1;
2099 goto ERROR;
2100 }
2101
2102 // Set path
2103 r = pakfire_file_set_path(file, path);
2104 if (r) {
2105 ERROR(db->pakfire, "%s: Could not set path '%s': %m\n", path, path);
2106 goto ERROR;
2107 }
ac71886a 2108
ac71886a
MT
2109 // Size
2110 size_t size = sqlite3_column_int64(stmt, 1);
2111 if (size)
2112 pakfire_file_set_size(file, size);
2113
2114 // Mode
2115 mode_t mode = sqlite3_column_int(stmt, 2);
2116 if (mode)
2117 pakfire_file_set_mode(file, mode);
2118
302e3253
MT
2119 // uname
2120 const char* uname = (const char*)sqlite3_column_text(stmt, 3);
f04369e6
MT
2121
2122 // Abort if no user is set
302e3253 2123 if (!uname) {
f04369e6
MT
2124 ERROR(db->pakfire, "%s: No user\n", path);
2125 r = 1;
2126 goto ERROR;
2127 }
2128
302e3253
MT
2129 // Set uname
2130 r = pakfire_file_set_uname(file, uname);
f04369e6 2131 if (r) {
302e3253 2132 ERROR(db->pakfire, "%s: Could not set user '%s': %m\n", path, uname);
f04369e6
MT
2133 goto ERROR;
2134 }
ac71886a 2135
302e3253
MT
2136 // gname
2137 const char* gname = (const char*)sqlite3_column_text(stmt, 4);
f04369e6
MT
2138
2139 // Abort if no group is set
302e3253 2140 if (!gname) {
f04369e6
MT
2141 ERROR(db->pakfire, "%s: No group\n", path);
2142 r = 1;
2143 goto ERROR;
2144 }
2145
302e3253
MT
2146 // Set gname
2147 r = pakfire_file_set_gname(file, gname);
f04369e6 2148 if (r) {
302e3253 2149 ERROR(db->pakfire, "%s: Could not set group '%s': %m\n", path, gname);
f04369e6
MT
2150 goto ERROR;
2151 }
ac71886a
MT
2152
2153 // ctime
2154 time_t ctime = sqlite3_column_int64(stmt, 5);
2155 if (ctime)
2156 pakfire_file_set_ctime(file, ctime);
2157
2158 // mtime
2159 time_t mtime = sqlite3_column_int64(stmt, 6);
2160 if (mtime)
2161 pakfire_file_set_mtime(file, mtime);
2162
a3845369 2163 // SHA2-512 Digest
4500ed0a 2164 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_512, 7);
923d6794
MT
2165 if (r)
2166 goto ERROR;
2167
a3845369 2168 // SHA2-256 Digest
4500ed0a 2169 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_256, 8);
923d6794
MT
2170 if (r)
2171 goto ERROR;
2172
a3845369
MT
2173 // BLAKE2b512 Digest
2174 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2B512, 9);
2175 if (r)
2176 goto ERROR;
2177
2178 // BLAKE2s256 Digest
2179 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2S256, 10);
2180 if (r)
2181 goto ERROR;
2182
2183 // SHA3-512 Digest
2184 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_512, 11);
2185 if (r)
2186 goto ERROR;
2187
2188 // SHA3-256 Digest
2189 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_256, 12);
2190 if (r)
2191 goto ERROR;
2192
ac71886a
MT
2193 // Append the file to the filelist
2194 r = pakfire_filelist_append(filelist, file);
f04369e6
MT
2195 if (r)
2196 goto ERROR;
ac71886a
MT
2197
2198ERROR:
2199 if (file)
2200 pakfire_file_unref(file);
2201
2202 return r;
2203}
2204
3f310c26
MT
2205int pakfire_db_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist) {
2206 struct pakfire_filelist* list = NULL;
2207 sqlite3_stmt* stmt = NULL;
2208 int r;
2209
2210 const char* sql =
2211 "SELECT "
2212 "path, "
2213 "size, "
2214 "mode, "
ca8fe553
MT
2215 "uname, "
2216 "gname, "
3f310c26 2217 "ctime, "
923d6794 2218 "mtime, "
a3845369
MT
2219 "digest_sha2_512, "
2220 "digest_sha2_256, "
2221 "digest_blake2b512, "
2222 "digest_blake2s256, "
2223 "digest_sha3_512, "
2224 "digest_sha3_256 "
3f310c26
MT
2225 "FROM files "
2226 "ORDER BY path"
2227 ";";
2228
2229 // Prepare the statement
2230 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2231 if (r) {
2232 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2233 sql, sqlite3_errmsg(db->handle));
2234 goto ERROR;
2235 }
2236
2237 // Create a new filelist
2238 r = pakfire_filelist_create(&list, db->pakfire);
2239 if (r)
2240 goto ERROR;
2241
2242 // Iterate over all rows
2243 for (;;) {
2244 // Execute query
2245 r = sqlite3_step(stmt);
2246
2247 switch (r) {
2248 // Retry if the database was busy
2249 case SQLITE_BUSY:
2250 continue;
2251
2252 // Read a row
2253 case SQLITE_ROW:
2254 r = pakfire_db_load_file(db, list, stmt);
2255 if (r)
2256 goto ERROR;
2257 break;
2258
2259 // All rows have been processed
2260 case SQLITE_DONE:
2261 r = 0;
2262 goto END;
2263
2264 // Go to error in any other cases
2265 default:
2266 goto ERROR;
2267 }
2268 }
2269
2270END:
2271 // Return the filelist
2272 *filelist = pakfire_filelist_ref(list);
2273
2274ERROR:
2275 if (r)
2276 ERROR(db->pakfire, "Could not fetch filelist: %m\n");
2277
2278 if (stmt)
2279 sqlite3_finalize(stmt);
2280 if (list)
2281 pakfire_filelist_unref(list);
2282
2283 return r;
2284}
2285
1bbbfb9e 2286int pakfire_db_package_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist,
31480bee 2287 struct pakfire_package* pkg) {
1bbbfb9e 2288 struct pakfire_filelist* fl = NULL;
ac71886a
MT
2289 sqlite3_stmt* stmt = NULL;
2290 int r = 1;
2291
2292 // Fetch the package ID
2293 uint64_t id = pakfire_package_get_dbid(pkg);
2294 if (!id) {
2295 ERROR(db->pakfire, "Package did not have an ID\n");
2296 return 1;
2297 }
2298
2299 // Create a new filelist
2300 r = pakfire_filelist_create(&fl, db->pakfire);
2301 if (r) {
2302 ERROR(db->pakfire, "Could not create filelist: %m\n");
2303 goto ERROR;
2304 }
2305
2306 const char* sql =
2307 "SELECT "
2308 "path, "
2309 "size, "
2310 "mode, "
ca8fe553
MT
2311 "uname, "
2312 "gname, "
ac71886a 2313 "ctime, "
923d6794 2314 "mtime, "
ca8fe553
MT
2315 "digest_sha2_512, "
2316 "digest_sha2_256, "
2317 "digest_blake2b512, "
2318 "digest_blake2s256, "
2319 "digest_sha3_512, "
2320 "digest_sha3_256 "
ac71886a
MT
2321 "FROM files "
2322
2323 // Select all files that belong to this package
2324 "WHERE "
2325 "pkg = ? "
2326
2327 // Filter out any files that are also in a different package (i.e. an update
2328 // that has already been installed and this is the cleanup of the obsolete pkg)
2329 "AND "
2330 "NOT EXISTS ("
2331 "SELECT "
2332 "1 "
2333 "FROM files AS duplicates "
2334 "WHERE "
2335 "files.path = duplicates.path "
2336 "AND "
2337 "files.pkg != duplicates.pkg"
2338 ") "
2339
2340 // Return the longest paths first
2341 "ORDER BY "
2342 "length(path) DESC"
2343 ";";
2344
2345 // Prepare the statement
2346 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2347 if (r) {
2348 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2349 sql, sqlite3_errmsg(db->handle));
2350 goto ERROR;
2351 }
2352
2353 // Bind package ID
2354 r = sqlite3_bind_int64(stmt, 1, id);
2355 if (r) {
2356 ERROR(db->pakfire, "Could not bind package ID: %s\n", sqlite3_errmsg(db->handle));
2357 goto ERROR;
2358 }
2359
2360 for (;;) {
2361 // Execute query
2362 r = sqlite3_step(stmt);
2363
2364 switch (r) {
2365 // Retry if the database was busy
2366 case SQLITE_BUSY:
2367 continue;
2368
2369 // Read a row
2370 case SQLITE_ROW:
2371 r = pakfire_db_load_file(db, fl, stmt);
2372 if (r)
2373 goto ERROR;
2374 break;
2375
2376 // All rows have been processed
2377 case SQLITE_DONE:
2378 goto END;
2379
2380 // Go to error in any other cases
2381 default:
2382 goto ERROR;
2383 }
2384 }
2385
2386END:
2387 *filelist = pakfire_filelist_ref(fl);
2388 r = 0;
2389
2390ERROR:
2391 if (stmt)
2392 sqlite3_finalize(stmt);
2393 if (fl)
2394 pakfire_filelist_unref(fl);
2395
2396 return r;
2397}