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