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