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