]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
filelists: Rename *_append() to *_add()
[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 841 sqlite3_stmt* stmt = NULL;
6f3fad3b 842 char** list = NULL;
1fb2b526
MT
843 int r = 1;
844
845 const char* sql = "INSERT INTO dependencies(pkg, type, dependency) VALUES(?, ?, ?)";
846
847 // Prepare the statement
848 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
849 if (r) {
850 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
851 sql, sqlite3_errmsg(db->handle));
852 goto END;
853 }
854
6f3fad3b
MT
855 for (const struct pakfire_dep* dep = pakfire_deps; dep->key; dep++) {
856 list = pakfire_package_get_deps(pkg, dep->key);
857 if (!list) {
858 r = 1;
859 goto END;
860 }
1fb2b526 861
6f3fad3b 862 for (char** d = list; *d; d++) {
1fb2b526
MT
863 // Bind package ID
864 r = sqlite3_bind_int64(stmt, 1, id);
865 if (r) {
866 ERROR(db->pakfire, "Could not bind id: %s\n",
867 sqlite3_errmsg(db->handle));
1fb2b526
MT
868 goto END;
869 }
870
871 // Bind type
6f3fad3b 872 r = sqlite3_bind_text(stmt, 2, dep->name, -1, NULL);
1fb2b526
MT
873 if (r) {
874 ERROR(db->pakfire, "Could not bind type: %s\n",
875 sqlite3_errmsg(db->handle));
1fb2b526
MT
876 goto END;
877 }
878
879 // Bind dependency
6f3fad3b 880 r = sqlite3_bind_text(stmt, 3, *d, -1, NULL);
1fb2b526
MT
881 if (r) {
882 ERROR(db->pakfire, "Could not bind dependency: %s\n",
883 sqlite3_errmsg(db->handle));
1fb2b526
MT
884 goto END;
885 }
886
887 // Execute query
888 do {
889 r = sqlite3_step(stmt);
890 } while (r == SQLITE_BUSY);
891
1fb2b526
MT
892 // Reset bound values
893 sqlite3_reset(stmt);
894 }
1fb2b526
MT
895 }
896
897 // All okay
898 r = 0;
899
900END:
901 if (stmt)
902 sqlite3_finalize(stmt);
6f3fad3b
MT
903 if (list) {
904 for (char** dep = list; *dep; dep++)
727f2721 905 free(*dep);
6f3fad3b
MT
906 free(list);
907 }
1fb2b526
MT
908
909 return r;
910}
911
a3845369
MT
912static int pakfire_db_bind_digest(struct pakfire_db* db, sqlite3_stmt* stmt, const int field,
913 struct pakfire_file* file, const enum pakfire_digest_types type) {
914 const unsigned char* digest = NULL;
915 size_t length = 0;
916
917 // Fetch the digest
918 digest = pakfire_file_get_digest(file, type, &length);
919
920 // If this digest isn't set, just bind NULL
921 if (!digest)
922 return sqlite3_bind_null(stmt, field);
923
924 // Otherwise bind the data blob
925 return sqlite3_bind_blob(stmt, field, digest, length, NULL);
926}
927
900faa2f 928static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
f5c77233 929 sqlite3_stmt* stmt = NULL;
dccd04a4 930 int r = 1;
f5c77233
MT
931
932 // Get the filelist from the archive
1bbbfb9e 933 struct pakfire_filelist* filelist = pakfire_archive_get_filelist(archive);
5e9463ec 934 if (!filelist) {
f5c77233
MT
935 ERROR(db->pakfire, "Could not fetch filelist from archive\n");
936 return 1;
937 }
938
5e9463ec 939 // Nothing to do if the list is empty
9a6e3e2d
MT
940 if (pakfire_filelist_is_empty(filelist)) {
941 r = 0;
5e9463ec 942 goto END;
9a6e3e2d 943 }
5e9463ec 944
a3845369
MT
945 const char* sql =
946 "INSERT INTO "
947 " files("
948 "pkg, "
949 "path, "
950 "size, "
951 "config, "
952 "datafile, "
953 "mode, "
df824b86
MT
954 "uname, "
955 "gname, "
a3845369
MT
956 "ctime, "
957 "mtime, "
958 "capabilities, "
959 "digest_sha2_512, "
960 "digest_sha2_256, "
961 "digest_blake2b512, "
962 "digest_blake2s256, "
963 "digest_sha3_512, "
964 "digest_sha3_256"
965 ") "
966 "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
f5c77233
MT
967
968 // Prepare the statement
923d6794 969 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
f5c77233
MT
970 if (r) {
971 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
972 sql, sqlite3_errmsg(db->handle));
973 goto END;
974 }
975
94ff3014 976 for (unsigned int i = 0; i < pakfire_filelist_length(filelist); i++) {
5803b5f6 977 struct pakfire_file* file = pakfire_filelist_get(filelist, i);
5e9463ec 978
f5c77233
MT
979 // Bind package ID
980 r = sqlite3_bind_int64(stmt, 1, id);
981 if (r) {
982 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 983 pakfire_file_unref(file);
f5c77233
MT
984 goto END;
985 }
986
987 // Bind name
32485f6c 988 const char* path = pakfire_file_get_path(file);
f5c77233 989
32485f6c 990 r = sqlite3_bind_text(stmt, 2, path, -1, NULL);
f5c77233 991 if (r) {
32485f6c 992 ERROR(db->pakfire, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 993 pakfire_file_unref(file);
f5c77233
MT
994 goto END;
995 }
996
997 // Bind size
998 size_t size = pakfire_file_get_size(file);
999
1000 r = sqlite3_bind_int64(stmt, 3, size);
1001 if (r) {
1002 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1003 pakfire_file_unref(file);
f5c77233
MT
1004 goto END;
1005 }
1006
f5c77233 1007 // Bind config - XXX TODO
b72bae3f 1008 r = sqlite3_bind_null(stmt, 4);
f5c77233
MT
1009 if (r) {
1010 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1011 pakfire_file_unref(file);
f5c77233
MT
1012 goto END;
1013 }
1014
1015 // Bind datafile - XXX TODO
b72bae3f 1016 r = sqlite3_bind_null(stmt, 5);
f5c77233
MT
1017 if (r) {
1018 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1019 pakfire_file_unref(file);
f5c77233
MT
1020 goto END;
1021 }
1022
1023 // Bind mode
1024 mode_t mode = pakfire_file_get_mode(file);
1025
b72bae3f 1026 r = sqlite3_bind_int64(stmt, 6, mode);
f5c77233
MT
1027 if (r) {
1028 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1029 pakfire_file_unref(file);
f5c77233
MT
1030 goto END;
1031 }
1032
302e3253
MT
1033 // Bind uname
1034 const char* uname = pakfire_file_get_uname(file);
f5c77233 1035
302e3253 1036 r = sqlite3_bind_text(stmt, 7, uname, -1, NULL);
f5c77233 1037 if (r) {
302e3253 1038 ERROR(db->pakfire, "Could not bind uname: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1039 pakfire_file_unref(file);
f5c77233
MT
1040 goto END;
1041 }
1042
302e3253
MT
1043 // Bind gname
1044 const char* gname = pakfire_file_get_gname(file);
f5c77233 1045
302e3253 1046 r = sqlite3_bind_text(stmt, 8, gname, -1, NULL);
f5c77233 1047 if (r) {
302e3253 1048 ERROR(db->pakfire, "Could not bind gname: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1049 pakfire_file_unref(file);
f5c77233
MT
1050 goto END;
1051 }
1052
ef4e8460
MT
1053 // Bind ctime
1054 time_t ctime = pakfire_file_get_ctime(file);
1055
a7e5cf06 1056 r = sqlite3_bind_int64(stmt, 9, ctime);
ef4e8460
MT
1057 if (r) {
1058 ERROR(db->pakfire, "Could not bind ctime: %s\n", sqlite3_errmsg(db->handle));
1059 pakfire_file_unref(file);
1060 goto END;
1061 }
1062
f5c77233 1063 // Bind mtime
ef4e8460 1064 time_t mtime = pakfire_file_get_mtime(file);
f5c77233 1065
a7e5cf06 1066 r = sqlite3_bind_int64(stmt, 10, mtime);
f5c77233
MT
1067 if (r) {
1068 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1069 pakfire_file_unref(file);
f5c77233
MT
1070 goto END;
1071 }
1072
1073 // Bind capabilities - XXX TODO
a7e5cf06 1074 r = sqlite3_bind_null(stmt, 11);
f5c77233
MT
1075 if (r) {
1076 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 1077 pakfire_file_unref(file);
f5c77233
MT
1078 goto END;
1079 }
1080
a3845369
MT
1081 // SHA2-512 Digest
1082 r = pakfire_db_bind_digest(db, stmt, 12, file, PAKFIRE_DIGEST_SHA2_512);
1083 if (r) {
1084 ERROR(db->pakfire, "Could not bind SHA2-512 digest: %s\n",
1085 sqlite3_errmsg(db->handle));
1086 pakfire_file_unref(file);
1087 goto END;
1088 }
923d6794 1089
a3845369
MT
1090 // SHA2-256 Digest
1091 r = pakfire_db_bind_digest(db, stmt, 13, file, PAKFIRE_DIGEST_SHA2_256);
1092 if (r) {
1093 ERROR(db->pakfire, "Could not bind SHA2-256 digest: %s\n",
1094 sqlite3_errmsg(db->handle));
1095 pakfire_file_unref(file);
1096 goto END;
923d6794 1097 }
a3845369
MT
1098
1099 // BLAKE2b512 Digest
1100 r = pakfire_db_bind_digest(db, stmt, 14, file, PAKFIRE_DIGEST_BLAKE2B512);
923d6794 1101 if (r) {
a3845369 1102 ERROR(db->pakfire, "Could not bind BLAKE2b512 digest: %s\n",
923d6794
MT
1103 sqlite3_errmsg(db->handle));
1104 pakfire_file_unref(file);
1105 goto END;
1106 }
1107
a3845369
MT
1108 // BLAKE2s256 Digest
1109 r = pakfire_db_bind_digest(db, stmt, 15, file, PAKFIRE_DIGEST_BLAKE2S256);
1110 if (r) {
1111 ERROR(db->pakfire, "Could not bind BLAKE2s256 digest: %s\n",
1112 sqlite3_errmsg(db->handle));
1113 pakfire_file_unref(file);
1114 goto END;
1115 }
923d6794 1116
a3845369
MT
1117 // SHA3-512 Digest
1118 r = pakfire_db_bind_digest(db, stmt, 16, file, PAKFIRE_DIGEST_SHA3_512);
1119 if (r) {
1120 ERROR(db->pakfire, "Could not bind SHA3-512 digest: %s\n",
1121 sqlite3_errmsg(db->handle));
1122 pakfire_file_unref(file);
1123 goto END;
923d6794 1124 }
a3845369
MT
1125
1126 // SHA3-256 Digest
1127 r = pakfire_db_bind_digest(db, stmt, 17, file, PAKFIRE_DIGEST_SHA3_256);
923d6794 1128 if (r) {
a3845369 1129 ERROR(db->pakfire, "Could not bind SHA3-256 digest: %s\n",
923d6794
MT
1130 sqlite3_errmsg(db->handle));
1131 pakfire_file_unref(file);
1132 goto END;
1133 }
1134
f5c77233
MT
1135 // Execute query
1136 do {
1137 r = sqlite3_step(stmt);
1138 } while (r == SQLITE_BUSY);
1139
5bae3112
MT
1140 // Check for errors
1141 if (r != SQLITE_DONE) {
1142 ERROR(db->pakfire, "Could not add file to database: %s\n",
1143 sqlite3_errmsg(db->handle));
a7e5cf06 1144 pakfire_file_unref(file);
5bae3112
MT
1145 goto END;
1146 }
1147
a7e5cf06
MT
1148 // Move on to next file
1149 pakfire_file_unref(file);
1150
1151 // Reset bound values
1152 sqlite3_reset(stmt);
f5c77233
MT
1153 }
1154
1155 // All okay
1156 r = 0;
1157
1158END:
1159 if (stmt)
1160 sqlite3_finalize(stmt);
5e9463ec
MT
1161 pakfire_filelist_unref(filelist);
1162
f5c77233
MT
1163 return r;
1164}
1165
900faa2f 1166static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, struct pakfire_archive* archive) {
265f539a 1167 sqlite3_stmt* stmt = NULL;
a0097ba2 1168 size_t size;
265f539a
MT
1169 int r = 1;
1170
265f539a
MT
1171 const char* sql = "INSERT INTO scriptlets(pkg, type, scriptlet) VALUES(?, ?, ?)";
1172
1173 // Prepare the statement
1174 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
1175 if (r) {
1176 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1177 sql, sqlite3_errmsg(db->handle));
1178 goto END;
1179 }
1180
a0097ba2 1181 for (const char** type = pakfire_scriptlet_types; *type; type++) {
265f539a 1182 // Fetch the scriptlet
106d2edd 1183 struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(archive, *type);
a0097ba2 1184 if (!scriptlet)
265f539a 1185 continue;
265f539a
MT
1186
1187 // Bind package ID
1188 r = sqlite3_bind_int64(stmt, 1, id);
1189 if (r) {
1190 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1191 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1192 goto END;
1193 }
1194
1195 // Bind handle
a0097ba2 1196 r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
265f539a
MT
1197 if (r) {
1198 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1199 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1200 goto END;
1201 }
1202
a0097ba2
MT
1203 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
1204
265f539a 1205 // Bind scriptlet
a0097ba2 1206 r = sqlite3_bind_text(stmt, 3, data, size, NULL);
265f539a
MT
1207 if (r) {
1208 ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 1209 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
1210 goto END;
1211 }
1212
1213 // Execute query
1214 do {
1215 r = sqlite3_step(stmt);
1216 } while (r == SQLITE_BUSY);
1217
5bae3112
MT
1218 // Check for errors
1219 if (r != SQLITE_DONE) {
1220 ERROR(db->pakfire, "Could not add scriptlet to database: %s\n",
1221 sqlite3_errmsg(db->handle));
a0097ba2 1222 pakfire_scriptlet_unref(scriptlet);
5bae3112
MT
1223 goto END;
1224 }
1225
a0097ba2
MT
1226 pakfire_scriptlet_unref(scriptlet);
1227
265f539a
MT
1228 // Reset bound values
1229 sqlite3_reset(stmt);
265f539a
MT
1230 }
1231
1232 // All okay
1233 r = 0;
1234
1235END:
1236 if (stmt)
1237 sqlite3_finalize(stmt);
1238
1239 return r;
1240}
1241
9c78c483 1242int pakfire_db_add_package(struct pakfire_db* db,
900faa2f 1243 struct pakfire_package* pkg, struct pakfire_archive* archive, int userinstalled) {
e49b93d1
MT
1244 sqlite3_stmt* stmt = NULL;
1245 int r;
1246
1247 // Begin a new transaction
1248 r = pakfire_db_begin_transaction(db);
1249 if (r)
687961c3 1250 goto ERROR;
e49b93d1 1251
571539a7
MT
1252 const char* sql = "INSERT INTO "
1253 "packages("
1254 "name, "
1255 "evr, "
1256 "arch, "
1257 "groups, "
1258 "filename, "
1259 "size, "
1260 "inst_size, "
e082fb85 1261 "digest_type, "
571539a7
MT
1262 "digest, "
1263 "license, "
1264 "summary, "
1265 "description, "
1266 "uuid, "
1267 "vendor, "
1268 "build_host, "
1269 "build_time, "
1270 "installed, "
1271 "repository, "
1272 "userinstalled, "
1273 "source_name, "
1274 "source_evr, "
ca002cae
MT
1275 "source_arch, "
1276 "distribution"
571539a7
MT
1277 ") VALUES("
1278 "?, "
1279 "?, "
1280 "?, "
1281 "?, "
1282 "?, "
1283 "?, "
1284 "?, "
1285 "?, "
1286 "?, "
1287 "?, "
1288 "?, "
1289 "?, "
1290 "?, "
1291 "?, "
1292 "?, "
e082fb85 1293 "?, "
571539a7
MT
1294 "CURRENT_TIMESTAMP, "
1295 "?, "
1296 "?, "
1297 "?, "
1298 "?, "
ca002cae 1299 "?, "
571539a7
MT
1300 "?"
1301 ")";
e49b93d1
MT
1302
1303 // Prepare the statement
1304 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1305 if (r != SQLITE_OK) {
1306 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
1307 sql, sqlite3_errmsg(db->handle));
687961c3 1308 goto ERROR;
e49b93d1
MT
1309 }
1310
1311 // Bind name
74468e4f 1312 const char* name = pakfire_package_get_string(pkg, PAKFIRE_PKG_NAME);
e49b93d1
MT
1313
1314 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
1315 if (r) {
1316 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
687961c3 1317 goto ERROR;
e49b93d1
MT
1318 }
1319
6ed66687 1320 // Bind evr
74468e4f 1321 const char* evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_EVR);
e49b93d1 1322
6ed66687 1323 r = sqlite3_bind_text(stmt, 2, evr, -1, NULL);
e49b93d1 1324 if (r) {
6ed66687 1325 ERROR(db->pakfire, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
687961c3 1326 goto ERROR;
e49b93d1
MT
1327 }
1328
1329 // Bind arch
74468e4f 1330 const char* arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_ARCH);
e49b93d1 1331
6ed66687 1332 r = sqlite3_bind_text(stmt, 3, arch, -1, NULL);
e49b93d1
MT
1333 if (r) {
1334 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
687961c3 1335 goto ERROR;
e49b93d1
MT
1336 }
1337
1338 // Bind groups
74468e4f
MT
1339 const char* groups = pakfire_package_get_string(pkg, PAKFIRE_PKG_GROUPS);
1340
1eb7f40b 1341 if (groups) {
6ed66687 1342 r = sqlite3_bind_text(stmt, 4, groups, -1, NULL);
1eb7f40b
MT
1343 if (r) {
1344 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
687961c3 1345 goto ERROR;
1eb7f40b 1346 }
e49b93d1 1347
1eb7f40b
MT
1348 // No groups
1349 } else {
6ed66687 1350 r = sqlite3_bind_null(stmt, 4);
1eb7f40b 1351 if (r)
687961c3 1352 goto ERROR;
e49b93d1
MT
1353 }
1354
1355 // Bind filename
0aade652 1356 const char* filename = pakfire_package_get_string(pkg, PAKFIRE_PKG_FILENAME);
e49b93d1 1357
6ed66687 1358 r = sqlite3_bind_text(stmt, 5, filename, -1, NULL);
e49b93d1
MT
1359 if (r) {
1360 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
687961c3 1361 goto ERROR;
e49b93d1
MT
1362 }
1363
1364 // Bind size
3f327c3c 1365 unsigned long long size = pakfire_package_get_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, 0);
e49b93d1 1366
6ed66687 1367 r = sqlite3_bind_int64(stmt, 6, size);
e49b93d1
MT
1368 if (r) {
1369 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
687961c3 1370 goto ERROR;
e49b93d1
MT
1371 }
1372
1373 // Bind installed size
3f327c3c 1374 unsigned long long inst_size = pakfire_package_get_num(pkg, PAKFIRE_PKG_INSTALLSIZE, 0);
e49b93d1 1375
6ed66687 1376 r = sqlite3_bind_int64(stmt, 7, inst_size);
e49b93d1
MT
1377 if (r) {
1378 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
687961c3 1379 goto ERROR;
e49b93d1
MT
1380 }
1381
e082fb85 1382 const unsigned char* digest = NULL;
c52e0148 1383 enum pakfire_digest_types digest_type = 0;
e082fb85 1384 size_t digest_length = 0;
b28af23a 1385
e082fb85
MT
1386 // Fetch the digest
1387 digest = pakfire_package_get_digest(pkg, &digest_type, &digest_length);
1388 if (!digest) {
1389 ERROR(db->pakfire, "Could not fetch the package's digest: %m\n");
1390 r = 1;
1391 goto ERROR;
1392 }
e49b93d1 1393
e082fb85
MT
1394 // Set the digest type
1395 r = sqlite3_bind_int64(stmt, 8, digest_type);
1396 if (r) {
1397 ERROR(db->pakfire, "Could not bind digest type: %s\n", sqlite3_errmsg(db->handle));
1398 goto ERROR;
1399 }
1400
1401 // Set the digest
1402 r = sqlite3_bind_blob(stmt, 9, digest, digest_length, NULL);
1403 if (r) {
1404 ERROR(db->pakfire, "Could not bind digest: %s\n", sqlite3_errmsg(db->handle));
1405 goto ERROR;
e49b93d1
MT
1406 }
1407
1408 // Bind license
74468e4f 1409 const char* license = pakfire_package_get_string(pkg, PAKFIRE_PKG_LICENSE);
e49b93d1 1410
e082fb85 1411 r = sqlite3_bind_text(stmt, 10, license, -1, NULL);
e49b93d1
MT
1412 if (r) {
1413 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
687961c3 1414 goto ERROR;
e49b93d1
MT
1415 }
1416
1417 // Bind summary
74468e4f 1418 const char* summary = pakfire_package_get_string(pkg, PAKFIRE_PKG_SUMMARY);
e49b93d1 1419
e082fb85 1420 r = sqlite3_bind_text(stmt, 11, summary, -1, NULL);
e49b93d1
MT
1421 if (r) {
1422 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
687961c3 1423 goto ERROR;
e49b93d1
MT
1424 }
1425
1426 // Bind description
74468e4f 1427 const char* description = pakfire_package_get_string(pkg, PAKFIRE_PKG_DESCRIPTION);
e49b93d1 1428
e082fb85 1429 r = sqlite3_bind_text(stmt, 12, description, -1, NULL);
e49b93d1
MT
1430 if (r) {
1431 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
687961c3 1432 goto ERROR;
e49b93d1
MT
1433 }
1434
1435 // Bind uuid
74468e4f 1436 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
e49b93d1 1437
e082fb85 1438 r = sqlite3_bind_text(stmt, 13, uuid, -1, NULL);
e49b93d1
MT
1439 if (r) {
1440 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
687961c3 1441 goto ERROR;
e49b93d1
MT
1442 }
1443
1444 // Bind vendor
74468e4f 1445 const char* vendor = pakfire_package_get_string(pkg, PAKFIRE_PKG_VENDOR);
e49b93d1 1446
e082fb85 1447 r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
e49b93d1
MT
1448 if (r) {
1449 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
687961c3 1450 goto ERROR;
e49b93d1
MT
1451 }
1452
e49b93d1 1453 // Bind build_host
1f669e88 1454 const char* build_host = pakfire_package_get_string(pkg, PAKFIRE_PKG_BUILD_HOST);
e49b93d1 1455
e082fb85 1456 r = sqlite3_bind_text(stmt, 15, build_host, -1, NULL);
e49b93d1
MT
1457 if (r) {
1458 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
687961c3 1459 goto ERROR;
e49b93d1
MT
1460 }
1461
1462 // Bind build_time
3f327c3c 1463 time_t build_time = pakfire_package_get_num(pkg, PAKFIRE_PKG_BUILD_TIME, 0);
e49b93d1 1464
e082fb85 1465 r = sqlite3_bind_int64(stmt, 16, build_time);
e49b93d1
MT
1466 if (r) {
1467 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
687961c3 1468 goto ERROR;
e49b93d1
MT
1469 }
1470
1471 // Bind repository name
4651122b 1472 struct pakfire_repo* repo = pakfire_package_get_repo(pkg);
e49b93d1
MT
1473 if (repo) {
1474 const char* repo_name = pakfire_repo_get_name(repo);
1475 pakfire_repo_unref(repo);
1476
e082fb85 1477 r = sqlite3_bind_text(stmt, 17, repo_name, -1, NULL);
e49b93d1 1478 if (r)
687961c3 1479 goto ERROR;
e49b93d1
MT
1480
1481 // No repository?
1482 } else {
e082fb85 1483 r = sqlite3_bind_null(stmt, 17);
e49b93d1 1484 if (r)
687961c3 1485 goto ERROR;
e49b93d1
MT
1486 }
1487
dc0cae14 1488 // installed by the user?
e082fb85 1489 r = sqlite3_bind_int(stmt, 18, userinstalled);
dc0cae14
MT
1490 if (r) {
1491 ERROR(db->pakfire, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle));
687961c3 1492 goto ERROR;
dc0cae14 1493 }
e49b93d1 1494
571539a7 1495 // Source package name
988ce1bc 1496 const char* source_name = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_NAME);
571539a7 1497 if (source_name) {
e082fb85 1498 r = sqlite3_bind_text(stmt, 19, source_name, -1, NULL);
571539a7
MT
1499 if (r)
1500 goto ERROR;
1501 } else {
e082fb85 1502 r = sqlite3_bind_null(stmt, 19);
571539a7
MT
1503 if (r)
1504 goto ERROR;
1505 }
1506
1507 // Source EVR
988ce1bc 1508 const char* source_evr = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_EVR);
571539a7 1509 if (source_evr) {
e082fb85 1510 r = sqlite3_bind_text(stmt, 20, source_evr, -1, NULL);
571539a7
MT
1511 if (r)
1512 goto ERROR;
1513 } else {
e082fb85 1514 r = sqlite3_bind_null(stmt, 20);
571539a7
MT
1515 if (r)
1516 goto ERROR;
1517 }
1518
1519 // Source arch
988ce1bc 1520 const char* source_arch = pakfire_package_get_string(pkg, PAKFIRE_PKG_SOURCE_ARCH);
571539a7 1521 if (source_arch) {
e082fb85 1522 r = sqlite3_bind_text(stmt, 21, source_arch, -1, NULL);
571539a7
MT
1523 if (r)
1524 goto ERROR;
1525 } else {
e082fb85 1526 r = sqlite3_bind_null(stmt, 21);
571539a7
MT
1527 if (r)
1528 goto ERROR;
1529 }
1530
ca002cae 1531 // Distribution
74468e4f 1532 const char* distribution = pakfire_package_get_string(pkg, PAKFIRE_PKG_DISTRO);
ca002cae 1533 if (distribution) {
e082fb85 1534 r = sqlite3_bind_text(stmt, 22, distribution, -1, NULL);
ca002cae
MT
1535 if (r)
1536 goto ERROR;
1537 } else {
e082fb85 1538 r = sqlite3_bind_null(stmt, 22);
ca002cae
MT
1539 if (r)
1540 goto ERROR;
1541 }
1542
e49b93d1
MT
1543 // Run query
1544 do {
1545 r = sqlite3_step(stmt);
1546 } while (r == SQLITE_BUSY);
1547
1548 if (r != SQLITE_DONE) {
1549 ERROR(db->pakfire, "Could not add package to database: %s\n",
1550 sqlite3_errmsg(db->handle));
687961c3
MT
1551 r = 1;
1552 goto ERROR;
e49b93d1
MT
1553 }
1554
f5c77233
MT
1555 // Save package ID
1556 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1557
1fb2b526
MT
1558 // Add dependencies
1559 r = pakfire_db_add_dependencies(db, packages_id, pkg);
1560 if (r)
687961c3 1561 goto ERROR;
1fb2b526 1562
f5c77233
MT
1563 // Add files
1564 r = pakfire_db_add_files(db, packages_id, archive);
1565 if (r)
687961c3 1566 goto ERROR;
e49b93d1 1567
265f539a
MT
1568 // Add scriptlets
1569 r = pakfire_db_add_scriptlets(db, packages_id, archive);
1570 if (r)
687961c3 1571 goto ERROR;
e49b93d1 1572
687961c3 1573ERROR:
f5c77233
MT
1574 if (stmt)
1575 sqlite3_finalize(stmt);
e49b93d1 1576
687961c3
MT
1577 // Commit or rollback
1578 if (r)
1579 pakfire_db_rollback(db);
1580 else
1581 r = pakfire_db_commit(db);
e49b93d1 1582
687961c3 1583 return r;
eafbe2ce
MT
1584}
1585
31480bee 1586int pakfire_db_remove_package(struct pakfire_db* db, struct pakfire_package* pkg) {
432a328a
MT
1587 sqlite3_stmt* stmt = NULL;
1588 int r = 1;
1589
687961c3
MT
1590 // Begin a new transaction
1591 r = pakfire_db_begin_transaction(db);
1592 if (r)
1593 goto ERROR;
1594
432a328a 1595 // Fetch the package's UUID
74468e4f 1596 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
432a328a
MT
1597 if (!uuid) {
1598 ERROR(db->pakfire, "Package has no UUID\n");
687961c3 1599 r = 1;
432a328a
MT
1600 goto ERROR;
1601 }
1602
1603 r = sqlite3_prepare_v2(db->handle,
1604 "DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
1605 if (r) {
1606 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
1607 sqlite3_errmsg(db->handle));
1608 goto ERROR;
1609 }
1610
1611 // Bind UUID
1612 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1613 if (r) {
1614 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
687961c3 1615 goto ERROR;
432a328a
MT
1616 }
1617
1618 // Execute query
1619 do {
1620 r = sqlite3_step(stmt);
1621 } while (r == SQLITE_BUSY);
1622
1623 // Check if we have been successful
1624 if (r != SQLITE_DONE) {
1625 ERROR(db->pakfire, "Could not delete package %s\n", uuid);
1626 r = 1;
1627 goto ERROR;
1628 }
1629
687961c3 1630 // All done
432a328a
MT
1631 r = 0;
1632
1633ERROR:
1634 if (stmt)
1635 sqlite3_finalize(stmt);
1636
687961c3
MT
1637 // Commit or rollback
1638 if (r)
1639 pakfire_db_rollback(db);
1640 else
1641 r = pakfire_db_commit(db);
1642
432a328a 1643 return r;
eafbe2ce 1644}
f6942b34
MT
1645
1646struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
31480bee 1647 struct pakfire_package* pkg, const char* type) {
f6942b34
MT
1648 struct pakfire_scriptlet* scriptlet = NULL;
1649 sqlite3_stmt* stmt = NULL;
1650 int r = 1;
1651
1652 // Fetch the package's UUID
74468e4f 1653 const char* uuid = pakfire_package_get_string(pkg, PAKFIRE_PKG_UUID);
f6942b34
MT
1654 if (!uuid) {
1655 ERROR(db->pakfire, "Package has no UUID\n");
1656 goto ERROR;
1657 }
1658
7bb92ae3 1659 const char* sql = "SELECT scriptlets.scriptlet FROM packages \
f6942b34
MT
1660 JOIN scriptlets ON packages.id = scriptlets.pkg \
1661 WHERE packages.uuid = ? AND scriptlets.type = ?";
1662
1663 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1664 if (r) {
1665 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1666 sql, sqlite3_errmsg(db->handle));
1667 goto ERROR;
1668 }
1669
1670 // Bind UUID
1671 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1672 if (r) {
1673 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1674 goto ERROR;
1675 }
1676
a0097ba2 1677 r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
f6942b34
MT
1678 if (r) {
1679 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
1680 goto ERROR;
1681 }
1682
a0097ba2 1683 DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
f6942b34
MT
1684
1685 // Execute query
1686 do {
1687 r = sqlite3_step(stmt);
1688 } while (r == SQLITE_BUSY);
1689
1690 // We have some payload
1691 if (r == SQLITE_ROW) {
1692 const void* data = sqlite3_column_blob(stmt, 1);
1693 ssize_t size = sqlite3_column_bytes(stmt, 1);
1694
1695 // Create a scriptlet object
a0097ba2
MT
1696 r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
1697 if (r)
f6942b34
MT
1698 goto ERROR;
1699 }
1700
1701ERROR:
1702 if (stmt)
1703 sqlite3_finalize(stmt);
1704
1705 return scriptlet;
1706}
361ca45f 1707
4651122b 1708static int pakfire_db_load_package(struct pakfire_db* db, struct pakfire_repo* repo, sqlite3_stmt* stmt) {
31480bee 1709 struct pakfire_package* pkg = NULL;
361ca45f
MT
1710 int r = 1;
1711
1712 // Name
1713 const char* name = (const char*)sqlite3_column_text(stmt, 0);
1714 if (!name) {
1715 ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
1716 goto ERROR;
1717 }
1718
6ed66687
MT
1719 // EVR
1720 const char* evr = (const char*)sqlite3_column_text(stmt, 1);
1721 if (!evr) {
1722 ERROR(db->pakfire, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
361ca45f
MT
1723 goto ERROR;
1724 }
1725
1726 // Arch
6ed66687 1727 const char* arch = (const char*)sqlite3_column_text(stmt, 2);
361ca45f
MT
1728 if (!arch) {
1729 ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
1730 goto ERROR;
1731 }
1732
361ca45f 1733 // Create package
33ad2a01
MT
1734 r = pakfire_package_create(&pkg, db->pakfire, repo, name, evr, arch);
1735 if (r) {
5dee04f3 1736 ERROR(db->pakfire, "Could not create package '%s-%s.%s': %m\n", name, evr, arch);
361ca45f
MT
1737 goto ERROR;
1738 }
1739
ac71886a
MT
1740 // ID
1741 uint64_t id = sqlite3_column_int64(stmt, 3);
3f327c3c
MT
1742 if (id) {
1743 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_DBID, id);
1744 if (r)
1745 goto ERROR;
1746 }
ac71886a 1747
7f826034 1748 // Groups
ac71886a 1749 const char* groups = (const char*)sqlite3_column_text(stmt, 4);
7f826034 1750 if (groups) {
74468e4f
MT
1751 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_GROUPS, groups);
1752 if (r)
1753 goto ERROR;
7f826034
MT
1754 }
1755
1756 // Filename
ac71886a 1757 const char* filename = (const char*)sqlite3_column_text(stmt, 5);
7f826034 1758 if (filename) {
0aade652
MT
1759 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_FILENAME, filename);
1760 if (r)
1761 goto ERROR;
7f826034
MT
1762 }
1763
1764 // Size
ac71886a 1765 size_t size = sqlite3_column_int64(stmt, 6);
7f826034 1766 if (size) {
3f327c3c
MT
1767 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_DOWNLOADSIZE, size);
1768 if (r)
1769 goto ERROR;
7f826034
MT
1770 }
1771
1772 // Installed size
ac71886a 1773 size = sqlite3_column_int64(stmt, 7);
7f826034 1774 if (size) {
3f327c3c
MT
1775 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLSIZE, size);
1776 if (r)
1777 goto ERROR;
7f826034
MT
1778 }
1779
e082fb85
MT
1780 // Digest type
1781 enum pakfire_digest_types digest_type = sqlite3_column_int64(stmt, 8);
1782 size_t digest_length = 0;
b28af23a 1783
e082fb85
MT
1784 // Digest length
1785
1786 // Digest
1787 const unsigned char* digest = sqlite3_column_blob(stmt, 9);
1788 if (digest_type && digest) {
1789 pakfire_package_set_digest(pkg, digest_type, digest, digest_length);
7f826034
MT
1790 }
1791
1792 // License
e082fb85 1793 const char* license = (const char*)sqlite3_column_text(stmt, 10);
7f826034 1794 if (license) {
74468e4f
MT
1795 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_LICENSE, license);
1796 if (r)
1797 goto ERROR;
7f826034
MT
1798 }
1799
1800 // Summary
e082fb85 1801 const char* summary = (const char*)sqlite3_column_text(stmt, 11);
7f826034 1802 if (summary) {
74468e4f
MT
1803 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SUMMARY, summary);
1804 if (r)
1805 goto ERROR;
7f826034
MT
1806 }
1807
1808 // Description
e082fb85 1809 const char* description = (const char*)sqlite3_column_text(stmt, 12);
7f826034 1810 if (description) {
74468e4f
MT
1811 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
1812 if (r)
1813 goto ERROR;
7f826034
MT
1814 }
1815
1816 // UUID
e082fb85 1817 const char* uuid = (const char*)sqlite3_column_text(stmt, 13);
7f826034 1818 if (uuid) {
74468e4f
MT
1819 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_UUID, uuid);
1820 if (r)
1821 goto ERROR;
7f826034
MT
1822 }
1823
1824 // Vendor
e082fb85 1825 const char* vendor = (const char*)sqlite3_column_text(stmt, 14);
7f826034 1826 if (vendor) {
74468e4f
MT
1827 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_VENDOR, vendor);
1828 if (r)
1829 goto ERROR;
7f826034
MT
1830 }
1831
1832 // Build Host
e082fb85 1833 const char* build_host = (const char*)sqlite3_column_text(stmt, 15);
7f826034 1834 if (build_host) {
1f669e88
MT
1835 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_BUILD_HOST, build_host);
1836 if (r)
1837 goto ERROR;
7f826034
MT
1838 }
1839
1840 // Build Time
e082fb85 1841 time_t build_time = sqlite3_column_int64(stmt, 16);
7f826034 1842 if (build_time) {
3f327c3c
MT
1843 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_BUILD_TIME, build_time);
1844 if (r)
1845 goto ERROR;
7f826034
MT
1846 }
1847
af647c55 1848 // Install Time
e082fb85 1849 time_t install_time = sqlite3_column_int64(stmt, 17);
af647c55 1850 if (install_time) {
3f327c3c
MT
1851 r = pakfire_package_set_num(pkg, PAKFIRE_PKG_INSTALLTIME, install_time);
1852 if (r)
1853 goto ERROR;
af647c55
MT
1854 }
1855
c9c03e6a 1856 // installed by user?
e082fb85 1857 int userinstalled = sqlite3_column_int(stmt, 18);
c9c03e6a
MT
1858 if (userinstalled)
1859 pakfire_db_add_userinstalled(db->pakfire, name);
1860
d995f7fc 1861 // Files
e082fb85 1862 const char* files = (const char*)sqlite3_column_text(stmt, 19);
d995f7fc 1863 if (files) {
d995f7fc
MT
1864 r = pakfire_package_set_filelist_from_string(pkg, files);
1865 if (r)
1866 goto ERROR;
1867 }
1868
24be412a
MT
1869 // Dependencies
1870
1871 const struct dependency {
1872 unsigned int field;
6f3fad3b 1873 const enum pakfire_package_key key;
24be412a 1874 } dependencies[] = {
6f3fad3b
MT
1875 { 20, PAKFIRE_PKG_PROVIDES },
1876 { 21, PAKFIRE_PKG_PREREQUIRES },
1877 { 22, PAKFIRE_PKG_REQUIRES },
1878 { 23, PAKFIRE_PKG_CONFLICTS },
1879 { 24, PAKFIRE_PKG_OBSOLETES },
1880 { 25, PAKFIRE_PKG_RECOMMENDS },
1881 { 26, PAKFIRE_PKG_SUGGESTS },
1882 { 27, PAKFIRE_PKG_SUPPLEMENTS },
1883 { 28, PAKFIRE_PKG_ENHANCES },
1884 { 0 },
24be412a
MT
1885 };
1886
1887 for (const struct dependency* deps = dependencies; deps->field; deps++) {
1888 const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
1889 if (relations) {
6f3fad3b
MT
1890 r = pakfire_str2deps(db->pakfire, pkg, deps->key, relations);
1891 if (r)
1892 goto ERROR;
24be412a
MT
1893 }
1894 }
1895
571539a7 1896 // Source package
e082fb85 1897 const char* source_name = (const char*)sqlite3_column_text(stmt, 29);
988ce1bc
MT
1898 if (source_name) {
1899 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_NAME, source_name);
1900 if (r)
1901 goto ERROR;
1902 }
571539a7
MT
1903
1904 // Source EVR
e082fb85 1905 const char* source_evr = (const char*)sqlite3_column_text(stmt, 30);
988ce1bc
MT
1906 if (source_evr) {
1907 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_EVR, source_evr);
1908 if (r)
1909 goto ERROR;
1910 }
571539a7
MT
1911
1912 // Source arch
e082fb85 1913 const char* source_arch = (const char*)sqlite3_column_text(stmt, 31);
988ce1bc
MT
1914 if (source_arch) {
1915 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_SOURCE_ARCH, source_arch);
1916 if (r)
1917 goto ERROR;
1918 }
571539a7 1919
ca002cae 1920 // Distribution
e082fb85 1921 const char* distribution = (const char*)sqlite3_column_text(stmt, 32);
74468e4f
MT
1922 if (distribution) {
1923 r = pakfire_package_set_string(pkg, PAKFIRE_PKG_DESCRIPTION, description);
1924 if (r)
1925 goto ERROR;
1926 }
ca002cae 1927
361ca45f
MT
1928 // Success
1929 r = 0;
1930
1931ERROR:
361ca45f
MT
1932 if (pkg)
1933 pakfire_package_unref(pkg);
1934
1935 return r;
1936}
1937
4651122b 1938int pakfire_db_load(struct pakfire_db* db, struct pakfire_repo* repo) {
361ca45f
MT
1939 sqlite3_stmt* stmt = NULL;
1940 int r = 1;
1941
1942 DEBUG(db->pakfire, "Loading package database...\n");
1943
7fe22178
MT
1944 // Drop contents of the repository
1945 pakfire_repo_clear(repo);
1946
788221bd
MT
1947 // Save starting time
1948 clock_t t_start = clock();
1949 clock_t t_end;
1950
361ca45f
MT
1951 const char* sql =
1952 "SELECT "
571539a7
MT
1953 "name, "
1954 "evr, "
1955 "arch, "
1956 "id, "
1957 "groups, "
1958 "filename, "
1959 "size, "
1960 "inst_size, "
e082fb85 1961 "digest_type, "
571539a7
MT
1962 "digest, "
1963 "license, "
1964 "summary, "
1965 "description, "
1966 "uuid, "
1967 "vendor, "
1968 "build_host, "
1969 "build_time, "
1970 "strftime('%s', installed) AS installed, "
1971 "userinstalled, "
d995f7fc 1972 "("
32485f6c 1973 "SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id"
24be412a
MT
1974 ") AS files, "
1975 "("
1976 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1977 "WHERE d.pkg = packages.id AND d.type = 'provides'"
1978 ") AS provides, "
1979 "("
1980 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1981 "WHERE d.pkg = packages.id AND d.type = 'prerequires'"
1982 ") AS prerequires, "
1983 "("
1984 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1985 "WHERE d.pkg = packages.id AND d.type = 'requires'"
1986 ") AS requires, "
1987 "("
1988 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1989 "WHERE d.pkg = packages.id AND d.type = 'conflicts'"
1990 ") AS conflicts, "
1991 "("
1992 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1993 "WHERE d.pkg = packages.id AND d.type = 'obsoletes'"
1994 ") AS obsoletes, "
1995 "("
1996 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1997 "WHERE d.pkg = packages.id AND d.type = 'recommends'"
1998 ") AS recommends, "
1999 "("
2000 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2001 "WHERE d.pkg = packages.id AND d.type = 'suggests'"
8fe2e4ba
MT
2002 ") AS suggests, "
2003 "("
2004 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2005 "WHERE d.pkg = packages.id AND d.type = 'supplements'"
2006 ") AS supplements, "
2007 "("
2008 "SELECT group_concat(dependency, '\n') FROM dependencies d "
2009 "WHERE d.pkg = packages.id AND d.type = 'enhances'"
571539a7
MT
2010 ") AS enhances, "
2011 "source_name, "
2012 "source_evr, "
ca002cae
MT
2013 "source_arch, "
2014 "distribution "
361ca45f
MT
2015 "FROM "
2016 "packages"
2017 ";";
2018
2019 // Prepare the statement
2020 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2021 if (r) {
2022 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2023 sql, sqlite3_errmsg(db->handle));
2024 goto ERROR;
2025 }
2026
2027 for (;;) {
2028 // Execute query
2029 r = sqlite3_step(stmt);
2030
2031 switch (r) {
2032 // Retry if the database was busy
2033 case SQLITE_BUSY:
2034 continue;
2035
2036 // Read a row
2037 case SQLITE_ROW:
2038 r = pakfire_db_load_package(db, repo, stmt);
2039 if (r)
2040 goto ERROR;
2041 break;
2042
2043 // All rows have been processed
2044 case SQLITE_DONE:
2045 goto END;
2046
2047 // Go to error in any other cases
2048 default:
2049 goto ERROR;
2050 }
2051 }
2052
2053END:
788221bd
MT
2054 // Save time when we finished
2055 t_end = clock();
2056
2057 DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
2058 (double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
361ca45f 2059
9eba3d65
MT
2060 // Mark repository as changed
2061 pakfire_repo_has_changed(repo);
05336f5e 2062
361ca45f
MT
2063 // All done
2064 r = 0;
2065
2066ERROR:
b027597a 2067 if (r) {
5dee04f3 2068 ERROR(db->pakfire, "Failed reading package database: %m\n");
b027597a
MT
2069 pakfire_repo_clear(repo);
2070 }
361ca45f
MT
2071
2072 if (stmt)
2073 sqlite3_finalize(stmt);
2074
2075 return r;
2076}
ac71886a 2077
923d6794 2078static int pakfire_db_load_file_digest(struct pakfire_db* db, struct pakfire_file* file,
c52e0148 2079 sqlite3_stmt* stmt, const enum pakfire_digest_types type, const int field) {
923d6794
MT
2080 // Fetch digest
2081 const unsigned char* digest = sqlite3_column_blob(stmt, field);
2082
2083 // Nothing further to do if field is NULL
2084 if (!digest)
2085 return 0;
2086
2087 // Length of the stored value
2088 const size_t length = sqlite3_column_bytes(stmt, field);
2089
923d6794 2090 // Store digest
399d14c2 2091 return pakfire_file_set_digest(file, type, digest, length);
923d6794
MT
2092}
2093
1bbbfb9e 2094static int pakfire_db_load_file(struct pakfire_db* db, struct pakfire_filelist* filelist,
ac71886a
MT
2095 sqlite3_stmt* stmt) {
2096 struct pakfire_file* file = NULL;
1fab76a4 2097 char abspath[PATH_MAX];
ac71886a
MT
2098 int r;
2099
2100 // Create a new file object
2101 r = pakfire_file_create(&file, db->pakfire);
2102 if (r)
2103 goto ERROR;
2104
2105 // Path
2106 const char* path = (const char*)sqlite3_column_text(stmt, 0);
f04369e6
MT
2107
2108 // Abort if no path is set
2109 if (!path) {
2110 ERROR(db->pakfire, "File has no path\n");
2111 r = 1;
2112 goto ERROR;
2113 }
2114
2115 // Set path
2116 r = pakfire_file_set_path(file, path);
2117 if (r) {
2118 ERROR(db->pakfire, "%s: Could not set path '%s': %m\n", path, path);
2119 goto ERROR;
2120 }
ac71886a 2121
1fab76a4
MT
2122 // Make the absolute path
2123 r = pakfire_path(db->pakfire, abspath, "%s", path);
2124 if (r) {
2125 ERROR(db->pakfire, "%s: Could not make absolute path: %m\n", path);
2126 goto ERROR;
2127 }
2128
2129 // Set the absolute path
2130 r = pakfire_file_set_abspath(file, abspath);
2131 if (r) {
2132 ERROR(db->pakfire, "%s: Could not set absolute path %s: %m\n", path, abspath);
2133 goto ERROR;
2134 }
2135
ac71886a
MT
2136 // Size
2137 size_t size = sqlite3_column_int64(stmt, 1);
2138 if (size)
2139 pakfire_file_set_size(file, size);
2140
2141 // Mode
2142 mode_t mode = sqlite3_column_int(stmt, 2);
2143 if (mode)
2144 pakfire_file_set_mode(file, mode);
2145
302e3253
MT
2146 // uname
2147 const char* uname = (const char*)sqlite3_column_text(stmt, 3);
f04369e6
MT
2148
2149 // Abort if no user is set
302e3253 2150 if (!uname) {
f04369e6
MT
2151 ERROR(db->pakfire, "%s: No user\n", path);
2152 r = 1;
2153 goto ERROR;
2154 }
2155
302e3253
MT
2156 // Set uname
2157 r = pakfire_file_set_uname(file, uname);
f04369e6 2158 if (r) {
302e3253 2159 ERROR(db->pakfire, "%s: Could not set user '%s': %m\n", path, uname);
f04369e6
MT
2160 goto ERROR;
2161 }
ac71886a 2162
302e3253
MT
2163 // gname
2164 const char* gname = (const char*)sqlite3_column_text(stmt, 4);
f04369e6
MT
2165
2166 // Abort if no group is set
302e3253 2167 if (!gname) {
f04369e6
MT
2168 ERROR(db->pakfire, "%s: No group\n", path);
2169 r = 1;
2170 goto ERROR;
2171 }
2172
302e3253
MT
2173 // Set gname
2174 r = pakfire_file_set_gname(file, gname);
f04369e6 2175 if (r) {
302e3253 2176 ERROR(db->pakfire, "%s: Could not set group '%s': %m\n", path, gname);
f04369e6
MT
2177 goto ERROR;
2178 }
ac71886a
MT
2179
2180 // ctime
2181 time_t ctime = sqlite3_column_int64(stmt, 5);
2182 if (ctime)
2183 pakfire_file_set_ctime(file, ctime);
2184
2185 // mtime
2186 time_t mtime = sqlite3_column_int64(stmt, 6);
2187 if (mtime)
2188 pakfire_file_set_mtime(file, mtime);
2189
a3845369 2190 // SHA2-512 Digest
4500ed0a 2191 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_512, 7);
923d6794
MT
2192 if (r)
2193 goto ERROR;
2194
a3845369 2195 // SHA2-256 Digest
4500ed0a 2196 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_256, 8);
923d6794
MT
2197 if (r)
2198 goto ERROR;
2199
a3845369
MT
2200 // BLAKE2b512 Digest
2201 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2B512, 9);
2202 if (r)
2203 goto ERROR;
2204
2205 // BLAKE2s256 Digest
2206 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2S256, 10);
2207 if (r)
2208 goto ERROR;
2209
2210 // SHA3-512 Digest
2211 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_512, 11);
2212 if (r)
2213 goto ERROR;
2214
2215 // SHA3-256 Digest
2216 r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_256, 12);
2217 if (r)
2218 goto ERROR;
2219
ac71886a 2220 // Append the file to the filelist
2f88682d 2221 r = pakfire_filelist_add(filelist, file);
f04369e6
MT
2222 if (r)
2223 goto ERROR;
ac71886a
MT
2224
2225ERROR:
2226 if (file)
2227 pakfire_file_unref(file);
2228
2229 return r;
2230}
2231
3f310c26
MT
2232int pakfire_db_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist) {
2233 struct pakfire_filelist* list = NULL;
2234 sqlite3_stmt* stmt = NULL;
2235 int r;
2236
2237 const char* sql =
2238 "SELECT "
2239 "path, "
2240 "size, "
2241 "mode, "
ca8fe553
MT
2242 "uname, "
2243 "gname, "
3f310c26 2244 "ctime, "
923d6794 2245 "mtime, "
a3845369
MT
2246 "digest_sha2_512, "
2247 "digest_sha2_256, "
2248 "digest_blake2b512, "
2249 "digest_blake2s256, "
2250 "digest_sha3_512, "
2251 "digest_sha3_256 "
3f310c26
MT
2252 "FROM files "
2253 "ORDER BY path"
2254 ";";
2255
2256 // Prepare the statement
2257 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2258 if (r) {
2259 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2260 sql, sqlite3_errmsg(db->handle));
2261 goto ERROR;
2262 }
2263
2264 // Create a new filelist
2265 r = pakfire_filelist_create(&list, db->pakfire);
2266 if (r)
2267 goto ERROR;
2268
2269 // Iterate over all rows
2270 for (;;) {
2271 // Execute query
2272 r = sqlite3_step(stmt);
2273
2274 switch (r) {
2275 // Retry if the database was busy
2276 case SQLITE_BUSY:
2277 continue;
2278
2279 // Read a row
2280 case SQLITE_ROW:
2281 r = pakfire_db_load_file(db, list, stmt);
2282 if (r)
2283 goto ERROR;
2284 break;
2285
2286 // All rows have been processed
2287 case SQLITE_DONE:
2288 r = 0;
2289 goto END;
2290
2291 // Go to error in any other cases
2292 default:
2293 goto ERROR;
2294 }
2295 }
2296
2297END:
2298 // Return the filelist
2299 *filelist = pakfire_filelist_ref(list);
2300
2301ERROR:
2302 if (r)
2303 ERROR(db->pakfire, "Could not fetch filelist: %m\n");
2304
2305 if (stmt)
2306 sqlite3_finalize(stmt);
2307 if (list)
2308 pakfire_filelist_unref(list);
2309
2310 return r;
2311}
2312
1bbbfb9e 2313int pakfire_db_package_filelist(struct pakfire_db* db, struct pakfire_filelist** filelist,
31480bee 2314 struct pakfire_package* pkg) {
1bbbfb9e 2315 struct pakfire_filelist* fl = NULL;
ac71886a
MT
2316 sqlite3_stmt* stmt = NULL;
2317 int r = 1;
2318
2319 // Fetch the package ID
3f327c3c 2320 uint64_t id = pakfire_package_get_num(pkg, PAKFIRE_PKG_DBID, 0);
ac71886a
MT
2321 if (!id) {
2322 ERROR(db->pakfire, "Package did not have an ID\n");
2323 return 1;
2324 }
2325
2326 // Create a new filelist
2327 r = pakfire_filelist_create(&fl, db->pakfire);
2328 if (r) {
2329 ERROR(db->pakfire, "Could not create filelist: %m\n");
2330 goto ERROR;
2331 }
2332
2333 const char* sql =
2334 "SELECT "
2335 "path, "
2336 "size, "
2337 "mode, "
ca8fe553
MT
2338 "uname, "
2339 "gname, "
ac71886a 2340 "ctime, "
923d6794 2341 "mtime, "
ca8fe553
MT
2342 "digest_sha2_512, "
2343 "digest_sha2_256, "
2344 "digest_blake2b512, "
2345 "digest_blake2s256, "
2346 "digest_sha3_512, "
2347 "digest_sha3_256 "
ac71886a
MT
2348 "FROM files "
2349
2350 // Select all files that belong to this package
2351 "WHERE "
2352 "pkg = ? "
2353
2354 // Filter out any files that are also in a different package (i.e. an update
2355 // that has already been installed and this is the cleanup of the obsolete pkg)
2356 "AND "
2357 "NOT EXISTS ("
2358 "SELECT "
2359 "1 "
2360 "FROM files AS duplicates "
2361 "WHERE "
2362 "files.path = duplicates.path "
2363 "AND "
2364 "files.pkg != duplicates.pkg"
2365 ") "
2366
2367 // Return the longest paths first
2368 "ORDER BY "
2369 "length(path) DESC"
2370 ";";
2371
2372 // Prepare the statement
2373 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
2374 if (r) {
2375 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
2376 sql, sqlite3_errmsg(db->handle));
2377 goto ERROR;
2378 }
2379
2380 // Bind package ID
2381 r = sqlite3_bind_int64(stmt, 1, id);
2382 if (r) {
2383 ERROR(db->pakfire, "Could not bind package ID: %s\n", sqlite3_errmsg(db->handle));
2384 goto ERROR;
2385 }
2386
2387 for (;;) {
2388 // Execute query
2389 r = sqlite3_step(stmt);
2390
2391 switch (r) {
2392 // Retry if the database was busy
2393 case SQLITE_BUSY:
2394 continue;
2395
2396 // Read a row
2397 case SQLITE_ROW:
2398 r = pakfire_db_load_file(db, fl, stmt);
2399 if (r)
2400 goto ERROR;
2401 break;
2402
2403 // All rows have been processed
2404 case SQLITE_DONE:
2405 goto END;
2406
2407 // Go to error in any other cases
2408 default:
2409 goto ERROR;
2410 }
2411 }
2412
2413END:
2414 *filelist = pakfire_filelist_ref(fl);
2415 r = 0;
2416
2417ERROR:
2418 if (stmt)
2419 sqlite3_finalize(stmt);
2420 if (fl)
2421 pakfire_filelist_unref(fl);
2422
2423 return r;
2424}