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