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