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