1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2013 Pakfire development team #
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. #
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. #
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/>. #
19 #############################################################################*/
24 #include <openssl/crypto.h>
25 #include <openssl/evp.h>
26 #include <solv/transaction.h>
28 #include <pakfire/archive.h>
29 #include <pakfire/db.h>
30 #include <pakfire/downloader.h>
31 #include <pakfire/execute.h>
32 #include <pakfire/file.h>
33 #include <pakfire/filelist.h>
34 #include <pakfire/i18n.h>
35 #include <pakfire/logging.h>
36 #include <pakfire/package.h>
37 #include <pakfire/pakfire.h>
38 #include <pakfire/private.h>
39 #include <pakfire/repo.h>
40 #include <pakfire/transaction.h>
41 #include <pakfire/ui.h>
42 #include <pakfire/util.h>
44 struct pakfire_transaction
{
45 struct pakfire
* pakfire
;
48 Transaction
* transaction
;
51 struct pakfire_archive
** archives
;
52 struct pakfire_package
** packages
;
56 enum pakfire_actions
{
57 PAKFIRE_ACTION_NOOP
= 0,
58 PAKFIRE_ACTION_VERIFY
,
59 PAKFIRE_ACTION_EXECUTE
,
60 PAKFIRE_ACTION_PRETRANS
,
61 PAKFIRE_ACTION_POSTTRANS
,
65 PAKFIRE_STEP_IGNORE
= 0,
67 PAKFIRE_STEP_REINSTALL
,
70 PAKFIRE_STEP_DOWNGRADE
,
71 PAKFIRE_STEP_OBSOLETE
,
74 static enum pakfire_steps
pakfire_transaction_get_step_type(
75 struct pakfire_transaction
* transaction
, struct pakfire_package
* pkg
) {
76 int type
= transaction_type(transaction
->transaction
, pakfire_package_id(pkg
),
77 SOLVER_TRANSACTION_SHOW_ACTIVE
|SOLVER_TRANSACTION_CHANGE_IS_REINSTALL
);
79 // Translate solver types into our own types
81 case SOLVER_TRANSACTION_INSTALL
:
82 case SOLVER_TRANSACTION_MULTIINSTALL
:
83 return PAKFIRE_STEP_INSTALL
;
85 case SOLVER_TRANSACTION_REINSTALL
:
86 case SOLVER_TRANSACTION_MULTIREINSTALL
:
87 return PAKFIRE_STEP_REINSTALL
;
89 case SOLVER_TRANSACTION_ERASE
:
90 return PAKFIRE_STEP_ERASE
;
92 case SOLVER_TRANSACTION_DOWNGRADE
:
93 return PAKFIRE_STEP_DOWNGRADE
;
95 case SOLVER_TRANSACTION_UPGRADE
:
96 return PAKFIRE_STEP_UPGRADE
;
98 case SOLVER_TRANSACTION_OBSOLETES
:
99 return PAKFIRE_STEP_OBSOLETE
;
101 // Anything we don't care about
102 case SOLVER_TRANSACTION_IGNORE
:
103 case SOLVER_TRANSACTION_REINSTALLED
:
104 case SOLVER_TRANSACTION_DOWNGRADED
:
106 return PAKFIRE_STEP_IGNORE
;
110 static void pakfire_transaction_free_archives_and_packages(
111 struct pakfire_transaction
* transaction
) {
112 if (transaction
->archives
) {
113 for (unsigned int i
= 0; i
< transaction
->num
; i
++)
114 if (transaction
->archives
[i
])
115 pakfire_archive_unref(transaction
->archives
[i
]);
116 free(transaction
->archives
);
118 transaction
->archives
= NULL
;
121 if (transaction
->packages
) {
122 for (unsigned int i
= 0; i
< transaction
->num
; i
++)
123 if (transaction
->packages
[i
])
124 pakfire_package_unref(transaction
->packages
[i
]);
125 free(transaction
->packages
);
127 transaction
->packages
= NULL
;
131 static void pakfire_transaction_free(struct pakfire_transaction
* transaction
) {
132 pakfire_transaction_free_archives_and_packages(transaction
);
134 if (transaction
->userinstalled
) {
135 for (char** userinstalled
= transaction
->userinstalled
; *userinstalled
; userinstalled
++)
136 free(*userinstalled
);
137 free(transaction
->userinstalled
);
139 transaction_free(transaction
->transaction
);
141 pakfire_unref(transaction
->pakfire
);
145 static int pakfire_transaction_import_transaction(
146 struct pakfire_transaction
* transaction
, Solver
* solver
) {
147 // Clone the transaction to keep a copy of it
148 Transaction
* t
= solver_create_transaction(solver
);
152 transaction
->transaction
= t
;
154 // Order the transaction
155 transaction_order(t
, 0);
157 // Free any previous content
158 pakfire_transaction_free_archives_and_packages(transaction
);
161 transaction
->num
= t
->steps
.count
;
163 // Allocate space for packages
164 transaction
->packages
= calloc(transaction
->num
, sizeof(*transaction
->packages
));
165 if (!transaction
->packages
)
168 // Allocate space for archives
169 transaction
->archives
= calloc(transaction
->num
, sizeof(*transaction
->archives
));
170 if (!transaction
->archives
)
173 // Create all packages
174 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
175 transaction
->packages
[i
] = pakfire_package_create_from_solvable(
176 transaction
->pakfire
, t
->steps
.elements
[i
]);
182 static int pakfire_transaction_import_userinstalled(
183 struct pakfire_transaction
* t
, Solver
* solver
) {
184 if (t
->userinstalled
) {
185 free(t
->userinstalled
);
186 t
->userinstalled
= NULL
;
190 queue_init(&userinstalled
);
192 // Fetch a list of all packages that are installed by the user
193 solver_get_userinstalled(solver
, &userinstalled
, GET_USERINSTALLED_NAMES
);
195 // Skip everything if the queue is empty
196 if (!userinstalled
.count
)
199 t
->userinstalled
= calloc(userinstalled
.count
+ 1, sizeof(*t
->userinstalled
));
200 if (!t
->userinstalled
) {
201 ERROR(t
->pakfire
, "Could not allocate userinstalled\n");
205 Pool
* pool
= pakfire_get_solv_pool(t
->pakfire
);
207 // Store the names of all userinstalled packages
208 for (int i
= 0; i
< userinstalled
.count
; i
++) {
209 const char* package
= pool_id2str(pool
, userinstalled
.elements
[i
]);
210 t
->userinstalled
[i
] = strdup(package
);
216 int pakfire_transaction_create(struct pakfire_transaction
** transaction
,
217 struct pakfire
* pakfire
, Solver
* solver
) {
218 struct pakfire_transaction
* t
= calloc(1, sizeof(*t
));
222 // Store reference to Pakfire
223 t
->pakfire
= pakfire_ref(pakfire
);
225 // Initialize the reference counter
228 // Import transaction
229 int r
= pakfire_transaction_import_transaction(t
, solver
);
233 // Import userinstalled
234 r
= pakfire_transaction_import_userinstalled(t
, solver
);
242 pakfire_transaction_free(t
);
246 PAKFIRE_EXPORT
struct pakfire_transaction
* pakfire_transaction_ref(
247 struct pakfire_transaction
* transaction
) {
248 transaction
->nrefs
++;
253 PAKFIRE_EXPORT
struct pakfire_transaction
* pakfire_transaction_unref(
254 struct pakfire_transaction
* transaction
) {
255 if (--transaction
->nrefs
> 0)
258 pakfire_transaction_free(transaction
);
262 PAKFIRE_EXPORT
size_t pakfire_transaction_count(struct pakfire_transaction
* transaction
) {
263 return transaction
->num
;
266 static ssize_t
pakfire_transaction_installsizechange(struct pakfire_transaction
* transaction
) {
267 ssize_t sizechange
= transaction_calc_installsizechange(transaction
->transaction
);
269 // Convert from kbytes to bytes
270 return sizechange
* 1024;
273 PAKFIRE_EXPORT ssize_t
pakfire_transaction_downloadsize(struct pakfire_transaction
* transaction
) {
276 for (unsigned int i
= 0; i
< transaction
->num
; i
++)
277 size
+= pakfire_package_get_downloadsize(transaction
->packages
[i
]);
282 static void pakfire_transaction_append_line(char*** lines
, const char* format
, ...) {
290 va_start(args
, format
);
291 r
= vasprintf(&buffer
, format
, args
);
298 unsigned int count
= 0;
300 for (char** l
= *lines
; *l
; l
++)
304 // Increase size of array
305 *lines
= reallocarray(*lines
, count
+ 2, sizeof(**lines
));
309 // Append line and terminate lines
310 (*lines
)[count
] = buffer
;
311 (*lines
)[count
+ 1] = NULL
;
314 static void pakfire_transaction_add_headline(char*** lines
, size_t width
, const char* headline
) {
315 pakfire_transaction_append_line(lines
, "%s\n", headline
);
318 static void pakfire_transaction_add_newline(char*** lines
, size_t width
) {
319 pakfire_transaction_append_line(lines
, "\n");
322 static void pakfire_transaction_add_line(char*** lines
, size_t width
, const char* name
,
323 const char* arch
, const char* version
, const char* repo
, const char* size
) {
324 pakfire_transaction_append_line(lines
, " %-21s %-8s %-21s %-18s %6s \n",
325 name
, arch
, version
, repo
, size
);
328 static void pakfire_transaction_add_package(char*** lines
, size_t width
, struct pakfire_package
* pkg
) {
331 struct pakfire_repo
* repo
= pakfire_package_get_repo(pkg
);
334 int r
= pakfire_format_size(size
, pakfire_package_get_size(pkg
));
338 pakfire_transaction_add_line(lines
, width
,
339 pakfire_package_get_name(pkg
),
340 pakfire_package_get_arch(pkg
),
341 pakfire_package_get_evr(pkg
),
342 pakfire_repo_get_name(repo
),
346 pakfire_repo_unref(repo
);
349 static void pakfire_transaction_add_package_change(char*** lines
, size_t width
,
350 struct pakfire_package
* old_pkg
, struct pakfire_package
* new_pkg
) {
351 // Print the new package first
352 pakfire_transaction_add_package(lines
, width
, new_pkg
);
354 pakfire_transaction_append_line(lines
,
355 " --> %s\n", pakfire_package_get_nevra(old_pkg
));
358 static void pakfire_transaction_add_separator(char*** lines
, size_t width
) {
359 char* separator
= alloca(width
+ 1);
361 for (unsigned int i
= 0; i
< width
; i
++)
363 separator
[width
] = '\0';
365 pakfire_transaction_append_line(lines
, "%s\n", separator
);
368 static void pakfire_transaction_add_usage_line(char*** lines
, size_t width
,
369 const char* headline
, ssize_t size
) {
372 int r
= pakfire_format_size(buffer
, size
);
376 pakfire_transaction_append_line(lines
, "%-21s: %s\n", headline
, buffer
);
379 static char* pakfire_transaction_join_lines(char** lines
) {
385 // Determine total length
386 for (char** line
= lines
; *line
; line
++)
387 size
+= strlen(*line
);
389 // Allocate memory large enough to hold the result
390 char* s
= calloc(1, size
+ 1);
396 for (char** line
= lines
; *line
; line
++) {
397 p
+= snprintf(p
, s
- p
- 1, "%s", *line
);
403 PAKFIRE_EXPORT
char* pakfire_transaction_dump(struct pakfire_transaction
* transaction
, size_t width
) {
406 Pool
* pool
= transaction
->transaction
->pool
;
408 SOLVER_TRANSACTION_SHOW_OBSOLETES
|
409 SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE
;
414 pakfire_transaction_add_separator(&lines
, width
);
415 pakfire_transaction_add_line(&lines
, width
,
422 pakfire_transaction_add_separator(&lines
, width
);
425 queue_init(&classes
);
428 transaction_classify(transaction
->transaction
, mode
, &classes
);
434 The classes queue now contains a list of all classes as a tuple of:
436 * The number of packages in this class
437 * The from ID (for arch/vendor change)
438 * The to ID (for arch/vendor change)
440 for (int i
= 0; i
< classes
.count
; i
+= 4) {
441 Id
class = classes
.elements
[i
];
442 unsigned int count
= classes
.elements
[i
+1];
444 const char* from
= pool_id2str(pool
, classes
.elements
[i
+2]);
445 const char* to
= pool_id2str(pool
, classes
.elements
[i
+3]);
448 case SOLVER_TRANSACTION_INSTALL
:
450 pakfire_string_format(headline
, _("Installing %u packages:"), count
);
452 pakfire_string_set(headline
, _("Installing one package:"));
455 case SOLVER_TRANSACTION_REINSTALLED
:
457 pakfire_string_format(headline
, _("Reinstalling %u packages:"), count
);
459 pakfire_string_set(headline
, _("Reinstalling one package:"));
462 case SOLVER_TRANSACTION_ERASE
:
464 pakfire_string_format(headline
, _("Removing %u packages:"), count
);
466 pakfire_string_set(headline
, _("Removing one package:"));
469 case SOLVER_TRANSACTION_UPGRADED
:
471 pakfire_string_format(headline
, _("Updating %u packages:"), count
);
473 pakfire_string_set(headline
, _("Updating one package:"));
476 case SOLVER_TRANSACTION_DOWNGRADED
:
478 pakfire_string_format(headline
, _("Downgrading %u packages:"), count
);
480 pakfire_string_set(headline
, _("Downgrading one package:"));
483 case SOLVER_TRANSACTION_CHANGED
:
485 pakfire_string_format(headline
, _("Changing %u packages:"), count
);
487 pakfire_string_set(headline
, _("Changing one package:"));
490 case SOLVER_TRANSACTION_ARCHCHANGE
:
492 pakfire_string_format(headline
,
493 _("%u architecture changes from '%s' to '%s':"), count
, from
, to
);
495 pakfire_string_format(headline
,
496 _("One architecture change from '%s' to '%s':"), from
, to
);
499 case SOLVER_TRANSACTION_VENDORCHANGE
:
501 pakfire_string_format(headline
,
502 _("%u vendor changes from '%s' to '%s':"), count
, from
, to
);
504 pakfire_string_format(headline
,
505 _("One vendor change from '%s' to '%s':"), from
, to
);
508 case SOLVER_TRANSACTION_IGNORE
:
512 // Show what we are doing
513 pakfire_transaction_add_headline(&lines
, width
, headline
);
515 // Fetch packages in this class
516 transaction_classify_pkgs(transaction
->transaction
, mode
, class,
517 classes
.elements
[i
+2], classes
.elements
[i
+3], &pkgs
);
520 for (int j
= 0; j
< pkgs
.count
; j
++) {
521 struct pakfire_package
* old_pkg
= pakfire_package_create_from_solvable(
522 transaction
->pakfire
, pkgs
.elements
[j
]);
523 struct pakfire_package
* new_pkg
= NULL
;
526 case SOLVER_TRANSACTION_UPGRADED
:
527 case SOLVER_TRANSACTION_DOWNGRADED
:
528 new_pkg
= pakfire_package_create_from_solvable(transaction
->pakfire
,
529 transaction_obs_pkg(transaction
->transaction
, pkgs
.elements
[j
]));
531 pakfire_transaction_add_package_change(&lines
, width
, old_pkg
, new_pkg
);
535 pakfire_transaction_add_package(&lines
, width
, old_pkg
);
539 pakfire_package_unref(old_pkg
);
541 pakfire_package_unref(new_pkg
);
545 pakfire_transaction_add_newline(&lines
, width
);
548 queue_free(&classes
);
552 pakfire_transaction_add_headline(&lines
, width
, _("Transaction Summary"));
553 pakfire_transaction_add_separator(&lines
, width
);
555 // How much do we need to download?
556 size_t downloadsize
= pakfire_transaction_downloadsize(transaction
);
558 if (downloadsize
> 0)
559 pakfire_transaction_add_usage_line(&lines
, width
,
560 _("Total Download Size"), downloadsize
);
562 // How much more space do we need?
563 ssize_t sizechange
= pakfire_transaction_installsizechange(transaction
);
564 pakfire_transaction_add_usage_line(&lines
, width
,
565 (sizechange
>= 0) ? _("Installed Size") : _("Freed Size"), sizechange
);
567 // Join all lines together
568 char* string
= pakfire_transaction_join_lines(lines
);
570 DEBUG(transaction
->pakfire
, "Transaction: %s\n", string
);
574 for (char** line
= lines
; *line
; line
++)
582 static int pakfire_transaction_verify(struct pakfire_transaction
* transaction
,
583 struct pakfire_package
* pkg
, struct pakfire_archive
* archive
) {
586 const char* nevra
= pakfire_package_get_nevra(pkg
);
588 // Nothing to do if this step does not have an archive
590 DEBUG(transaction
->pakfire
, "Package %s requires no archive\n", nevra
);
594 enum pakfire_digests digest_type
= PAKFIRE_DIGEST_NONE
;
596 // Fetch digest from package
597 const unsigned char* expected_digest
= pakfire_package_get_digest(pkg
, &digest_type
);
598 if (!expected_digest
) {
599 DEBUG(transaction
->pakfire
, "Package %s has no digest\n", nevra
);
603 unsigned char computed_digest
[EVP_MAX_MD_SIZE
];
604 size_t digest_length
= 0;
606 // Compute digest of the archive
607 r
= pakfire_archive_digest(archive
, digest_type
, computed_digest
, &digest_length
);
609 ERROR(transaction
->pakfire
, "Could not compute digest for %s: %m\n", nevra
);
614 r
= CRYPTO_memcmp(computed_digest
, expected_digest
, digest_length
);
616 ERROR(transaction
->pakfire
, "Digests of %s do not match\n", nevra
);
623 static int pakfire_transaction_run_script(struct pakfire_transaction
* transaction
,
624 struct pakfire_db
* db
, const char* type
, struct pakfire_package
* pkg
, struct pakfire_archive
* archive
) {
625 struct pakfire_scriptlet
* scriptlet
= NULL
;
627 // Fetch scriptlet from archive if possible
629 scriptlet
= pakfire_archive_get_scriptlet(archive
, type
);
631 scriptlet
= pakfire_db_get_scriptlet(db
, pkg
, type
);
633 // Nothing to do if there are no scriptlets
637 // Execute the scriptlet
638 pakfire_scriptlet_execute(scriptlet
);
640 pakfire_scriptlet_unref(scriptlet
);
645 static int pakfire_transaction_extract(struct pakfire_transaction
* transaction
,
646 struct pakfire_package
* pkg
, struct pakfire_archive
* archive
) {
647 // Extract payload to the root of the Pakfire instance
648 int r
= pakfire_archive_extract(archive
, NULL
);
650 ERROR(transaction
->pakfire
, "Could not extract package %s: %m\n",
651 pakfire_package_get_nevra(pkg
));
655 // Is it necessary to call ldconfig?
656 struct pakfire_filelist
* filelist
= pakfire_archive_get_filelist(archive
);
658 int need_ldconfig
= pakfire_filelist_contains(filelist
, "*/lib*.so.?");
660 // Update the runtime linker cache
662 pakfire_execute_ldconfig(transaction
->pakfire
);
664 pakfire_filelist_unref(filelist
);
670 static int pakfire_transaction_erase(struct pakfire_transaction
* transaction
,
671 struct pakfire_db
* db
, struct pakfire_package
* pkg
) {
672 struct pakfire_filelist
* filelist
= NULL
;
676 r
= pakfire_db_package_filelist(db
, &filelist
, pkg
);
680 const size_t length
= pakfire_filelist_size(filelist
);
683 for (unsigned int i
= 0; i
< length
; i
++) {
684 struct pakfire_file
* file
= pakfire_filelist_get(filelist
, i
);
687 r
= pakfire_file_remove(file
);
688 pakfire_file_unref(file
);
690 // Break on any errors
695 // Update the runtime linker cache after all files have been removed
696 pakfire_execute_ldconfig(transaction
->pakfire
);
700 pakfire_filelist_unref(filelist
);
705 static const char* pakfire_action_type_string(enum pakfire_actions type
) {
707 case PAKFIRE_ACTION_NOOP
:
710 case PAKFIRE_ACTION_VERIFY
:
713 case PAKFIRE_ACTION_EXECUTE
:
716 case PAKFIRE_ACTION_PRETRANS
:
719 case PAKFIRE_ACTION_POSTTRANS
:
726 static int pakfire_transaction_package_is_userinstalled(
727 struct pakfire_transaction
* transaction
, struct pakfire_package
* pkg
) {
728 // No packages on the list
729 if (!transaction
->userinstalled
)
732 const char* name
= pakfire_package_get_name(pkg
);
734 // Check if the package is on the list
735 for (char** elem
= transaction
->userinstalled
; *elem
; elem
++) {
736 if (strcmp(name
, *elem
) == 0)
744 static int pakfire_transaction_run_step(struct pakfire_transaction
* transaction
,
745 struct pakfire_db
* db
, const enum pakfire_actions action
, struct pakfire_package
* pkg
, struct pakfire_archive
* archive
) {
751 DEBUG(transaction
->pakfire
, "Running %s for %s\n",
752 pakfire_action_type_string(action
), pakfire_package_get_nevra(pkg
));
754 enum pakfire_steps type
= pakfire_transaction_get_step_type(transaction
, pkg
);
759 case PAKFIRE_ACTION_VERIFY
:
760 r
= pakfire_transaction_verify(transaction
, pkg
, archive
);
763 // Run the pre-transaction scripts
764 case PAKFIRE_ACTION_PRETRANS
:
766 case PAKFIRE_STEP_INSTALL
:
767 case PAKFIRE_STEP_REINSTALL
:
768 r
= pakfire_transaction_run_script(transaction
, db
,
769 "pretransin", pkg
, archive
);
772 case PAKFIRE_STEP_UPGRADE
:
773 case PAKFIRE_STEP_DOWNGRADE
:
774 r
= pakfire_transaction_run_script(transaction
, db
,
775 "pretransup", pkg
, archive
);
778 case PAKFIRE_STEP_ERASE
:
779 case PAKFIRE_STEP_OBSOLETE
:
780 r
= pakfire_transaction_run_script(transaction
, db
,
781 "pretransun", pkg
, archive
);
784 case PAKFIRE_STEP_IGNORE
:
789 // Run the post-transaction scripts
790 case PAKFIRE_ACTION_POSTTRANS
:
792 case PAKFIRE_STEP_INSTALL
:
793 case PAKFIRE_STEP_REINSTALL
:
794 r
= pakfire_transaction_run_script(transaction
, db
,
795 "posttransin", pkg
, archive
);
798 case PAKFIRE_STEP_UPGRADE
:
799 case PAKFIRE_STEP_DOWNGRADE
:
800 r
= pakfire_transaction_run_script(transaction
, db
,
801 "posttransup", pkg
, archive
);
804 case PAKFIRE_STEP_ERASE
:
805 case PAKFIRE_STEP_OBSOLETE
:
806 r
= pakfire_transaction_run_script(transaction
, db
,
807 "posttransun", pkg
, archive
);
810 case PAKFIRE_STEP_IGNORE
:
815 // Execute the action of this script
816 case PAKFIRE_ACTION_EXECUTE
:
818 case PAKFIRE_STEP_INSTALL
:
819 case PAKFIRE_STEP_REINSTALL
:
820 r
= pakfire_transaction_run_script(transaction
, db
,
821 "prein", pkg
, archive
);
825 r
= pakfire_transaction_extract(transaction
, pkg
, archive
);
829 // Remove package metadata first when reinstalling
830 if (type
== PAKFIRE_STEP_REINSTALL
) {
831 r
= pakfire_db_remove_package(db
, pkg
);
836 r
= pakfire_db_add_package(db
, pkg
, archive
,
837 pakfire_transaction_package_is_userinstalled(transaction
, pkg
));
841 r
= pakfire_transaction_run_script(transaction
, db
,
842 "postin", pkg
, archive
);
845 case PAKFIRE_STEP_UPGRADE
:
846 case PAKFIRE_STEP_DOWNGRADE
:
847 r
= pakfire_transaction_run_script(transaction
, db
,
848 "preup", pkg
, archive
);
852 r
= pakfire_transaction_extract(transaction
, pkg
, archive
);
856 r
= pakfire_db_add_package(db
, pkg
, archive
,
857 pakfire_transaction_package_is_userinstalled(transaction
, pkg
));
861 r
= pakfire_transaction_run_script(transaction
, db
,
862 "postup", pkg
, archive
);
865 case PAKFIRE_STEP_ERASE
:
866 case PAKFIRE_STEP_OBSOLETE
:
867 r
= pakfire_transaction_run_script(transaction
, db
,
868 "preun", pkg
, archive
);
872 r
= pakfire_transaction_erase(transaction
, db
, pkg
);
876 r
= pakfire_db_remove_package(db
, pkg
);
880 r
= pakfire_transaction_run_script(transaction
, db
,
881 "postun", pkg
, archive
);
884 case PAKFIRE_STEP_IGNORE
:
890 case PAKFIRE_ACTION_NOOP
:
895 ERROR(transaction
->pakfire
, "Step has failed: %s\n", strerror(r
));
900 static int pakfire_transaction_run_steps(struct pakfire_transaction
* transaction
,
901 struct pakfire_db
* db
, enum pakfire_actions action
) {
904 // Walk through all steps
905 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
906 r
= pakfire_transaction_run_step(transaction
, db
, action
,
907 transaction
->packages
[i
], transaction
->archives
[i
]);
909 // End loop if action was unsuccessful
911 DEBUG(transaction
->pakfire
, "Step %d failed: %m\n", i
);
919 static int pakfire_transaction_open_archives(struct pakfire_transaction
* transaction
) {
920 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
921 struct pakfire_package
* pkg
= transaction
->packages
[i
];
924 enum pakfire_steps type
= pakfire_transaction_get_step_type(transaction
, pkg
);
926 // Do we need the archive?
928 case PAKFIRE_STEP_INSTALL
:
929 case PAKFIRE_STEP_REINSTALL
:
930 case PAKFIRE_STEP_UPGRADE
:
931 case PAKFIRE_STEP_DOWNGRADE
:
932 case PAKFIRE_STEP_OBSOLETE
:
935 case PAKFIRE_STEP_ERASE
:
936 case PAKFIRE_STEP_IGNORE
:
940 transaction
->archives
[i
] = pakfire_package_get_archive(pkg
);
941 if (!transaction
->archives
[i
]) {
942 ERROR(transaction
->pakfire
, "Could not open archive for %s: %m\n",
943 pakfire_package_get_nevra(pkg
));
951 static int pakfire_transaction_perform(struct pakfire_transaction
* transaction
) {
952 struct pakfire_repo
* repo
= NULL
;
953 struct pakfire_db
* db
;
956 DEBUG(transaction
->pakfire
, "Running Transaction %p\n", transaction
);
959 r
= pakfire_transaction_open_archives(transaction
);
964 r
= pakfire_db_open(&db
, transaction
->pakfire
, PAKFIRE_DB_READWRITE
);
966 ERROR(transaction
->pakfire
, "Could not open the database\n");
971 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_VERIFY
);
975 // Execute all pre transaction actions
976 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_PRETRANS
);
980 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_EXECUTE
);
984 // Execute all post transaction actions
985 r
= pakfire_transaction_run_steps(transaction
, db
, PAKFIRE_ACTION_POSTTRANS
);
989 DEBUG(transaction
->pakfire
, "The transaction has finished successfully\n");
991 // Reload database for next transaction
993 repo
= pakfire_get_installed_repo(transaction
->pakfire
);
997 // Reload the database
998 r
= pakfire_db_load(db
, repo
);
1002 pakfire_repo_unref(repo
);
1003 pakfire_db_unref(db
);
1008 static int pakfire_transaction_download_package(struct pakfire_transaction
* transaction
,
1009 struct pakfire_downloader
* downloader
, struct pakfire_package
* pkg
) {
1011 struct pakfire_repo
* repo
= NULL
;
1012 struct pakfire_mirrorlist
* mirrorlist
= NULL
;
1014 // Fetch the repository to download from
1015 repo
= pakfire_package_get_repo(pkg
);
1020 const char* baseurl
= pakfire_repo_get_baseurl(repo
);
1023 mirrorlist
= pakfire_repo_get_mirrorlist(repo
);
1025 const char* nevra
= pakfire_package_get_nevra(pkg
);
1029 // Where to store the package?
1030 const char* path
= pakfire_package_get_path(pkg
);
1032 ERROR(transaction
->pakfire
, "Could not retrieve package path for %s: %m\n", nevra
);
1036 // What file to download?
1037 const char* filename
= pakfire_package_get_filename(pkg
);
1039 ERROR(transaction
->pakfire
, "Could not retrieve filename for package %s: %m\n", nevra
);
1043 enum pakfire_digests digest_type
= PAKFIRE_DIGEST_NONE
;
1045 // Retrieve package digest
1046 const unsigned char* digest
= pakfire_package_get_digest(pkg
, &digest_type
);
1047 const size_t digest_length
= pakfire_digest_length(digest_type
);
1049 // Add transfer to downloader
1050 r
= pakfire_downloader_add_transfer(downloader
, baseurl
, mirrorlist
,
1051 nevra
, filename
, path
, digest_type
, digest
, digest_length
, 0);
1055 pakfire_mirrorlist_unref(mirrorlist
);
1057 pakfire_repo_unref(repo
);
1062 static int pakfire_transaction_package_needs_download(
1063 struct pakfire_transaction
* transaction
, struct pakfire_package
* pkg
) {
1064 enum pakfire_steps type
= pakfire_transaction_get_step_type(transaction
, pkg
);
1066 case PAKFIRE_STEP_INSTALL
:
1067 case PAKFIRE_STEP_REINSTALL
:
1068 case PAKFIRE_STEP_DOWNGRADE
:
1069 case PAKFIRE_STEP_UPGRADE
:
1072 // No need to download for these steps
1077 // No download required if this package is already installed
1078 if (pakfire_package_is_installed(pkg
))
1081 const char* path
= pakfire_package_get_path(pkg
);
1083 // Does the file exist?
1084 int r
= access(path
, R_OK
);
1088 // This package needs to be downloaded
1092 PAKFIRE_EXPORT
int pakfire_transaction_download(struct pakfire_transaction
* transaction
) {
1093 struct pakfire_downloader
* downloader
;
1096 // Initialize the downloader
1097 r
= pakfire_downloader_create(&downloader
, transaction
->pakfire
);
1099 ERROR(transaction
->pakfire
, "Could not initialize downloader: %m\n");
1103 // Add all packages that need to be downloaded
1104 for (unsigned int i
= 0; i
< transaction
->num
; i
++) {
1105 struct pakfire_package
* pkg
= transaction
->packages
[i
];
1107 if (!pakfire_transaction_package_needs_download(transaction
, pkg
))
1111 r
= pakfire_transaction_download_package(transaction
, downloader
, pkg
);
1113 const char* nevra
= pakfire_package_get_nevra(pkg
);
1115 ERROR(transaction
->pakfire
, "Could not add download to queue: %s: %m\n", nevra
);
1120 // Run the downloader
1121 r
= pakfire_downloader_run(downloader
);
1124 pakfire_downloader_unref(downloader
);
1129 PAKFIRE_EXPORT
int pakfire_transaction_run(struct pakfire_transaction
* transaction
) {
1132 // Skip running an empty transaction
1133 if (!transaction
->num
) {
1134 DEBUG(transaction
->pakfire
, "Empty transaction. Skipping...\n");
1138 // Show what would be done
1139 char* dump
= pakfire_transaction_dump(transaction
, 80);
1141 // Check if we should continue
1142 r
= pakfire_ui_confirm(transaction
->pakfire
, dump
, _("Is this okay? [y/N]"));
1144 ERROR(transaction
->pakfire
, "Transaction aborted upon user request\n");
1148 // Write transaction dump to log
1149 INFO(transaction
->pakfire
, "%s\n", dump
);
1151 // Download what we need
1152 r
= pakfire_transaction_download(transaction
);
1156 // Perform all steps
1157 r
= pakfire_transaction_perform(transaction
);