]> git.ipfire.org Git - people/ms/pakfire.git/blame - src/libpakfire/db.c
libpakfire: scriptlets live in "scriptlets/"
[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>
22#include <stdlib.h>
23
26affd69
MT
24#include <sqlite3.h>
25
f5c77233 26#include <pakfire/archive.h>
33d55ab4 27#include <pakfire/db.h>
f5c77233 28#include <pakfire/file.h>
33d55ab4 29#include <pakfire/logging.h>
e49b93d1 30#include <pakfire/package.h>
18bf891d
MT
31#include <pakfire/pakfire.h>
32#include <pakfire/private.h>
e49b93d1 33#include <pakfire/repo.h>
33d55ab4
MT
34#include <pakfire/types.h>
35#include <pakfire/util.h>
36
0cb487ff
MT
37#define DATABASE_PATH PAKFIRE_PRIVATE_DIR "/packages.db"
38
5ba550fe 39#define CURRENT_SCHEMA 8
c745fb2d
MT
40#define SCHEMA_MIN_SUP 7
41
33d55ab4
MT
42struct pakfire_db {
43 Pakfire pakfire;
44 int nrefs;
77a4b3a3
MT
45
46 int mode;
26affd69
MT
47
48 sqlite3* handle;
c745fb2d 49 int schema;
33d55ab4
MT
50};
51
9c5938ea
MT
52static void logging_callback(void* data, int r, const char* msg) {
53 Pakfire pakfire = (Pakfire)data;
54
55 ERROR(pakfire, "Database Error: %s: %s\n",
56 sqlite3_errstr(r), msg);
57}
58
0076c50d
MT
59static int pakfire_db_execute(struct pakfire_db* db, const char* stmt) {
60 int r;
c745fb2d
MT
61
62 DEBUG(db->pakfire, "Executing database query: %s\n", stmt);
0076c50d
MT
63
64 do {
c745fb2d 65 r = sqlite3_exec(db->handle, stmt, NULL, NULL, NULL);
0076c50d
MT
66 } while (r == SQLITE_BUSY);
67
c745fb2d
MT
68 // Log any errors
69 if (r) {
70 ERROR(db->pakfire, "Database query failed: %s\n", sqlite3_errmsg(db->handle));
71 }
72
25753290
MT
73 return r;
74}
75
c745fb2d
MT
76static int pakfire_db_begin_transaction(struct pakfire_db* db) {
77 return pakfire_db_execute(db, "BEGIN TRANSACTION");
78}
79
80static int pakfire_db_commit(struct pakfire_db* db) {
81 return pakfire_db_execute(db, "COMMIT");
82}
83
84static int pakfire_db_rollback(struct pakfire_db* db) {
85 return pakfire_db_execute(db, "ROLLBACK");
86}
87
25753290
MT
88/*
89 This function performs any fast optimization and tries to truncate the WAL log file
90 to keep the database as compact as possible on disk.
91*/
92static void pakfire_db_optimize(struct pakfire_db* db) {
44d392ef 93 pakfire_db_execute(db, "PRAGMA optimize");
25753290 94 pakfire_db_execute(db, "PRAGMA wal_checkpoint = TRUNCATE");
0076c50d
MT
95}
96
26affd69
MT
97static void pakfire_db_free(struct pakfire_db* db) {
98 DEBUG(db->pakfire, "Releasing database at %p\n", db);
99
26affd69 100 if (db->handle) {
25753290
MT
101 // Optimize the database before it is being closed
102 pakfire_db_optimize(db);
103
104 // Close database handle
26affd69
MT
105 int r = sqlite3_close(db->handle);
106 if (r != SQLITE_OK) {
107 ERROR(db->pakfire, "Could not close database handle: %s\n",
108 sqlite3_errmsg(db->handle));
109 }
110 }
111
112 pakfire_unref(db->pakfire);
113
114 pakfire_free(db);
115}
116
c745fb2d
MT
117static sqlite3_value* pakfire_db_get(struct pakfire_db* db, const char* key) {
118 sqlite3_stmt* stmt = NULL;
119 sqlite3_value* val = NULL;
120 int r;
121
122 const char* sql = "SELECT val FROM settings WHERE key = ?";
123
124 // Prepare the statement
125 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
126 if (r != SQLITE_OK) {
127 //ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
128 // sql, sqlite3_errmsg(db->handle));
129 return NULL;
130 }
131
132 // Bind key
133 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
134 if (r != SQLITE_OK) {
135 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
136 goto ERROR;
137 }
138
139 // Execute the statement
140 do {
141 r = sqlite3_step(stmt);
142 } while (r == SQLITE_BUSY);
143
f168dd0c
MT
144 // We should have read a row
145 if (r != SQLITE_ROW)
146 goto ERROR;
147
c745fb2d 148 // Read value
f168dd0c 149 val = sqlite3_column_value(stmt, 0);
c745fb2d
MT
150 if (!val) {
151 ERROR(db->pakfire, "Could not read value\n");
152 goto ERROR;
153 }
154
155 // Copy value onto the heap
156 val = sqlite3_value_dup(val);
157
158ERROR:
159 if (stmt)
160 sqlite3_finalize(stmt);
161
162 return val;
163}
164
165static int pakfire_db_set_int(struct pakfire_db* db, const char* key, int val) {
166 sqlite3_stmt* stmt = NULL;
167 int r;
168
169 const char* sql = "INSERT INTO settings(key, val) VALUES(?, ?) \
170 ON CONFLICT (key) DO UPDATE SET val = excluded.val";
171
172 // Prepare statement
173 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
174 if (r != SQLITE_OK) {
175 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
176 sql, sqlite3_errmsg(db->handle));
177 return 1;
178 }
179
180 // Bind key
181 r = sqlite3_bind_text(stmt, 1, key, strlen(key), NULL);
182 if (r != SQLITE_OK) {
183 ERROR(db->pakfire, "Could not bind key: %s\n", sqlite3_errmsg(db->handle));
184 goto ERROR;
185 }
186
187 // Bind val
188 r = sqlite3_bind_int64(stmt, 2, val);
189 if (r != SQLITE_OK) {
190 ERROR(db->pakfire, "Could not bind val: %s\n", sqlite3_errmsg(db->handle));
191 goto ERROR;
192 }
193
194 // Execute the statement
195 do {
196 r = sqlite3_step(stmt);
197 } while (r == SQLITE_BUSY);
198
199 // Set return code
200 r = (r == SQLITE_OK);
201
202ERROR:
203 if (stmt)
204 sqlite3_finalize(stmt);
205
206 return r;
207}
208
209static int pakfire_db_get_schema(struct pakfire_db* db) {
210 sqlite3_value* value = pakfire_db_get(db, "schema");
211 if (!value)
f168dd0c 212 return -1;
c745fb2d
MT
213
214 int schema = sqlite3_value_int64(value);
215 sqlite3_value_free(value);
216
217 DEBUG(db->pakfire, "Database has schema version %d\n", schema);
218
219 return schema;
220}
221
222static int pakfire_db_create_schema(struct pakfire_db* db) {
223 int r;
224
225 // Create settings table
226 r = pakfire_db_execute(db, "CREATE TABLE IF NOT EXISTS settings(key TEXT, val TEXT)");
227 if (r)
228 return 1;
229
230 // settings: Add a unique index on key
231 r = pakfire_db_execute(db, "CREATE UNIQUE INDEX IF NOT EXISTS settings_key ON settings(key)");
232 if (r)
233 return 1;
234
704b3993
MT
235 // Create packages table
236 r = pakfire_db_execute(db,
237 "CREATE TABLE IF NOT EXISTS packages("
238 "id INTEGER PRIMARY KEY, "
239 "name TEXT, "
240 "epoch INTEGER, "
241 "version TEXT, "
242 "release TEXT, "
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, "
257 "reason TEXT, "
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
2359ca14
MT
268 // Create dependencies table
269 r = pakfire_db_execute(db,
270 "CREATE TABLE IF NOT EXISTS dependencies("
271 "pkg INTEGER, "
272 "type TEXT, "
46257c5f
MT
273 "dependency TEXT, "
274 "FOREIGN KEY (pkg) REFERENCES packages(id)"
2359ca14
MT
275 ")");
276 if (r)
277 return r;
278
279 // dependencies: Add index over packages
280 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS dependencies_pkg_index ON dependencies(pkg)");
281 if (r)
282 return r;
283
68036506
MT
284 // Create files table
285 r = pakfire_db_execute(db,
286 "CREATE TABLE IF NOT EXISTS files("
287 "id INTEGER PRIMARY KEY, "
288 "name TEXT, "
289 "pkg INTEGER, "
290 "size INTEGER, "
291 "type INTEGER, "
292 "config INTEGER, "
293 "datafile INTEGER, "
294 "mode INTEGER, "
295 "user TEXT, "
296 "'group' TEXT, "
297 "hash1 TEXT, "
298 "mtime INTEGER, "
46257c5f
MT
299 "capabilities TEXT, "
300 "FOREIGN KEY (pkg) REFERENCES packages(id)"
68036506
MT
301 ")");
302 if (r)
303 return 1;
304
305 // files: Add index over packages
306 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS files_pkg_index ON files(pkg)");
307 if (r)
308 return 1;
309
d83414aa
MT
310 // Create scriptlets table
311 r = pakfire_db_execute(db,
312 "CREATE TABLE IF NOT EXISTS scriptlets("
313 "id INTEGER PRIMARY KEY, "
314 "pkg INTEGER, "
315 "action TEXT, "
46257c5f
MT
316 "scriptlet TEXT, "
317 "FOREIGN KEY (pkg) REFERENCES packages(id)"
d83414aa
MT
318 ")");
319 if (r)
320 return 1;
321
322 // scriptlets: Add index over packages
323 r = pakfire_db_execute(db, "CREATE INDEX IF NOT EXISTS scriptlets_pkg_index ON scriptlets(pkg)");
324 if (r)
325 return 1;
326
c745fb2d
MT
327 return 0;
328}
329
46257c5f 330static int pakfire_db_migrate_to_schema_8(struct pakfire_db* db) {
5ba550fe
MT
331 // packages: Drop build_id column
332
46257c5f
MT
333 // Add foreign keys
334 // TODO sqlite doesn't support adding foreign keys to existing tables and so we would
335 // need to recreate the whole table and rename it afterwards. Annoying.
336
337 return 0;
338}
339
c745fb2d
MT
340static int pakfire_db_migrate_schema(struct pakfire_db* db) {
341 int r;
342
343 while (db->schema < CURRENT_SCHEMA) {
344 // Begin a new transaction
345 r = pakfire_db_begin_transaction(db);
346 if (r)
347 goto ROLLBACK;
348
349 switch (db->schema) {
350 // No schema exists
f168dd0c 351 case -1:
c745fb2d
MT
352 r = pakfire_db_create_schema(db);
353 if (r)
354 goto ROLLBACK;
355
356 db->schema = CURRENT_SCHEMA;
357 break;
358
46257c5f
MT
359 case 7:
360 r = pakfire_db_migrate_to_schema_8(db);
361 if (r)
362 goto ROLLBACK;
363
364 db->schema++;
365 break;
366
c745fb2d
MT
367 default:
368 ERROR(db->pakfire, "Cannot migrate database from schema %d\n", db->schema);
369 goto ROLLBACK;
370 }
371
372 // Update the schema version
373 r = pakfire_db_set_int(db, "schema", CURRENT_SCHEMA);
374 if (r)
375 goto ROLLBACK;
376
377 // All done, commit!
378 r = pakfire_db_commit(db);
379 if (r)
380 goto ROLLBACK;
381 }
382
383 return 0;
384
385ROLLBACK:
386 pakfire_db_rollback(db);
387
388 return 1;
389}
390
9c5938ea 391static int pakfire_db_setup(struct pakfire_db* db) {
25753290
MT
392 int r;
393
9c5938ea
MT
394 // Setup logging
395 sqlite3_config(SQLITE_CONFIG_LOG, logging_callback, db->pakfire);
396
46257c5f
MT
397 // Enable foreign keys
398 pakfire_db_execute(db, "PRAGMA foreign_keys = ON");
399
0076c50d
MT
400 // Make LIKE case-sensitive
401 pakfire_db_execute(db, "PRAGMA case_sensitive_like = ON");
402
c745fb2d
MT
403 // Fetch the current schema
404 db->schema = pakfire_db_get_schema(db);
405
406 // Check if the schema is recent enough
407 if (db->schema > 0 && db->schema < SCHEMA_MIN_SUP) {
408 ERROR(db->pakfire, "Database schema %d is not supported by this version of Pakfire\n",
409 db->schema);
410 return 1;
411 }
412
9c5938ea
MT
413 // Done when not in read-write mode
414 if (db->mode != PAKFIRE_DB_READWRITE)
415 return 0;
416
0076c50d
MT
417 // Disable secure delete
418 pakfire_db_execute(db, "PRAGMA secure_delete = OFF");
419
25753290
MT
420 // Set database journal to WAL
421 r = pakfire_db_execute(db, "PRAGMA journal_mode = WAL");
422 if (r != SQLITE_OK) {
423 ERROR(db->pakfire, "Could not set journal mode to WAL: %s\n",
424 sqlite3_errmsg(db->handle));
425 return 1;
426 }
427
428 // Disable autocheckpoint
429 r = sqlite3_wal_autocheckpoint(db->handle, 0);
430 if (r != SQLITE_OK) {
431 ERROR(db->pakfire, "Could not disable autocheckpoint: %s\n",
432 sqlite3_errmsg(db->handle));
433 return 1;
434 }
435
c745fb2d
MT
436 // Create or migrate schema
437 r = pakfire_db_migrate_schema(db);
438 if (r)
439 return r;
9c5938ea
MT
440
441 return 0;
442}
443
77a4b3a3 444PAKFIRE_EXPORT int pakfire_db_open(struct pakfire_db** db, Pakfire pakfire, int flags) {
26affd69
MT
445 int r = 1;
446
33d55ab4
MT
447 struct pakfire_db* o = pakfire_calloc(1, sizeof(*o));
448 if (!o)
449 return -ENOMEM;
450
451 DEBUG(pakfire, "Allocated database at %p\n", o);
452
453 o->pakfire = pakfire_ref(pakfire);
454 o->nrefs = 1;
455
26affd69
MT
456 int sqlite3_flags = 0;
457
458 // Store mode & forward it to sqlite3
459 if (flags & PAKFIRE_DB_READWRITE) {
77a4b3a3 460 o->mode = PAKFIRE_DB_READWRITE;
26affd69
MT
461 sqlite3_flags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
462 } else {
77a4b3a3 463 o->mode = PAKFIRE_DB_READONLY;
26affd69
MT
464 sqlite3_flags |= SQLITE_OPEN_READONLY;
465 }
466
467 // Make the filename
468 char* path = pakfire_make_path(o->pakfire, DATABASE_PATH);
469 if (!path)
470 goto END;
471
472 // Try to open the sqlite3 database file
473 r = sqlite3_open_v2(path, &o->handle, sqlite3_flags, NULL);
474 if (r != SQLITE_OK) {
475 ERROR(pakfire, "Could not open database %s: %s\n",
476 path, sqlite3_errmsg(o->handle));
477
478 r = 1;
479 goto END;
480 }
77a4b3a3 481
9c5938ea
MT
482 // Setup the database
483 r = pakfire_db_setup(o);
484 if (r)
485 goto END;
486
33d55ab4 487 *db = o;
26affd69
MT
488 r = 0;
489
490END:
491 if (r)
492 pakfire_db_free(o);
33d55ab4 493
26affd69
MT
494 if (path)
495 free(path);
496
497 return r;
33d55ab4
MT
498}
499
18bf891d 500PAKFIRE_EXPORT struct pakfire_db* pakfire_db_ref(struct pakfire_db* db) {
33d55ab4
MT
501 db->nrefs++;
502
503 return db;
504}
505
18bf891d 506PAKFIRE_EXPORT struct pakfire_db* pakfire_db_unref(struct pakfire_db* db) {
33d55ab4
MT
507 if (--db->nrefs > 0)
508 return db;
509
510 pakfire_db_free(db);
511
512 return NULL;
513}
eafbe2ce 514
a1571786
MT
515static unsigned long pakfire_db_integrity_check(struct pakfire_db* db) {
516 sqlite3_stmt* stmt = NULL;
517 int r;
518
519 r = sqlite3_prepare_v2(db->handle, "PRAGMA integrity_check", -1, &stmt, NULL);
520 if (r) {
521 ERROR(db->pakfire, "Could not prepare integrity check: %s\n",
522 sqlite3_errmsg(db->handle));
523 return 1;
524 }
525
526 // Count any errors
527 unsigned long errors = 0;
528
529 while (1) {
530 do {
531 r = sqlite3_step(stmt);
532 } while (r == SQLITE_BUSY);
533
534 if (r == SQLITE_ROW) {
535 const char* error = (const char*)sqlite3_column_text(stmt, 0);
536
537 // If the message is "ok", the database has passed the check
538 if (strcmp(error, "ok") == 0)
539 continue;
540
541 // Increment error counter
542 errors++;
543
544 // Log the message
545 ERROR(db->pakfire, "%s\n", error);
546
547 // Break on anything else
548 } else
549 break;
550 }
551
552 sqlite3_finalize(stmt);
553
554 if (errors)
555 ERROR(db->pakfire, "Database integrity check failed\n");
556 else
557 INFO(db->pakfire, "Database integrity check passed\n");
558
559 return errors;
560}
561
562static unsigned long pakfire_db_foreign_key_check(struct pakfire_db* db) {
563 sqlite3_stmt* stmt = NULL;
564 int r;
565
566 r = sqlite3_prepare_v2(db->handle, "PRAGMA foreign_key_check", -1, &stmt, NULL);
567 if (r) {
568 ERROR(db->pakfire, "Could not prepare foreign key check: %s\n",
569 sqlite3_errmsg(db->handle));
570 return 1;
571 }
572
573 // Count any errors
574 unsigned long errors = 0;
575
576 while (1) {
577 do {
578 r = sqlite3_step(stmt);
579 } while (r == SQLITE_BUSY);
580
581 if (r == SQLITE_ROW) {
582 const unsigned char* table = sqlite3_column_text(stmt, 0);
583 unsigned long rowid = sqlite3_column_int64(stmt, 1);
584 const unsigned char* foreign_table = sqlite3_column_text(stmt, 2);
585 unsigned long foreign_rowid = sqlite3_column_int64(stmt, 3);
586
587 // Increment error counter
588 errors++;
589
590 // Log the message
591 ERROR(db->pakfire, "Foreign key violation found in %s, row %lu: "
592 "%lu does not exist in table %s\n", table, rowid, foreign_rowid, foreign_table);
593
594 // Break on anything else
595 } else
596 break;
597 }
598
599 sqlite3_finalize(stmt);
600
601 if (errors)
602 ERROR(db->pakfire, "Foreign key check failed\n");
603 else
604 INFO(db->pakfire, "Foreign key check passed\n");
605
606 return errors;
607}
608
609/*
610 This function performs an integrity check of the database
611*/
612PAKFIRE_EXPORT int pakfire_db_check(struct pakfire_db* db) {
613 int r;
614
615 // Perform integrity check
616 r = pakfire_db_integrity_check(db);
617 if (r)
618 return 1;
619
620 // Perform foreign key check
621 r = pakfire_db_foreign_key_check(db);
622 if (r)
623 return 1;
624
625 return 0;
626}
627
f5c77233
MT
628static int pakfire_db_add_files(struct pakfire_db* db, unsigned long id, PakfireArchive archive) {
629 sqlite3_stmt* stmt = NULL;
dccd04a4 630 int r = 1;
f5c77233
MT
631
632 // Get the filelist from the archive
5e9463ec
MT
633 PakfireFilelist filelist = pakfire_archive_get_filelist(archive);
634 if (!filelist) {
f5c77233
MT
635 ERROR(db->pakfire, "Could not fetch filelist from archive\n");
636 return 1;
637 }
638
5e9463ec
MT
639 // Nothing to do if the list is empty
640 if (pakfire_filelist_is_empty(filelist))
641 goto END;
642
f5c77233
MT
643 const char* sql = "INSERT INTO files(pkg, name, size, type, config, datafile, mode, "
644 "user, 'group', hash1, mtime, capabilities) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
645
646 // Prepare the statement
647 r = sqlite3_prepare_v2(db->handle, sql, -1, &stmt, NULL);
648 if (r) {
649 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
650 sql, sqlite3_errmsg(db->handle));
651 goto END;
652 }
653
5e9463ec
MT
654 for (unsigned int i = 0; i < pakfire_filelist_size(filelist); i++) {
655 PakfireFile file = pakfire_filelist_get(filelist, i);
656
f5c77233
MT
657 // Bind package ID
658 r = sqlite3_bind_int64(stmt, 1, id);
659 if (r) {
660 ERROR(db->pakfire, "Could not bind id: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 661 pakfire_file_unref(file);
f5c77233
MT
662 goto END;
663 }
664
665 // Bind name
666 const char* name = pakfire_file_get_name(file);
667
668 r = sqlite3_bind_text(stmt, 2, name, -1, NULL);
669 if (r) {
670 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 671 pakfire_file_unref(file);
f5c77233
MT
672 goto END;
673 }
674
675 // Bind size
676 size_t size = pakfire_file_get_size(file);
677
678 r = sqlite3_bind_int64(stmt, 3, size);
679 if (r) {
680 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 681 pakfire_file_unref(file);
f5c77233
MT
682 goto END;
683 }
684
685 // Bind type - XXX this is char which isn't very helpful
686 //char type = pakfire_file_get_type(file);
687
688 r = sqlite3_bind_null(stmt, 4);
689 if (r) {
690 ERROR(db->pakfire, "Could not bind type: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 691 pakfire_file_unref(file);
f5c77233
MT
692 goto END;
693 }
694
695 // Bind config - XXX TODO
696 r = sqlite3_bind_null(stmt, 5);
697 if (r) {
698 ERROR(db->pakfire, "Could not bind config: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 699 pakfire_file_unref(file);
f5c77233
MT
700 goto END;
701 }
702
703 // Bind datafile - XXX TODO
704 r = sqlite3_bind_null(stmt, 6);
705 if (r) {
706 ERROR(db->pakfire, "Could not bind datafile: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 707 pakfire_file_unref(file);
f5c77233
MT
708 goto END;
709 }
710
711 // Bind mode
712 mode_t mode = pakfire_file_get_mode(file);
713
714 r = sqlite3_bind_int64(stmt, 7, mode);
715 if (r) {
716 ERROR(db->pakfire, "Could not bind mode: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 717 pakfire_file_unref(file);
f5c77233
MT
718 goto END;
719 }
720
721 // Bind user
722 const char* user = pakfire_file_get_user(file);
723
724 r = sqlite3_bind_text(stmt, 8, user, -1, NULL);
725 if (r) {
726 ERROR(db->pakfire, "Could not bind user: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 727 pakfire_file_unref(file);
f5c77233
MT
728 goto END;
729 }
730
731 // Bind group
732 const char* group = pakfire_file_get_group(file);
733
734 r = sqlite3_bind_text(stmt, 9, group, -1, NULL);
735 if (r) {
736 ERROR(db->pakfire, "Could not bind group: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 737 pakfire_file_unref(file);
f5c77233
MT
738 goto END;
739 }
740
741 // Bind hash1
742 const char* chksum = pakfire_file_get_chksum(file);
743
744 r = sqlite3_bind_text(stmt, 10, chksum, -1, NULL);
745 if (r) {
746 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 747 pakfire_file_unref(file);
f5c77233
MT
748 goto END;
749 }
750
751 // Bind mtime
752 time_t mtime = pakfire_file_get_time(file);
753
754 r = sqlite3_bind_int64(stmt, 11, mtime);
755 if (r) {
756 ERROR(db->pakfire, "Could not bind mtime: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 757 pakfire_file_unref(file);
f5c77233
MT
758 goto END;
759 }
760
761 // Bind capabilities - XXX TODO
762 r = sqlite3_bind_null(stmt, 12);
763 if (r) {
764 ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
5e9463ec 765 pakfire_file_unref(file);
f5c77233
MT
766 goto END;
767 }
768
769 // Execute query
770 do {
771 r = sqlite3_step(stmt);
772 } while (r == SQLITE_BUSY);
773
774 // Move on to next file
5e9463ec 775 pakfire_file_unref(file);
f5c77233
MT
776
777 // Reset bound values
778 sqlite3_reset(stmt);
779 }
780
781 // All okay
782 r = 0;
783
784END:
785 if (stmt)
786 sqlite3_finalize(stmt);
787
5e9463ec
MT
788 pakfire_filelist_unref(filelist);
789
f5c77233
MT
790 return r;
791}
792
793PAKFIRE_EXPORT int pakfire_db_add_package(struct pakfire_db* db,
794 PakfirePackage pkg, PakfireArchive archive) {
e49b93d1
MT
795 sqlite3_stmt* stmt = NULL;
796 int r;
797
798 // Begin a new transaction
799 r = pakfire_db_begin_transaction(db);
800 if (r)
801 goto ROLLBACK;
802
803 const char* sql = "INSERT INTO packages(name, epoch, version, release, arch, groups, "
804 "filename, size, inst_size, hash1, license, summary, description, uuid, vendor, "
1ca6a13d
MT
805 "build_host, build_time, installed, repository, reason) VALUES(?, ?, "
806 "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?)";
e49b93d1
MT
807
808 // Prepare the statement
809 r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
810 if (r != SQLITE_OK) {
811 ERROR(db->pakfire, "Could not prepare SQL statement: %s: %s\n",
812 sql, sqlite3_errmsg(db->handle));
813 goto ROLLBACK;
814 }
815
816 // Bind name
817 const char* name = pakfire_package_get_name(pkg);
818
819 r = sqlite3_bind_text(stmt, 1, name, -1, NULL);
820 if (r) {
821 ERROR(db->pakfire, "Could not bind name: %s\n", sqlite3_errmsg(db->handle));
822 goto ROLLBACK;
823 }
824
825 // Bind epoch
826 unsigned long epoch = pakfire_package_get_epoch(pkg);
827
828 r = sqlite3_bind_int64(stmt, 2, epoch);
829 if (r) {
830 ERROR(db->pakfire, "Could not bind epoch: %s\n", sqlite3_errmsg(db->handle));
831 goto ROLLBACK;
832 }
833
834 // Bind version
835 const char* version = pakfire_package_get_version(pkg);
836
837 r = sqlite3_bind_text(stmt, 3, version, -1, NULL);
838 if (r) {
839 ERROR(db->pakfire, "Could not bind version: %s\n", sqlite3_errmsg(db->handle));
840 goto ROLLBACK;
841 }
842
843 // Bind release
844 const char* release = pakfire_package_get_release(pkg);
845
846 r = sqlite3_bind_text(stmt, 4, release, -1, NULL);
847 if (r) {
848 ERROR(db->pakfire, "Could not bind release: %s\n", sqlite3_errmsg(db->handle));
849 goto ROLLBACK;
850 }
851
852 // Bind arch
853 const char* arch = pakfire_package_get_arch(pkg);
854
855 r = sqlite3_bind_text(stmt, 5, arch, -1, NULL);
856 if (r) {
857 ERROR(db->pakfire, "Could not bind arch: %s\n", sqlite3_errmsg(db->handle));
858 goto ROLLBACK;
859 }
860
861 // Bind groups
862 const char* groups = pakfire_package_get_groups(pkg);
863
864 r = sqlite3_bind_text(stmt, 6, groups, -1, NULL);
865 if (r) {
866 ERROR(db->pakfire, "Could not bind groups: %s\n", sqlite3_errmsg(db->handle));
867 goto ROLLBACK;
868 }
869
870 // Bind filename
871 const char* filename = pakfire_package_get_filename(pkg);
872
873 r = sqlite3_bind_text(stmt, 7, filename, -1, NULL);
874 if (r) {
875 ERROR(db->pakfire, "Could not bind filename: %s\n", sqlite3_errmsg(db->handle));
876 goto ROLLBACK;
877 }
878
879 // Bind size
880 unsigned long long size = pakfire_package_get_downloadsize(pkg);
881
882 r = sqlite3_bind_int64(stmt, 8, size);
883 if (r) {
884 ERROR(db->pakfire, "Could not bind size: %s\n", sqlite3_errmsg(db->handle));
885 goto ROLLBACK;
886 }
887
888 // Bind installed size
889 unsigned long long inst_size = pakfire_package_get_installsize(pkg);
890
891 r = sqlite3_bind_int64(stmt, 9, inst_size);
892 if (r) {
893 ERROR(db->pakfire, "Could not bind inst_size: %s\n", sqlite3_errmsg(db->handle));
894 goto ROLLBACK;
895 }
896
897 // Bind hash1
898 const char* hash1 = pakfire_package_get_checksum(pkg);
899
900 r = sqlite3_bind_text(stmt, 10, hash1, -1, NULL);
901 if (r) {
902 ERROR(db->pakfire, "Could not bind hash1: %s\n", sqlite3_errmsg(db->handle));
903 goto ROLLBACK;
904 }
905
906 // Bind license
907 const char* license = pakfire_package_get_license(pkg);
908
909 r = sqlite3_bind_text(stmt, 11, license, -1, NULL);
910 if (r) {
911 ERROR(db->pakfire, "Could not bind license: %s\n", sqlite3_errmsg(db->handle));
912 goto ROLLBACK;
913 }
914
915 // Bind summary
916 const char* summary = pakfire_package_get_summary(pkg);
917
918 r = sqlite3_bind_text(stmt, 12, summary, -1, NULL);
919 if (r) {
920 ERROR(db->pakfire, "Could not bind summary: %s\n", sqlite3_errmsg(db->handle));
921 goto ROLLBACK;
922 }
923
924 // Bind description
925 const char* description = pakfire_package_get_description(pkg);
926
927 r = sqlite3_bind_text(stmt, 13, description, -1, NULL);
928 if (r) {
929 ERROR(db->pakfire, "Could not bind description: %s\n", sqlite3_errmsg(db->handle));
930 goto ROLLBACK;
931 }
932
933 // Bind uuid
934 const char* uuid = pakfire_package_get_uuid(pkg);
935
936 r = sqlite3_bind_text(stmt, 14, uuid, -1, NULL);
937 if (r) {
938 ERROR(db->pakfire, "Could not bind uuid: %s\n", sqlite3_errmsg(db->handle));
939 goto ROLLBACK;
940 }
941
942 // Bind vendor
943 const char* vendor = pakfire_package_get_vendor(pkg);
944
945 r = sqlite3_bind_text(stmt, 14, vendor, -1, NULL);
946 if (r) {
947 ERROR(db->pakfire, "Could not bind vendor: %s\n", sqlite3_errmsg(db->handle));
948 goto ROLLBACK;
949 }
950
e49b93d1
MT
951 // Bind build_host
952 const char* buildhost = pakfire_package_get_buildhost(pkg);
953
954 r = sqlite3_bind_text(stmt, 16, buildhost, -1, NULL);
955 if (r) {
956 ERROR(db->pakfire, "Could not bind build_host: %s\n", sqlite3_errmsg(db->handle));
957 goto ROLLBACK;
958 }
959
960 // Bind build_time
961 unsigned long long build_time = pakfire_package_get_buildtime(pkg);
962
963 r = sqlite3_bind_int64(stmt, 17, build_time);
964 if (r) {
965 ERROR(db->pakfire, "Could not bind build_time: %s\n", sqlite3_errmsg(db->handle));
966 goto ROLLBACK;
967 }
968
969 // Bind repository name
970 PakfireRepo repo = pakfire_package_get_repo(pkg);
971 if (repo) {
972 const char* repo_name = pakfire_repo_get_name(repo);
973 pakfire_repo_unref(repo);
974
975 r = sqlite3_bind_text(stmt, 18, repo_name, -1, NULL);
976 if (r)
977 goto ROLLBACK;
978
979 // No repository?
980 } else {
981 r = sqlite3_bind_null(stmt, 18);
982 if (r)
983 goto ROLLBACK;
984 }
985
986 // XXX TODO Bind reason
987 r = sqlite3_bind_null(stmt, 19);
988 if (r)
989 goto ROLLBACK;
990
991 // Run query
992 do {
993 r = sqlite3_step(stmt);
994 } while (r == SQLITE_BUSY);
995
996 if (r != SQLITE_DONE) {
997 ERROR(db->pakfire, "Could not add package to database: %s\n",
998 sqlite3_errmsg(db->handle));
999 goto ROLLBACK;
1000 }
1001
f5c77233
MT
1002 // Save package ID
1003 unsigned long packages_id = sqlite3_last_insert_rowid(db->handle);
1004
e49b93d1 1005 // This is done
f5c77233
MT
1006 r = sqlite3_finalize(stmt);
1007 if (r == SQLITE_OK)
1008 stmt = NULL;
1009
1010 // Add files
1011 r = pakfire_db_add_files(db, packages_id, archive);
1012 if (r)
1013 goto ROLLBACK;
e49b93d1
MT
1014
1015 // All done, commit!
1016 r = pakfire_db_commit(db);
1017 if (r)
1018 goto ROLLBACK;
1019
1020 return 0;
1021
1022ROLLBACK:
f5c77233
MT
1023 if (stmt)
1024 sqlite3_finalize(stmt);
e49b93d1
MT
1025
1026 pakfire_db_rollback(db);
1027
1028 return 1;
eafbe2ce
MT
1029}
1030
18bf891d 1031PAKFIRE_EXPORT int pakfire_db_remove_package(struct pakfire_db* db, PakfirePackage pkg) {
eafbe2ce
MT
1032 return 0; // TODO
1033}