]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
packagelist: Drop unused conditional push function
[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/types.h>
38#include <pakfire/util.h>
39
0cb487ff
MT
40#define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db"
41
5ba550fe 42#define CURRENT_SCHEMA 8
c745fb2d
MT
43#define SCHEMA_MIN_SUP 7
44
33d55ab4
MT
45struct pakfire_db {
46 Pakfire pakfire;
47 int nrefs;
77a4b3a3 48
097b6ca6 49 char path[PATH_MAX];
77a4b3a3 50 int mode;
26affd69
MT
51
52 sqlite3* handle;
c745fb2d 53 int schema;
33d55ab4
MT
54};
55
9c5938ea
MT
56static void logging_callback(void* data, int r, const char* msg) {
57 Pakfire pakfire = (Pakfire)data;
58
59 ERROR(pakfire, "Database Error: %s: %s\n",
60 sqlite3_errstr(r), msg);
61}
62
0076c50d
MT
63static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
64 int r;
c745fb2d
MT
65
66 DEBUG(db->pakfire, "Executing database query: %s\n", stmt);
0076c50d
MT
67
68 do {
c745fb2d 69 r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
0076c50d
MT
70 } while (r == SQLITE_BUSY);
71
c745fb2d
MT
72 // Log any errors
73 if (r) {
74 ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
75 }
76
25753290
MT
77 return r;
78}
79
c745fb2d
MT
80static int pakfire_db_begin_transaction(struct pakfire_db* db) {
81 return pakfire_db_execute(db, "BEGIN TRANSACTION");
82}
83
84static int pakfire_db_commit(struct pakfire_db* db) {
85 return pakfire_db_execute(db, "COMMIT");
86}
87
88static int pakfire_db_rollback(struct pakfire_db* db) {
89 return pakfire_db_execute(db, "ROLLBACK");
90}
91
25753290
MT
92/*
93 This function performs any fast optimization and tries to truncate the WAL log file
94 to keep the database as compact as possible on disk.
95*/
96static void pakfire_db_optimize(struct pakfire_db* db) {
44d392ef 97 pakfire_db_execute(db, "PRAGMA optimize");
25753290 98 pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
0076c50d
MT
99}
100
26affd69 101static void pakfire_db_free(struct pakfire_db* db) {
26affd69 102 if (db->handle) {
25753290
MT
103 // Optimize the database before it is being closed
104 pakfire_db_optimize(db);
105
106 // Close database handle
26affd69
MT
107 int r = sqlite3_close(db->handle);
108 if (r != SQLITE_OK) {
109 ERROR(db->pakfire, "Could not close database handle: %s\n",
110 sqlite3_errmsg(db->handle));
111 }
112 }
113
114 pakfire_unref(db->pakfire);
115
f0d6233d 116 free(db);
26affd69
MT
117}
118
c745fb2d
MT
119static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
120 sqlite3_stmt* stmt = NULL;
121 sqlite3_value* val = NULL;
122 int r;
123
124 const char* sql = "SELECT val FROM settings WHERE key = ?";
125
126 // Prepare the statement
127 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
128 if (r != SQLITE_OK) {
129 //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
130 // sql, sqlite3_errmsg(db->handle));
131 return NULL;
132 }
133
134 // Bind key
135 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
136 if (r != SQLITE_OK) {
137 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
138 goto ERROR;
139 }
140
141 // Execute the statement
142 do {
143 r = sqlite3_step(stmt);
144 } while (r == SQLITE_BUSY);
145
f168dd0c
MT
146 // We should have read a row
147 if (r != SQLITE_ROW)
148 goto ERROR;
149
c745fb2d 150 // Read value
f168dd0c 151 val = sqlite3_column_value(stmt, 0);
c745fb2d
MT
152 if (!val) {
153 ERROR(db->pakfire, "Could not read value\n");
154 goto ERROR;
155 }
156
157 // Copy value onto the heap
158 val = sqlite3_value_dup(val);
159
160ERROR:
161 if (stmt)
162 sqlite3_finalize(stmt);
163
164 return val;
165}
166
167static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
168 sqlite3_stmt* stmt = NULL;
169 int r;
170
171 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
172 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
173
174 // Prepare statement
175 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
176 if (r != SQLITE_OK) {
177 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
178 sql, sqlite3_errmsg(db->handle));
179 return 1;
180 }
181
182 // Bind key
183 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
184 if (r != SQLITE_OK) {
185 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
186 goto ERROR;
187 }
188
189 // Bind val
190 r = sqlite3_bind_int64(stmt, 2, val);
191 if (r != SQLITE_OK) {
192 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
193 goto ERROR;
194 }
195
196 // Execute the statement
197 do {
198 r = sqlite3_step(stmt);
199 } while (r == SQLITE_BUSY);
200
201 // Set return code
202 r = (r == SQLITE_OK);
203
204ERROR:
205 if (stmt)
206 sqlite3_finalize(stmt);
207
208 return r;
209}
210
211static int pakfire_db_get_schema(struct pakfire_db* db) {
212 sqlite3_value* value = pakfire_db_get(db, "schema");
213 if (!value)
f168dd0c 214 return -1;
c745fb2d
MT
215
216 int schema = sqlite3_value_int64(value);
217 sqlite3_value_free(value);
218
219 DEBUG(db->pakfire, "Database has schema version %d\n", schema);
220
221 return schema;
222}
223
224static int pakfire_db_create_schema(struct pakfire_db* db) {
225 int r;
226
227 // Create settings table
228 r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)");
229 if (r)
230 return 1;
231
232 // settings: Add a unique index on key
233 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)");
234 if (r)
235 return 1;
236
704b3993
MT
237 // Create packages table
238 r = pakfire_db_execute(db,
239 "CREATE TABLE IF NOT EXISTS packages("
240 "id INTEGER PRIMARY KEY, "
241 "name TEXT, "
6ed66687 242 "evr TEXT, "
704b3993
MT
243 "arch TEXT, "
244 "groups TEXT, "
245 "filename TEXT, "
246 "size INTEGER, "
247 "inst_size INTEGER, "
248 "hash1 TEXT, "
249 "license TEXT, "
250 "summary TEXT, "
251 "description TEXT, "
252 "uuid TEXT, "
253 "vendor TEXT, "
704b3993 254 "build_host TEXT, "
704b3993
MT
255 "build_time INTEGER, "
256 "installed INTEGER, "
dc0cae14 257 "userinstalled INTEGER, "
704b3993
MT
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
00fd98ff
MT
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
2359ca14
MT
273 // Create dependencies table
274 r = pakfire_db_execute(db,
275 "CREATE TABLE IF NOT EXISTS dependencies("
276 "pkg INTEGER, "
277 "type TEXT, "
46257c5f 278 "dependency TEXT, "
432a328a 279 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
2359ca14
MT
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
68036506
MT
289 // Create files table
290 r = pakfire_db_execute(db,
291 "CREATE TABLE IF NOT EXISTS files("
292 "id INTEGER PRIMARY KEY, "
32485f6c 293 "path TEXT, "
68036506
MT
294 "pkg INTEGER, "
295 "size INTEGER, "
68036506
MT
296 "config INTEGER, "
297 "datafile INTEGER, "
298 "mode INTEGER, "
299 "user TEXT, "
300 "'group' TEXT, "
301 "hash1 TEXT, "
ef4e8460 302 "ctime INTEGER, "
68036506 303 "mtime INTEGER, "
46257c5f 304 "capabilities TEXT, "
432a328a 305 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
68036506
MT
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
ab1aa17a
MT
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
d83414aa
MT
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, "
265f539a 325 "type TEXT, "
46257c5f 326 "scriptlet TEXT, "
432a328a 327 "FOREIGN KEY (pkg) REFERENCES packages(id) ON DELETE CASCADE"
d83414aa
MT
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
c745fb2d
MT
337 return 0;
338}
339
46257c5f 340static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
5ba550fe
MT
341 // packages: Drop build_id column
342
46257c5f
MT
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
c745fb2d
MT
350static 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
f168dd0c 361 case -1:
c745fb2d
MT
362 r = pakfire_db_create_schema(db);
363 if (r)
364 goto ROLLBACK;
365
366 db->schema = CURRENT_SCHEMA;
367 break;
368
46257c5f
MT
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
c745fb2d
MT
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
395ROLLBACK:
396 pakfire_db_rollback(db);
397
398 return 1;
399}
400
9c5938ea 401static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
402 int r;
403
9c5938ea
MT
404 // Setup logging
405 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
406
46257c5f
MT
407 // Enable foreign keys
408 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
409
0076c50d
MT
410 // Make LIKE case-sensitive
411 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
412
c745fb2d
MT
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
9c5938ea
MT
423 // Done when not in read-write mode
424 if (db->mode != PAKFIRE_DB_READWRITE)
425 return 0;
426
0076c50d
MT
427 // Disable secure delete
428 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
429
25753290
MT
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
c745fb2d
MT
446 // Create or migrate schema
447 r = pakfire_db_migrate_schema(db);
448 if (r)
449 return r;
9c5938ea
MT
450
451 return 0;
452}
453
9c78c483 454int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
26affd69
MT
455 int r = 1;
456
90312f5c 457 struct pakfire_db* o = calloc(1, sizeof(*o));
33d55ab4
MT
458 if (!o)
459 return -ENOMEM;
460
33d55ab4
MT
461 o->pakfire = pakfire_ref(pakfire);
462 o->nrefs = 1;
463
26affd69
MT
464 int sqlite3_flags = 0;
465
466 // Store mode & forward it to sqlite3
467 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 468 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
469 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
470 } else {
77a4b3a3 471 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
472 sqlite3_flags |= SQLITE_OPEN_READONLY;
473 }
474
475 // Make the filename
097b6ca6
MT
476 r = pakfire_make_path(o->pakfire, o->path, DATABASE_PATH);
477 if (r < 0)
26affd69
MT
478 goto END;
479
480 // Try to open the sqlite3 database file
097b6ca6 481 r = sqlite3_open_v2(o->path, &o->handle, sqlite3_flags, NULL);
26affd69
MT
482 if (r != SQLITE_OK) {
483 ERROR(pakfire, "Could not open database %s: %s\n",
097b6ca6 484 o->path, sqlite3_errmsg(o->handle));
26affd69
MT
485
486 r = 1;
487 goto END;
488 }
77a4b3a3 489
9c5938ea
MT
490 // Setup the database
491 r = pakfire_db_setup(o);
492 if (r)
493 goto END;
494
33d55ab4 495 *db = o;
26affd69
MT
496 r = 0;
497
498END:
499 if (r)
500 pakfire_db_free(o);
33d55ab4 501
26affd69 502 return r;
33d55ab4
MT
503}
504
9c78c483 505struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
33d55ab4
MT
506 db->nrefs++;
507
508 return db;
509}
510
9c78c483 511struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
33d55ab4
MT
512 if (--db->nrefs > 0)
513 return db;
514
515 pakfire_db_free(db);
516
517 return NULL;
518}
eafbe2ce 519
a1571786
MT
520static 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
567static 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*/
9c78c483 617int pakfire_db_check(struct pakfire_db* db) {
a1571786
MT
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
817757f4 633// Returns the number of packages installed
9c78c483 634ssize_t pakfire_db_packages(struct pakfire_db* db) {
817757f4
MT
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
c9c03e6a
MT
659static void pakfire_db_add_userinstalled(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
31480bee 669static int pakfire_db_add_dependencies(struct pakfire_db* db, unsigned long id, struct pakfire_package* pkg) {
1fb2b526
MT
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;
31480bee 685 char** (*func)(struct pakfire_package*);
1fb2b526
MT
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 },
8fe2e4ba
MT
694 { "supplements", pakfire_package_get_supplements },
695 { "enhances", pakfire_package_get_enhances },
1fb2b526
MT
696 { NULL, NULL },
697 };
698
699 for (const struct __relation* relation = relations; relation->type; relation++) {
452d3833 700 char** list = relation->func(pkg);
1fb2b526
MT
701 if (!list)
702 continue;
703
452d3833 704 for (char** dep = list; *dep; dep++) {
1fb2b526
MT
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));
1fb2b526
MT
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));
1fb2b526
MT
718 goto END;
719 }
720
721 // Bind dependency
452d3833 722 r = sqlite3_bind_text(stmt, 3, *dep, -1, NULL);
1fb2b526
MT
723 if (r) {
724 ERROR(db->pakfire, "Could not bind dependency: %s\n",
725 sqlite3_errmsg(db->handle));
1fb2b526
MT
726 goto END;
727 }
728
729 // Execute query
730 do {
731 r = sqlite3_step(stmt);
732 } while (r == SQLITE_BUSY);
733
452d3833 734 free(*dep);
1fb2b526
MT
735
736 // Reset bound values
737 sqlite3_reset(stmt);
738 }
739
452d3833 740 free(list);
1fb2b526
MT
741 }
742
743 // All okay
744 r = 0;
745
746END:
747 if (stmt)
748 sqlite3_finalize(stmt);
749
750 return r;
751}
752
f5c77233
MT
753static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
754 sqlite3_stmt* stmt = NULL;
dccd04a4 755 int r = 1;
f5c77233
MT
756
757 // Get the filelist from the archive
5e9463ec
MT
758 PakfireFilelist filelist = pakfire_archive_get_filelist(archive);
759 if (!filelist) {
f5c77233
MT
760 ERROR(db->pakfire, "Could not fetch filelist from archive\n");
761 return 1;
762 }
763
5e9463ec 764 // Nothing to do if the list is empty
9a6e3e2d
MT
765 if (pakfire_filelist_is_empty(filelist)) {
766 r = 0;
5e9463ec 767 goto END;
9a6e3e2d 768 }
5e9463ec 769
b72bae3f
MT
770 const char* sql = "INSERT INTO files(pkg, path, size, config, datafile, mode, "
771 "user, 'group', hash1, ctime, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
f5c77233
MT
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
5e9463ec 781 for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
5803b5f6 782 struct pakfire_file* file = pakfire_filelist_get(filelist, i);
5e9463ec 783
f5c77233
MT
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));
5e9463ec 788 pakfire_file_unref(file);
f5c77233
MT
789 goto END;
790 }
791
792 // Bind name
32485f6c 793 const char* path = pakfire_file_get_path(file);
f5c77233 794
32485f6c 795 r = sqlite3_bind_text(stmt, 2, path, -1, NULL);
f5c77233 796 if (r) {
32485f6c 797 ERROR(db->pakfire, "Could not bind path: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 798 pakfire_file_unref(file);
f5c77233
MT
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));
5e9463ec 808 pakfire_file_unref(file);
f5c77233
MT
809 goto END;
810 }
811
f5c77233 812 // Bind config - XXX TODO
b72bae3f 813 r = sqlite3_bind_null(stmt, 4);
f5c77233
MT
814 if (r) {
815 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 816 pakfire_file_unref(file);
f5c77233
MT
817 goto END;
818 }
819
820 // Bind datafile - XXX TODO
b72bae3f 821 r = sqlite3_bind_null(stmt, 5);
f5c77233
MT
822 if (r) {
823 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 824 pakfire_file_unref(file);
f5c77233
MT
825 goto END;
826 }
827
828 // Bind mode
829 mode_t mode = pakfire_file_get_mode(file);
830
b72bae3f 831 r = sqlite3_bind_int64(stmt, 6, mode);
f5c77233
MT
832 if (r) {
833 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 834 pakfire_file_unref(file);
f5c77233
MT
835 goto END;
836 }
837
838 // Bind user
839 const char* user = pakfire_file_get_user(file);
840
b72bae3f 841 r = sqlite3_bind_text(stmt, 7, user, -1, NULL);
f5c77233
MT
842 if (r) {
843 ERROR(db->pakfire, "Could not bind user: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 844 pakfire_file_unref(file);
f5c77233
MT
845 goto END;
846 }
847
848 // Bind group
849 const char* group = pakfire_file_get_group(file);
850
b72bae3f 851 r = sqlite3_bind_text(stmt, 8, group, -1, NULL);
f5c77233
MT
852 if (r) {
853 ERROR(db->pakfire, "Could not bind group: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 854 pakfire_file_unref(file);
f5c77233
MT
855 goto END;
856 }
857
858 // Bind hash1
859 const char* chksum = pakfire_file_get_chksum(file);
860
b72bae3f 861 r = sqlite3_bind_text(stmt, 9, chksum, -1, NULL);
f5c77233
MT
862 if (r) {
863 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 864 pakfire_file_unref(file);
f5c77233
MT
865 goto END;
866 }
867
ef4e8460
MT
868 // Bind ctime
869 time_t ctime = pakfire_file_get_ctime(file);
870
b72bae3f 871 r = sqlite3_bind_int64(stmt, 10, ctime);
ef4e8460
MT
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
f5c77233 878 // Bind mtime
ef4e8460 879 time_t mtime = pakfire_file_get_mtime(file);
f5c77233 880
b72bae3f 881 r = sqlite3_bind_int64(stmt, 11, mtime);
f5c77233
MT
882 if (r) {
883 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 884 pakfire_file_unref(file);
f5c77233
MT
885 goto END;
886 }
887
888 // Bind capabilities - XXX TODO
b72bae3f 889 r = sqlite3_bind_null(stmt, 12);
f5c77233
MT
890 if (r) {
891 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 892 pakfire_file_unref(file);
f5c77233
MT
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
5e9463ec 902 pakfire_file_unref(file);
f5c77233 903
5bae3112
MT
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
f5c77233
MT
911 // Reset bound values
912 sqlite3_reset(stmt);
913 }
914
915 // All okay
916 r = 0;
917
918END:
919 if (stmt)
920 sqlite3_finalize(stmt);
921
5e9463ec
MT
922 pakfire_filelist_unref(filelist);
923
f5c77233
MT
924 return r;
925}
926
265f539a
MT
927static int pakfire_db_add_scriptlets(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
928 sqlite3_stmt* stmt = NULL;
a0097ba2 929 size_t size;
265f539a
MT
930 int r = 1;
931
265f539a
MT
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
a0097ba2 942 for (const char** type = pakfire_scriptlet_types; *type; type++) {
265f539a 943 // Fetch the scriptlet
106d2edd 944 struct pakfire_scriptlet* scriptlet = pakfire_archive_get_scriptlet(archive, *type);
a0097ba2 945 if (!scriptlet)
265f539a 946 continue;
265f539a
MT
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));
a0097ba2 952 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
953 goto END;
954 }
955
956 // Bind handle
a0097ba2 957 r = sqlite3_bind_text(stmt, 2, *type, -1, NULL);
265f539a
MT
958 if (r) {
959 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 960 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
961 goto END;
962 }
963
a0097ba2
MT
964 const char* data = pakfire_scriptlet_get_data(scriptlet, &size);
965
265f539a 966 // Bind scriptlet
a0097ba2 967 r = sqlite3_bind_text(stmt, 3, data, size, NULL);
265f539a
MT
968 if (r) {
969 ERROR(db->pakfire, "Could not bind scriptlet: %s\n", sqlite3_errmsg(db->handle));
a0097ba2 970 pakfire_scriptlet_unref(scriptlet);
265f539a
MT
971 goto END;
972 }
973
974 // Execute query
975 do {
976 r = sqlite3_step(stmt);
977 } while (r == SQLITE_BUSY);
978
5bae3112
MT
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));
a0097ba2 983 pakfire_scriptlet_unref(scriptlet);
5bae3112
MT
984 goto END;
985 }
986
a0097ba2
MT
987 pakfire_scriptlet_unref(scriptlet);
988
265f539a
MT
989 // Reset bound values
990 sqlite3_reset(stmt);
265f539a
MT
991 }
992
993 // All okay
994 r = 0;
995
996END:
997 if (stmt)
998 sqlite3_finalize(stmt);
999
1000 return r;
1001}
1002
9c78c483 1003int pakfire_db_add_package(struct pakfire_db* db,
31480bee 1004 struct pakfire_package* pkg, PakfireArchive archive, int userinstalled) {
e49b93d1
MT
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
6ed66687
MT
1013 const char* sql = "INSERT INTO packages(name, evr, arch, groups, filename, size, "
1014 "inst_size, hash1, license, summary, description, uuid, vendor, build_host, "
dc0cae14
MT
1015 "build_time, installed, repository, userinstalled) "
1016 "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
e49b93d1
MT
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
6ed66687
MT
1035 // Bind evr
1036 const char* evr = pakfire_package_get_evr(pkg);
e49b93d1 1037
6ed66687 1038 r = sqlite3_bind_text(stmt, 2, evr, -1, NULL);
e49b93d1 1039 if (r) {
6ed66687 1040 ERROR(db->pakfire, "Could not bind evr: %s\n", sqlite3_errmsg(db->handle));
e49b93d1
MT
1041 goto ROLLBACK;
1042 }
1043
1044 // Bind arch
1045 const char* arch = pakfire_package_get_arch(pkg);
1046
6ed66687 1047 r = sqlite3_bind_text(stmt, 3, arch, -1, NULL);
e49b93d1
MT
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
1eb7f40b
MT
1054 char* groups = pakfire_package_get_groups(pkg);
1055 if (groups) {
6ed66687 1056 r = sqlite3_bind_text(stmt, 4, groups, -1, NULL);
1eb7f40b
MT
1057 if (r) {
1058 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
1059 free(groups);
1060 goto ROLLBACK;
1061 }
e49b93d1 1062
1eb7f40b
MT
1063 free(groups);
1064
1065 // No groups
1066 } else {
6ed66687 1067 r = sqlite3_bind_null(stmt, 4);
1eb7f40b
MT
1068 if (r)
1069 goto ROLLBACK;
e49b93d1
MT
1070 }
1071
1072 // Bind filename
1073 const char* filename = pakfire_package_get_filename(pkg);
1074
6ed66687 1075 r = sqlite3_bind_text(stmt, 5, filename, -1, NULL);
e49b93d1
MT
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
6ed66687 1084 r = sqlite3_bind_int64(stmt, 6, size);
e49b93d1
MT
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
6ed66687 1093 r = sqlite3_bind_int64(stmt, 7, inst_size);
e49b93d1
MT
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 hash1
1100 const char* hash1 = pakfire_package_get_checksum(pkg);
1101
6ed66687 1102 r = sqlite3_bind_text(stmt, 8, hash1, -1, NULL);
e49b93d1
MT
1103 if (r) {
1104 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
1105 goto ROLLBACK;
1106 }
1107
1108 // Bind license
1109 const char* license = pakfire_package_get_license(pkg);
1110
6ed66687 1111 r = sqlite3_bind_text(stmt, 9, license, -1, NULL);
e49b93d1
MT
1112 if (r) {
1113 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
1114 goto ROLLBACK;
1115 }
1116
1117 // Bind summary
1118 const char* summary = pakfire_package_get_summary(pkg);
1119
6ed66687 1120 r = sqlite3_bind_text(stmt, 10, summary, -1, NULL);
e49b93d1
MT
1121 if (r) {
1122 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
1123 goto ROLLBACK;
1124 }
1125
1126 // Bind description
1127 const char* description = pakfire_package_get_description(pkg);
1128
6ed66687 1129 r = sqlite3_bind_text(stmt, 11, description, -1, NULL);
e49b93d1
MT
1130 if (r) {
1131 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
1132 goto ROLLBACK;
1133 }
1134
1135 // Bind uuid
1136 const char* uuid = pakfire_package_get_uuid(pkg);
1137
6ed66687 1138 r = sqlite3_bind_text(stmt, 12, uuid, -1, NULL);
e49b93d1
MT
1139 if (r) {
1140 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1141 goto ROLLBACK;
1142 }
1143
1144 // Bind vendor
1145 const char* vendor = pakfire_package_get_vendor(pkg);
1146
6ed66687 1147 r = sqlite3_bind_text(stmt, 13, vendor, -1, NULL);
e49b93d1
MT
1148 if (r) {
1149 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
1150 goto ROLLBACK;
1151 }
1152
e49b93d1 1153 // Bind build_host
2ffc704d 1154 const char* build_host = pakfire_package_get_build_host(pkg);
e49b93d1 1155
6ed66687 1156 r = sqlite3_bind_text(stmt, 14, build_host, -1, NULL);
e49b93d1
MT
1157 if (r) {
1158 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
1159 goto ROLLBACK;
1160 }
1161
1162 // Bind build_time
2ffc704d 1163 time_t build_time = pakfire_package_get_build_time(pkg);
e49b93d1 1164
6ed66687 1165 r = sqlite3_bind_int64(stmt, 15, build_time);
e49b93d1
MT
1166 if (r) {
1167 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
1168 goto ROLLBACK;
1169 }
1170
1171 // Bind repository name
1172 PakfireRepo repo = pakfire_package_get_repo(pkg);
1173 if (repo) {
1174 const char* repo_name = pakfire_repo_get_name(repo);
1175 pakfire_repo_unref(repo);
1176
6ed66687 1177 r = sqlite3_bind_text(stmt, 16, repo_name, -1, NULL);
e49b93d1
MT
1178 if (r)
1179 goto ROLLBACK;
1180
1181 // No repository?
1182 } else {
6ed66687 1183 r = sqlite3_bind_null(stmt, 16);
e49b93d1
MT
1184 if (r)
1185 goto ROLLBACK;
1186 }
1187
dc0cae14
MT
1188 // installed by the user?
1189 r = sqlite3_bind_int(stmt, 17, userinstalled);
1190 if (r) {
1191 ERROR(db->pakfire, "Could not bind userinstalled: %s\n", sqlite3_errmsg(db->handle));
e49b93d1 1192 goto ROLLBACK;
dc0cae14 1193 }
e49b93d1
MT
1194
1195 // Run query
1196 do {
1197 r = sqlite3_step(stmt);
1198 } while (r == SQLITE_BUSY);
1199
1200 if (r != SQLITE_DONE) {
1201 ERROR(db->pakfire, "Could not add package to database: %s\n",
1202 sqlite3_errmsg(db->handle));
1203 goto ROLLBACK;
1204 }
1205
f5c77233
MT
1206 // Save package ID
1207 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1208
e49b93d1 1209 // This is done
f5c77233
MT
1210 r = sqlite3_finalize(stmt);
1211 if (r == SQLITE_OK)
1212 stmt = NULL;
1213
1fb2b526
MT
1214 // Add dependencies
1215 r = pakfire_db_add_dependencies(db, packages_id, pkg);
1216 if (r)
1217 goto ROLLBACK;
1218
f5c77233
MT
1219 // Add files
1220 r = pakfire_db_add_files(db, packages_id, archive);
1221 if (r)
1222 goto ROLLBACK;
e49b93d1 1223
265f539a
MT
1224 // Add scriptlets
1225 r = pakfire_db_add_scriptlets(db, packages_id, archive);
1226 if (r)
1227 goto ROLLBACK;
1228
e49b93d1
MT
1229 // All done, commit!
1230 r = pakfire_db_commit(db);
1231 if (r)
1232 goto ROLLBACK;
1233
1234 return 0;
1235
1236ROLLBACK:
f5c77233
MT
1237 if (stmt)
1238 sqlite3_finalize(stmt);
e49b93d1
MT
1239
1240 pakfire_db_rollback(db);
1241
1242 return 1;
eafbe2ce
MT
1243}
1244
31480bee 1245int pakfire_db_remove_package(struct pakfire_db* db, struct pakfire_package* pkg) {
432a328a
MT
1246 sqlite3_stmt* stmt = NULL;
1247 int r = 1;
1248
1249 // Fetch the package's UUID
1250 const char* uuid = pakfire_package_get_uuid(pkg);
1251 if (!uuid) {
1252 ERROR(db->pakfire, "Package has no UUID\n");
1253 goto ERROR;
1254 }
1255
1256 r = sqlite3_prepare_v2(db->handle,
1257 "DELETE FROM packages WHERE uuid = ?", -1, &stmt, NULL);
1258 if (r) {
1259 ERROR(db->pakfire, "Could not prepare SQL statement: %s\n",
1260 sqlite3_errmsg(db->handle));
1261 goto ERROR;
1262 }
1263
1264 // Bind UUID
1265 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1266 if (r) {
1267 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1268 return 1;
1269 }
1270
1271 // Execute query
1272 do {
1273 r = sqlite3_step(stmt);
1274 } while (r == SQLITE_BUSY);
1275
1276 // Check if we have been successful
1277 if (r != SQLITE_DONE) {
1278 ERROR(db->pakfire, "Could not delete package %s\n", uuid);
1279 r = 1;
1280 goto ERROR;
1281 }
1282
1283 r = 0;
1284
1285ERROR:
1286 if (stmt)
1287 sqlite3_finalize(stmt);
1288
1289 return r;
eafbe2ce 1290}
f6942b34
MT
1291
1292struct pakfire_scriptlet* pakfire_db_get_scriptlet(struct pakfire_db* db,
31480bee 1293 struct pakfire_package* pkg, const char* type) {
f6942b34
MT
1294 struct pakfire_scriptlet* scriptlet = NULL;
1295 sqlite3_stmt* stmt = NULL;
1296 int r = 1;
1297
1298 // Fetch the package's UUID
1299 const char* uuid = pakfire_package_get_uuid(pkg);
1300 if (!uuid) {
1301 ERROR(db->pakfire, "Package has no UUID\n");
1302 goto ERROR;
1303 }
1304
7bb92ae3 1305 const char* sql = "SELECT scriptlets.scriptlet FROM packages \
f6942b34
MT
1306 JOIN scriptlets ON packages.id = scriptlets.pkg \
1307 WHERE packages.uuid = ? AND scriptlets.type = ?";
1308
1309 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1310 if (r) {
1311 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1312 sql, sqlite3_errmsg(db->handle));
1313 goto ERROR;
1314 }
1315
1316 // Bind UUID
1317 r = sqlite3_bind_text(stmt, 1, uuid, -1, NULL);
1318 if (r) {
1319 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
1320 goto ERROR;
1321 }
1322
a0097ba2 1323 r = sqlite3_bind_text(stmt, 2, type, -1, NULL);
f6942b34
MT
1324 if (r) {
1325 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
1326 goto ERROR;
1327 }
1328
a0097ba2 1329 DEBUG(db->pakfire, "Searching for scriptlet for package %s of type %s\n", uuid, type);
f6942b34
MT
1330
1331 // Execute query
1332 do {
1333 r = sqlite3_step(stmt);
1334 } while (r == SQLITE_BUSY);
1335
1336 // We have some payload
1337 if (r == SQLITE_ROW) {
1338 const void* data = sqlite3_column_blob(stmt, 1);
1339 ssize_t size = sqlite3_column_bytes(stmt, 1);
1340
1341 // Create a scriptlet object
a0097ba2
MT
1342 r = pakfire_scriptlet_create(&scriptlet, db->pakfire, type, data, size);
1343 if (r)
f6942b34
MT
1344 goto ERROR;
1345 }
1346
1347ERROR:
1348 if (stmt)
1349 sqlite3_finalize(stmt);
1350
1351 return scriptlet;
1352}
361ca45f
MT
1353
1354static int pakfire_db_load_package(struct pakfire_db* db, PakfireRepo repo, sqlite3_stmt* stmt) {
31480bee 1355 struct pakfire_package* pkg = NULL;
361ca45f
MT
1356 int r = 1;
1357
1358 // Name
1359 const char* name = (const char*)sqlite3_column_text(stmt, 0);
1360 if (!name) {
1361 ERROR(db->pakfire, "Could not read name: %s\n", sqlite3_errmsg(db->handle));
1362 goto ERROR;
1363 }
1364
6ed66687
MT
1365 // EVR
1366 const char* evr = (const char*)sqlite3_column_text(stmt, 1);
1367 if (!evr) {
1368 ERROR(db->pakfire, "Could not read evr: %s\n", sqlite3_errmsg(db->handle));
361ca45f
MT
1369 goto ERROR;
1370 }
1371
1372 // Arch
6ed66687 1373 const char* arch = (const char*)sqlite3_column_text(stmt, 2);
361ca45f
MT
1374 if (!arch) {
1375 ERROR(db->pakfire, "Could not read arch: %s\n", sqlite3_errmsg(db->handle));
1376 goto ERROR;
1377 }
1378
361ca45f 1379 // Create package
f71cc0c7 1380 pkg = pakfire_package_create(db->pakfire, repo, name, evr, arch);
361ca45f
MT
1381 if (!pkg) {
1382 ERROR(db->pakfire, "Could not create package\n");
1383 goto ERROR;
1384 }
1385
ac71886a
MT
1386 // ID
1387 uint64_t id = sqlite3_column_int64(stmt, 3);
1388 if (id)
1389 pakfire_package_set_dbid(pkg, id);
1390
7f826034 1391 // Groups
ac71886a 1392 const char* groups = (const char*)sqlite3_column_text(stmt, 4);
7f826034
MT
1393 if (groups) {
1394 pakfire_package_set_groups(pkg, groups);
1395 }
1396
1397 // Filename
ac71886a 1398 const char* filename = (const char*)sqlite3_column_text(stmt, 5);
7f826034
MT
1399 if (filename) {
1400 pakfire_package_set_filename(pkg, filename);
1401 }
1402
1403 // Size
ac71886a 1404 size_t size = sqlite3_column_int64(stmt, 6);
7f826034
MT
1405 if (size) {
1406 pakfire_package_set_downloadsize(pkg, size);
1407 }
1408
1409 // Installed size
ac71886a 1410 size = sqlite3_column_int64(stmt, 7);
7f826034
MT
1411 if (size) {
1412 pakfire_package_set_installsize(pkg, size);
1413 }
1414
1415 // Hash 1
ac71886a 1416 const char* hash1 = (const char*)sqlite3_column_text(stmt, 8);
7f826034
MT
1417 if (hash1) {
1418 pakfire_package_set_checksum(pkg, hash1);
1419 }
1420
1421 // License
ac71886a 1422 const char* license = (const char*)sqlite3_column_text(stmt, 9);
7f826034
MT
1423 if (license) {
1424 pakfire_package_set_license(pkg, license);
1425 }
1426
1427 // Summary
ac71886a 1428 const char* summary = (const char*)sqlite3_column_text(stmt, 10);
7f826034
MT
1429 if (summary) {
1430 pakfire_package_set_summary(pkg, summary);
1431 }
1432
1433 // Description
ac71886a 1434 const char* description = (const char*)sqlite3_column_text(stmt, 11);
7f826034
MT
1435 if (description) {
1436 pakfire_package_set_description(pkg, description);
1437 }
1438
1439 // UUID
ac71886a 1440 const char* uuid = (const char*)sqlite3_column_text(stmt, 12);
7f826034
MT
1441 if (uuid) {
1442 pakfire_package_set_uuid(pkg, uuid);
1443 }
1444
1445 // Vendor
ac71886a 1446 const char* vendor = (const char*)sqlite3_column_text(stmt, 13);
7f826034
MT
1447 if (vendor) {
1448 pakfire_package_set_vendor(pkg, vendor);
1449 }
1450
1451 // Build Host
ac71886a 1452 const char* build_host = (const char*)sqlite3_column_text(stmt, 14);
7f826034 1453 if (build_host) {
2ffc704d 1454 pakfire_package_set_build_host(pkg, build_host);
7f826034
MT
1455 }
1456
1457 // Build Time
ac71886a 1458 time_t build_time = sqlite3_column_int64(stmt, 15);
7f826034 1459 if (build_time) {
2ffc704d 1460 pakfire_package_set_build_time(pkg, build_time);
7f826034
MT
1461 }
1462
af647c55 1463 // Install Time
ac71886a 1464 time_t install_time = sqlite3_column_int64(stmt, 16);
af647c55
MT
1465 if (install_time) {
1466 pakfire_package_set_install_time(pkg, install_time);
1467 }
1468
c9c03e6a 1469 // installed by user?
ac71886a 1470 int userinstalled = sqlite3_column_int(stmt, 17);
c9c03e6a
MT
1471 if (userinstalled)
1472 pakfire_db_add_userinstalled(db->pakfire, name);
1473
d995f7fc 1474 // Files
ac71886a 1475 const char* files = (const char*)sqlite3_column_text(stmt, 18);
d995f7fc 1476 if (files) {
d995f7fc
MT
1477 r = pakfire_package_set_filelist_from_string(pkg, files);
1478 if (r)
1479 goto ERROR;
1480 }
1481
24be412a
MT
1482 // Dependencies
1483
1484 const struct dependency {
1485 unsigned int field;
31480bee 1486 void (*func)(struct pakfire_package* pkg, const char* dep);
24be412a 1487 } dependencies[] = {
ac71886a
MT
1488 { 19, pakfire_package_add_provides },
1489 { 20, pakfire_package_add_prerequires },
1490 { 21, pakfire_package_add_requires },
1491 { 22, pakfire_package_add_conflicts },
1492 { 23, pakfire_package_add_obsoletes },
1493 { 24, pakfire_package_add_recommends },
1494 { 25, pakfire_package_add_suggests },
1495 { 26, pakfire_package_add_supplements },
1496 { 27, pakfire_package_add_enhances },
24be412a
MT
1497 { 0, NULL },
1498 };
1499
1500 for (const struct dependency* deps = dependencies; deps->field; deps++) {
1501 const char* relations = (const char*)sqlite3_column_text(stmt, deps->field);
1502 if (relations) {
b81a64ec 1503 pakfire_parse_deps(db->pakfire, pkg, deps->func, relations);
24be412a
MT
1504 }
1505 }
1506
361ca45f
MT
1507 // Success
1508 r = 0;
1509
1510ERROR:
361ca45f
MT
1511 if (pkg)
1512 pakfire_package_unref(pkg);
1513
1514 return r;
1515}
1516
1517int pakfire_db_load(struct pakfire_db* db, PakfireRepo repo) {
1518 sqlite3_stmt* stmt = NULL;
1519 int r = 1;
1520
1521 DEBUG(db->pakfire, "Loading package database...\n");
1522
7fe22178
MT
1523 // Drop contents of the repository
1524 pakfire_repo_clear(repo);
1525
788221bd
MT
1526 // Save starting time
1527 clock_t t_start = clock();
1528 clock_t t_end;
1529
361ca45f
MT
1530 const char* sql =
1531 "SELECT "
ac71886a
MT
1532 "name, evr, arch, id, groups, filename, size, inst_size, hash1, license, "
1533 "summary, description, uuid, vendor, build_host, build_time, "
c9c03e6a 1534 "strftime('%s', installed) AS installed, userinstalled, "
d995f7fc 1535 "("
32485f6c 1536 "SELECT group_concat(path, '\n') FROM files WHERE files.pkg = packages.id"
24be412a
MT
1537 ") AS files, "
1538 "("
1539 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1540 "WHERE d.pkg = packages.id AND d.type = 'provides'"
1541 ") AS provides, "
1542 "("
1543 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1544 "WHERE d.pkg = packages.id AND d.type = 'prerequires'"
1545 ") AS prerequires, "
1546 "("
1547 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1548 "WHERE d.pkg = packages.id AND d.type = 'requires'"
1549 ") AS requires, "
1550 "("
1551 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1552 "WHERE d.pkg = packages.id AND d.type = 'conflicts'"
1553 ") AS conflicts, "
1554 "("
1555 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1556 "WHERE d.pkg = packages.id AND d.type = 'obsoletes'"
1557 ") AS obsoletes, "
1558 "("
1559 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1560 "WHERE d.pkg = packages.id AND d.type = 'recommends'"
1561 ") AS recommends, "
1562 "("
1563 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1564 "WHERE d.pkg = packages.id AND d.type = 'suggests'"
8fe2e4ba
MT
1565 ") AS suggests, "
1566 "("
1567 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1568 "WHERE d.pkg = packages.id AND d.type = 'supplements'"
1569 ") AS supplements, "
1570 "("
1571 "SELECT group_concat(dependency, '\n') FROM dependencies d "
1572 "WHERE d.pkg = packages.id AND d.type = 'enhances'"
1573 ") AS enhances "
361ca45f
MT
1574 "FROM "
1575 "packages"
1576 ";";
1577
1578 // Prepare the statement
1579 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1580 if (r) {
1581 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1582 sql, sqlite3_errmsg(db->handle));
1583 goto ERROR;
1584 }
1585
1586 for (;;) {
1587 // Execute query
1588 r = sqlite3_step(stmt);
1589
1590 switch (r) {
1591 // Retry if the database was busy
1592 case SQLITE_BUSY:
1593 continue;
1594
1595 // Read a row
1596 case SQLITE_ROW:
1597 r = pakfire_db_load_package(db, repo, stmt);
1598 if (r)
1599 goto ERROR;
1600 break;
1601
1602 // All rows have been processed
1603 case SQLITE_DONE:
1604 goto END;
1605
1606 // Go to error in any other cases
1607 default:
1608 goto ERROR;
1609 }
1610 }
1611
1612END:
788221bd
MT
1613 // Save time when we finished
1614 t_end = clock();
1615
1616 DEBUG(db->pakfire, "Loading package database completed in %.4fms\n",
1617 (double)(t_end - t_start) * 1000 / CLOCKS_PER_SEC);
361ca45f 1618
05336f5e
MT
1619 // Internalize repository
1620 pakfire_repo_internalize(repo);
1621
361ca45f
MT
1622 // All done
1623 r = 0;
1624
1625ERROR:
b027597a 1626 if (r) {
361ca45f 1627 ERROR(db->pakfire, "Failed reading package database: %d\n", r);
b027597a
MT
1628 pakfire_repo_clear(repo);
1629 }
361ca45f
MT
1630
1631 if (stmt)
1632 sqlite3_finalize(stmt);
1633
1634 return r;
1635}
ac71886a
MT
1636
1637static int pakfire_db_load_file(struct pakfire_db* db, PakfireFilelist filelist,
1638 sqlite3_stmt* stmt) {
1639 struct pakfire_file* file = NULL;
1640 char abspath[PATH_MAX];
1641 int r;
1642
1643 // Create a new file object
1644 r = pakfire_file_create(&file, db->pakfire);
1645 if (r)
1646 goto ERROR;
1647
1648 // Path
1649 const char* path = (const char*)sqlite3_column_text(stmt, 0);
1650 if (path)
1651 pakfire_file_set_path(file, path);
1652
1653 // Abspath
1654 r = pakfire_make_path(db->pakfire, abspath, path);
1655 if (r < 0)
1656 goto ERROR;
1657
1658 pakfire_file_set_abspath(file, abspath);
1659
1660 // Size
1661 size_t size = sqlite3_column_int64(stmt, 1);
1662 if (size)
1663 pakfire_file_set_size(file, size);
1664
1665 // Mode
1666 mode_t mode = sqlite3_column_int(stmt, 2);
1667 if (mode)
1668 pakfire_file_set_mode(file, mode);
1669
1670 // User
1671 const char* user = (const char*)sqlite3_column_text(stmt, 3);
1672 if (user)
1673 pakfire_file_set_user(file, user);
1674
1675 // Group
1676 const char* group = (const char*)sqlite3_column_text(stmt, 4);
1677 if (group)
1678 pakfire_file_set_group(file, group);
1679
1680 // ctime
1681 time_t ctime = sqlite3_column_int64(stmt, 5);
1682 if (ctime)
1683 pakfire_file_set_ctime(file, ctime);
1684
1685 // mtime
1686 time_t mtime = sqlite3_column_int64(stmt, 6);
1687 if (mtime)
1688 pakfire_file_set_mtime(file, mtime);
1689
1690 // Append the file to the filelist
1691 r = pakfire_filelist_append(filelist, file);
1692
1693ERROR:
1694 if (file)
1695 pakfire_file_unref(file);
1696
1697 return r;
1698}
1699
1700int pakfire_db_package_filelist(struct pakfire_db* db, PakfireFilelist* filelist,
31480bee 1701 struct pakfire_package* pkg) {
ac71886a
MT
1702 PakfireFilelist fl = NULL;
1703 sqlite3_stmt* stmt = NULL;
1704 int r = 1;
1705
1706 // Fetch the package ID
1707 uint64_t id = pakfire_package_get_dbid(pkg);
1708 if (!id) {
1709 ERROR(db->pakfire, "Package did not have an ID\n");
1710 return 1;
1711 }
1712
1713 // Create a new filelist
1714 r = pakfire_filelist_create(&fl, db->pakfire);
1715 if (r) {
1716 ERROR(db->pakfire, "Could not create filelist: %m\n");
1717 goto ERROR;
1718 }
1719
1720 const char* sql =
1721 "SELECT "
1722 "path, "
1723 "size, "
1724 "mode, "
1725 "user, "
1726 "'group', "
1727 "ctime, "
1728 "mtime "
1729 "FROM files "
1730
1731 // Select all files that belong to this package
1732 "WHERE "
1733 "pkg = ? "
1734
1735 // Filter out any files that are also in a different package (i.e. an update
1736 // that has already been installed and this is the cleanup of the obsolete pkg)
1737 "AND "
1738 "NOT EXISTS ("
1739 "SELECT "
1740 "1 "
1741 "FROM files AS duplicates "
1742 "WHERE "
1743 "files.path = duplicates.path "
1744 "AND "
1745 "files.pkg != duplicates.pkg"
1746 ") "
1747
1748 // Return the longest paths first
1749 "ORDER BY "
1750 "length(path) DESC"
1751 ";";
1752
1753 // Prepare the statement
1754 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
1755 if (r) {
1756 ERROR(db->pakfire, "Could not prepare SQL statement: %s %s\n",
1757 sql, sqlite3_errmsg(db->handle));
1758 goto ERROR;
1759 }
1760
1761 // Bind package ID
1762 r = sqlite3_bind_int64(stmt, 1, id);
1763 if (r) {
1764 ERROR(db->pakfire, "Could not bind package ID: %s\n", sqlite3_errmsg(db->handle));
1765 goto ERROR;
1766 }
1767
1768 for (;;) {
1769 // Execute query
1770 r = sqlite3_step(stmt);
1771
1772 switch (r) {
1773 // Retry if the database was busy
1774 case SQLITE_BUSY:
1775 continue;
1776
1777 // Read a row
1778 case SQLITE_ROW:
1779 r = pakfire_db_load_file(db, fl, stmt);
1780 if (r)
1781 goto ERROR;
1782 break;
1783
1784 // All rows have been processed
1785 case SQLITE_DONE:
1786 goto END;
1787
1788 // Go to error in any other cases
1789 default:
1790 goto ERROR;
1791 }
1792 }
1793
1794END:
1795 *filelist = pakfire_filelist_ref(fl);
1796 r = 0;
1797
1798ERROR:
1799 if (stmt)
1800 sqlite3_finalize(stmt);
1801 if (fl)
1802 pakfire_filelist_unref(fl);
1803
1804 return r;
1805}