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