4 * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
5 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/types.h>
31 #include <inttypes.h> /* int64_t */
32 #include <stdint.h> /* intmax_t */
36 #include <archive_entry.h>
40 #include "alpm_list.h"
52 /** Add a file target to the transaction.
53 * @param target the name of the file target to add
54 * @return 0 on success, -1 on error (pm_errno is set accordingly)
56 int SYMEXPORT
alpm_add_target(const char *target
)
59 const char *pkgname
, *pkgver
;
66 ASSERT(target
!= NULL
&& strlen(target
) != 0, RET_ERR(PM_ERR_WRONG_ARGS
, -1));
67 ASSERT(handle
!= NULL
, RET_ERR(PM_ERR_HANDLE_NULL
, -1));
68 trans
= handle
->trans
;
69 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
70 ASSERT(trans
->state
== STATE_INITIALIZED
, RET_ERR(PM_ERR_TRANS_NOT_INITIALIZED
, -1));
71 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
73 _alpm_log(PM_LOG_DEBUG
, "loading target '%s'\n", target
);
75 if(alpm_pkg_load(target
, 1, &pkg
) != 0) {
78 pkgname
= alpm_pkg_get_name(pkg
);
79 pkgver
= alpm_pkg_get_version(pkg
);
81 /* check if an older version of said package is already in transaction
82 * packages. if so, replace it in the list */
83 for(i
= trans
->add
; i
; i
= i
->next
) {
84 pmpkg_t
*transpkg
= i
->data
;
85 if(strcmp(transpkg
->name
, pkgname
) == 0) {
86 if(alpm_pkg_vercmp(transpkg
->version
, pkgver
) < 0) {
87 _alpm_log(PM_LOG_WARNING
,
88 _("replacing older version %s-%s by %s in target list\n"),
89 transpkg
->name
, transpkg
->version
, pkgver
);
90 _alpm_pkg_free(i
->data
);
93 _alpm_log(PM_LOG_WARNING
,
94 _("skipping %s-%s because newer version %s is in target list\n"),
95 pkgname
, pkgver
, transpkg
->version
);
102 /* add the package to the transaction */
103 trans
->add
= alpm_list_add(trans
->add
, pkg
);
112 static int perform_extraction(struct archive
*archive
,
113 struct archive_entry
*entry
, const char *filename
, const char *origname
)
116 const int archive_flags
= ARCHIVE_EXTRACT_OWNER
|
117 ARCHIVE_EXTRACT_PERM
|
118 ARCHIVE_EXTRACT_TIME
;
120 archive_entry_set_pathname(entry
, filename
);
122 ret
= archive_read_extract(archive
, entry
, archive_flags
);
123 if(ret
== ARCHIVE_WARN
&& archive_errno(archive
) != ENOSPC
) {
124 /* operation succeeded but a "non-critical" error was encountered */
125 _alpm_log(PM_LOG_WARNING
, _("warning given when extracting %s (%s)\n"),
126 origname
, archive_error_string(archive
));
127 } else if(ret
!= ARCHIVE_OK
) {
128 _alpm_log(PM_LOG_ERROR
, _("could not extract %s (%s)\n"),
129 origname
, archive_error_string(archive
));
130 alpm_logaction("error: could not extract %s (%s)\n",
131 origname
, archive_error_string(archive
));
137 static int extract_single_file(struct archive
*archive
,
138 struct archive_entry
*entry
, pmpkg_t
*newpkg
, pmpkg_t
*oldpkg
,
139 pmtrans_t
*trans
, pmdb_t
*db
)
141 const char *entryname
;
143 char filename
[PATH_MAX
]; /* the actual file we're extracting */
144 int needbackup
= 0, notouch
= 0;
145 char *hash_orig
= NULL
;
146 char *entryname_orig
= NULL
;
149 entryname
= archive_entry_pathname(entry
);
150 entrymode
= archive_entry_mode(entry
);
152 memset(filename
, 0, PATH_MAX
); /* just to be sure */
154 if(strcmp(entryname
, ".INSTALL") == 0) {
155 /* the install script goes inside the db */
156 snprintf(filename
, PATH_MAX
, "%s%s-%s/install",
157 _alpm_db_path(db
), newpkg
->name
, newpkg
->version
);
158 archive_entry_set_perm(entry
, 0644);
159 } else if(strcmp(entryname
, ".CHANGELOG") == 0) {
160 /* the changelog goes inside the db */
161 snprintf(filename
, PATH_MAX
, "%s%s-%s/changelog",
162 _alpm_db_path(db
), newpkg
->name
, newpkg
->version
);
163 archive_entry_set_perm(entry
, 0644);
164 } else if(*entryname
== '.') {
165 /* for now, ignore all files starting with '.' that haven't
166 * already been handled (for future possibilities) */
167 _alpm_log(PM_LOG_DEBUG
, "skipping extraction of '%s'\n", entryname
);
168 archive_read_data_skip(archive
);
171 /* build the new entryname relative to handle->root */
172 snprintf(filename
, PATH_MAX
, "%s%s", handle
->root
, entryname
);
175 /* if a file is in NoExtract then we never extract it */
176 if(alpm_list_find_str(handle
->noextract
, entryname
)) {
177 _alpm_log(PM_LOG_DEBUG
, "%s is in NoExtract, skipping extraction\n",
179 alpm_logaction("note: %s is in NoExtract, skipping extraction\n",
181 archive_read_data_skip(archive
);
185 /* if a file is in the add skiplist we never extract it */
186 if(alpm_list_find_str(trans
->skip_add
, filename
)) {
187 _alpm_log(PM_LOG_DEBUG
, "%s is in trans->skip_add, skipping extraction\n",
189 archive_read_data_skip(archive
);
193 /* Check for file existence. This is one of the more crucial parts
194 * to get 'right'. Here are the possibilities, with the filesystem
195 * on the left and the package on the top:
196 * (F=file, N=node, S=symlink, D=dir)
198 * non-existent | 1 | 2 | 3
203 * 1,2,3- extract, no magic necessary. lstat (_alpm_lstat) will fail here.
204 * 4,5,6,7,8- conflict checks should have caught this. either overwrite
205 * or backup the file.
206 * 9- follow the symlink, hopefully it is a directory, check it.
207 * 10- file replacing directory- don't allow it.
208 * 11- don't extract symlink- a dir exists here. we don't want links to
210 * 12- skip extraction, dir already exists.
213 /* do both a lstat and a stat, so we can see what symlinks point to */
214 struct stat lsbuf
, sbuf
;
215 if(_alpm_lstat(filename
, &lsbuf
) != 0 || stat(filename
, &sbuf
) != 0) {
216 /* cases 1,2,3: couldn't stat an existing file, skip all backup checks */
218 if(S_ISDIR(lsbuf
.st_mode
)) {
219 if(S_ISDIR(entrymode
)) {
220 /* case 12: existing dir, ignore it */
221 if(lsbuf
.st_mode
!= entrymode
) {
222 /* if filesystem perms are different than pkg perms, warn user */
224 _alpm_log(PM_LOG_WARNING
, _("directory permissions differ on %s\n"
225 "filesystem: %o package: %o\n"), entryname
, lsbuf
.st_mode
& mask
,
227 alpm_logaction("warning: directory permissions differ on %s\n"
228 "filesystem: %o package: %o\n", entryname
, lsbuf
.st_mode
& mask
,
231 _alpm_log(PM_LOG_DEBUG
, "extract: skipping dir extraction of %s\n",
233 archive_read_data_skip(archive
);
236 /* case 10/11: trying to overwrite dir with file/symlink, don't allow it */
237 _alpm_log(PM_LOG_ERROR
, _("extract: not overwriting dir with file %s\n"),
239 archive_read_data_skip(archive
);
242 } else if(S_ISLNK(lsbuf
.st_mode
) && S_ISDIR(entrymode
)) {
243 /* case 9: existing symlink, dir in package */
244 if(S_ISDIR(sbuf
.st_mode
)) {
245 /* the symlink on FS is to a directory, so we'll use it */
246 _alpm_log(PM_LOG_DEBUG
, "extract: skipping symlink overwrite of %s\n",
248 archive_read_data_skip(archive
);
251 /* this is BAD. symlink was not to a directory */
252 _alpm_log(PM_LOG_ERROR
, _("extract: symlink %s does not point to dir\n"),
254 archive_read_data_skip(archive
);
257 } else if(S_ISREG(lsbuf
.st_mode
) && S_ISDIR(entrymode
)) {
258 /* case 6: trying to overwrite file with dir */
259 _alpm_log(PM_LOG_DEBUG
, "extract: overwriting file with dir %s\n",
261 } else if(S_ISREG(entrymode
)) {
263 /* if file is in NoUpgrade, don't touch it */
264 if(alpm_list_find_str(handle
->noupgrade
, entryname
)) {
267 /* go to the backup array and see if our conflict is there */
268 /* check newpkg first, so that adding backup files is retroactive */
269 if(alpm_list_find_str(alpm_pkg_get_backup(newpkg
), entryname
) != NULL
) {
273 /* check oldpkg for a backup entry, store the hash if available */
275 hash_orig
= _alpm_needbackup(entryname
, alpm_pkg_get_backup(oldpkg
));
281 /* if we force hash_orig to be non-NULL retroactive backup works */
282 if(needbackup
&& !hash_orig
) {
283 STRDUP(hash_orig
, "", RET_ERR(PM_ERR_MEMORY
, -1));
287 /* else if(S_ISLNK(entrymode)) */
288 /* case 5,8: don't need to do anything special */
291 /* we need access to the original entryname later after calls to
292 * archive_entry_set_pathname(), so we need to dupe it and free() later */
293 STRDUP(entryname_orig
, entryname
, RET_ERR(PM_ERR_MEMORY
, -1));
296 char checkfile
[PATH_MAX
];
297 char *hash_local
= NULL
, *hash_pkg
= NULL
;
300 snprintf(checkfile
, PATH_MAX
, "%s.paccheck", filename
);
302 ret
= perform_extraction(archive
, entry
, checkfile
, entryname_orig
);
306 FREE(entryname_orig
);
310 hash_local
= alpm_compute_md5sum(filename
);
311 hash_pkg
= alpm_compute_md5sum(checkfile
);
313 /* append the new md5 hash to it's respective entry
314 * in newpkg's backup (it will be the new orginal) */
315 alpm_list_t
*backups
;
316 for(backups
= alpm_pkg_get_backup(newpkg
); backups
;
317 backups
= alpm_list_next(backups
)) {
318 char *oldbackup
= alpm_list_getdata(backups
);
319 if(!oldbackup
|| strcmp(oldbackup
, entryname_orig
) != 0) {
323 /* length is tab char, null byte and MD5 (32 char) */
324 size_t backup_len
= strlen(oldbackup
) + 34;
325 MALLOC(backup
, backup_len
, RET_ERR(PM_ERR_MEMORY
, -1));
327 sprintf(backup
, "%s\t%s", oldbackup
, hash_pkg
);
328 backup
[backup_len
-1] = '\0';
330 backups
->data
= backup
;
333 _alpm_log(PM_LOG_DEBUG
, "checking hashes for %s\n", entryname_orig
);
334 _alpm_log(PM_LOG_DEBUG
, "current: %s\n", hash_local
);
335 _alpm_log(PM_LOG_DEBUG
, "new: %s\n", hash_pkg
);
336 _alpm_log(PM_LOG_DEBUG
, "original: %s\n", hash_orig
);
339 if(strcmp(hash_local
, hash_pkg
) != 0) {
340 /* looks like we have a local file that has a different hash as the
341 * file in the package, move it to a .pacorig */
342 char newpath
[PATH_MAX
];
343 snprintf(newpath
, PATH_MAX
, "%s.pacorig", filename
);
345 /* move the existing file to the "pacorig" */
346 if(rename(filename
, newpath
)) {
347 _alpm_log(PM_LOG_ERROR
, _("could not rename %s to %s (%s)\n"),
348 filename
, newpath
, strerror(errno
));
349 alpm_logaction("error: could not rename %s to %s (%s)\n",
350 filename
, newpath
, strerror(errno
));
353 /* rename the file we extracted to the real name */
354 if(rename(checkfile
, filename
)) {
355 _alpm_log(PM_LOG_ERROR
, _("could not rename %s to %s (%s)\n"),
356 checkfile
, filename
, strerror(errno
));
357 alpm_logaction("error: could not rename %s to %s (%s)\n",
358 checkfile
, filename
, strerror(errno
));
361 _alpm_log(PM_LOG_WARNING
, _("%s saved as %s\n"), filename
, newpath
);
362 alpm_logaction("warning: %s saved as %s\n", filename
, newpath
);
366 /* local file is identical to pkg one, so just remove pkg one */
369 } else if(hash_orig
) {
372 if(strcmp(hash_orig
, hash_local
) == 0) {
373 /* installed file has NOT been changed by user */
374 if(strcmp(hash_orig
, hash_pkg
) != 0) {
375 _alpm_log(PM_LOG_DEBUG
, "action: installing new file: %s\n",
378 if(rename(checkfile
, filename
)) {
379 _alpm_log(PM_LOG_ERROR
, _("could not rename %s to %s (%s)\n"),
380 checkfile
, filename
, strerror(errno
));
381 alpm_logaction("error: could not rename %s to %s (%s)\n",
382 checkfile
, filename
, strerror(errno
));
386 /* there's no sense in installing the same file twice, install
387 * ONLY is the original and package hashes differ */
388 _alpm_log(PM_LOG_DEBUG
, "action: leaving existing file in place\n");
391 } else if(strcmp(hash_orig
, hash_pkg
) == 0) {
392 /* originally installed file and new file are the same - this
393 * implies the case above failed - i.e. the file was changed by a
395 _alpm_log(PM_LOG_DEBUG
, "action: leaving existing file in place\n");
397 } else if(strcmp(hash_local
, hash_pkg
) == 0) {
398 /* this would be magical. The above two cases failed, but the
399 * user changes just so happened to make the new file exactly the
400 * same as the one in the package... skip it */
401 _alpm_log(PM_LOG_DEBUG
, "action: leaving existing file in place\n");
404 char newpath
[PATH_MAX
];
405 _alpm_log(PM_LOG_DEBUG
, "action: keeping current file and installing"
406 " new one with .pacnew ending\n");
407 snprintf(newpath
, PATH_MAX
, "%s.pacnew", filename
);
408 if(rename(checkfile
, newpath
)) {
409 _alpm_log(PM_LOG_ERROR
, _("could not install %s as %s (%s)\n"),
410 filename
, newpath
, strerror(errno
));
411 alpm_logaction("error: could not install %s as %s (%s)\n",
412 filename
, newpath
, strerror(errno
));
414 _alpm_log(PM_LOG_WARNING
, _("%s installed as %s\n"),
416 alpm_logaction("warning: %s installed as %s\n",
428 /* we didn't need a backup */
430 /* change the path to a .pacnew extension */
431 _alpm_log(PM_LOG_DEBUG
, "%s is in NoUpgrade -- skipping\n", filename
);
432 _alpm_log(PM_LOG_WARNING
, _("extracting %s as %s.pacnew\n"), filename
, filename
);
433 alpm_logaction("warning: extracting %s as %s.pacnew\n", filename
, filename
);
434 strncat(filename
, ".pacnew", PATH_MAX
- strlen(filename
));
436 _alpm_log(PM_LOG_DEBUG
, "extracting %s\n", filename
);
439 if(trans
->flags
& PM_TRANS_FLAG_FORCE
) {
440 /* if FORCE was used, unlink() each file (whether it's there
441 * or not) before extracting. This prevents the old "Text file busy"
442 * error that crops up if forcing a glibc or pacman upgrade. */
446 ret
= perform_extraction(archive
, entry
, filename
, entryname_orig
);
449 FREE(entryname_orig
);
453 /* calculate an hash if this is in newpkg's backup */
455 for(b
= alpm_pkg_get_backup(newpkg
); b
; b
= b
->next
) {
456 char *backup
= NULL
, *hash
= NULL
;
457 char *oldbackup
= alpm_list_getdata(b
);
458 /* length is tab char, null byte and MD5 (32 char) */
459 size_t backup_len
= strlen(oldbackup
) + 34;
461 if(!oldbackup
|| strcmp(oldbackup
, entryname_orig
) != 0) {
464 _alpm_log(PM_LOG_DEBUG
, "appending backup entry for %s\n", filename
);
466 hash
= alpm_compute_md5sum(filename
);
467 MALLOC(backup
, backup_len
, RET_ERR(PM_ERR_MEMORY
, -1));
469 sprintf(backup
, "%s\t%s", oldbackup
, hash
);
470 backup
[backup_len
-1] = '\0';
476 FREE(entryname_orig
);
480 static int commit_single_pkg(pmpkg_t
*newpkg
, size_t pkg_current
, size_t pkg_count
,
481 pmtrans_t
*trans
, pmdb_t
*db
)
483 int i
, ret
= 0, errors
= 0;
484 char scriptlet
[PATH_MAX
+1];
486 pmpkg_t
*oldpkg
= NULL
;
490 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
492 snprintf(scriptlet
, PATH_MAX
, "%s%s-%s/install",
493 _alpm_db_path(db
), alpm_pkg_get_name(newpkg
),
494 alpm_pkg_get_version(newpkg
));
496 /* see if this is an upgrade. if so, remove the old package first */
497 pmpkg_t
*local
= _alpm_db_get_pkgfromcache(db
, newpkg
->name
);
501 /* we'll need to save some record for backup checks later */
502 oldpkg
= _alpm_pkg_dup(local
);
503 /* make sure all infos are loaded because the database entry
504 * will be removed soon */
505 _alpm_local_db_read(oldpkg
->origin_data
.db
, oldpkg
, INFRQ_ALL
);
507 EVENT(trans
, PM_TRANS_EVT_UPGRADE_START
, newpkg
, oldpkg
);
508 _alpm_log(PM_LOG_DEBUG
, "upgrading package %s-%s\n",
509 newpkg
->name
, newpkg
->version
);
511 /* copy over the install reason */
512 newpkg
->reason
= alpm_pkg_get_reason(oldpkg
);
514 /* pre_upgrade scriptlet */
515 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& PM_TRANS_FLAG_NOSCRIPTLET
)) {
516 _alpm_runscriptlet(handle
->root
, newpkg
->origin_data
.file
,
517 "pre_upgrade", newpkg
->version
, oldpkg
->version
, trans
);
522 EVENT(trans
, PM_TRANS_EVT_ADD_START
, newpkg
, NULL
);
523 _alpm_log(PM_LOG_DEBUG
, "adding package %s-%s\n",
524 newpkg
->name
, newpkg
->version
);
526 /* pre_install scriptlet */
527 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& PM_TRANS_FLAG_NOSCRIPTLET
)) {
528 _alpm_runscriptlet(handle
->root
, newpkg
->origin_data
.file
,
529 "pre_install", newpkg
->version
, NULL
, trans
);
533 /* we override any pre-set reason if we have alldeps or allexplicit set */
534 if(trans
->flags
& PM_TRANS_FLAG_ALLDEPS
) {
535 newpkg
->reason
= PM_PKG_REASON_DEPEND
;
536 } else if(trans
->flags
& PM_TRANS_FLAG_ALLEXPLICIT
) {
537 newpkg
->reason
= PM_PKG_REASON_EXPLICIT
;
541 /* set up fake remove transaction */
542 if(_alpm_upgraderemove_package(oldpkg
, newpkg
, trans
) == -1) {
543 pm_errno
= PM_ERR_TRANS_ABORT
;
549 /* prepare directory for database entries so permission are correct after
550 changelog/install script installation (FS#12263) */
551 if(_alpm_local_db_prepare(db
, newpkg
)) {
552 alpm_logaction("error: could not create database entry %s-%s\n",
553 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
554 pm_errno
= PM_ERR_DB_WRITE
;
559 if(!(trans
->flags
& PM_TRANS_FLAG_DBONLY
)) {
560 struct archive
*archive
;
561 struct archive_entry
*entry
;
562 char cwd
[PATH_MAX
] = "";
565 _alpm_log(PM_LOG_DEBUG
, "extracting files\n");
567 if ((archive
= archive_read_new()) == NULL
) {
568 pm_errno
= PM_ERR_LIBARCHIVE
;
573 archive_read_support_compression_all(archive
);
574 archive_read_support_format_all(archive
);
576 _alpm_log(PM_LOG_DEBUG
, "archive: %s\n", newpkg
->origin_data
.file
);
577 if(archive_read_open_filename(archive
, newpkg
->origin_data
.file
,
578 ARCHIVE_DEFAULT_BYTES_PER_BLOCK
) != ARCHIVE_OK
) {
579 pm_errno
= PM_ERR_PKG_OPEN
;
584 /* save the cwd so we can restore it later */
585 if(getcwd(cwd
, PATH_MAX
) == NULL
) {
586 _alpm_log(PM_LOG_ERROR
, _("could not get current working directory\n"));
591 /* libarchive requires this for extracting hard links */
592 if(chdir(handle
->root
) != 0) {
593 _alpm_log(PM_LOG_ERROR
, _("could not change directory to %s (%s)\n"), handle
->root
, strerror(errno
));
598 /* call PROGRESS once with 0 percent, as we sort-of skip that here */
600 PROGRESS(trans
, PM_TRANS_PROGRESS_UPGRADE_START
,
601 alpm_pkg_get_name(newpkg
), 0, pkg_count
, pkg_current
);
603 PROGRESS(trans
, PM_TRANS_PROGRESS_ADD_START
,
604 alpm_pkg_get_name(newpkg
), 0, pkg_count
, pkg_current
);
607 for(i
= 0; archive_read_next_header(archive
, &entry
) == ARCHIVE_OK
; i
++) {
610 if(newpkg
->size
!= 0) {
611 /* Using compressed size for calculations here, as newpkg->isize is not
612 * exact when it comes to comparing to the ACTUAL uncompressed size
613 * (missing metadata sizes) */
614 int64_t pos
= archive_position_compressed(archive
);
615 percent
= (double)pos
/ (double)newpkg
->size
;
616 _alpm_log(PM_LOG_DEBUG
, "decompression progress: "
617 "%f%% (%"PRId64
" / %jd)\n",
618 percent
*100.0, pos
, (intmax_t)newpkg
->size
);
627 PROGRESS(trans
, PM_TRANS_PROGRESS_UPGRADE_START
,
628 alpm_pkg_get_name(newpkg
), (int)(percent
* 100), pkg_count
,
631 PROGRESS(trans
, PM_TRANS_PROGRESS_ADD_START
,
632 alpm_pkg_get_name(newpkg
), (int)(percent
* 100), pkg_count
,
636 /* extract the next file from the archive */
637 errors
+= extract_single_file(archive
, entry
, newpkg
, oldpkg
,
640 archive_read_finish(archive
);
642 /* restore the old cwd if we have it */
643 if(restore_cwd
&& chdir(cwd
) != 0) {
644 _alpm_log(PM_LOG_ERROR
, _("could not change directory to %s (%s)\n"), cwd
, strerror(errno
));
650 _alpm_log(PM_LOG_ERROR
, _("problem occurred while upgrading %s\n"),
652 alpm_logaction("error: problem occurred while upgrading %s\n",
655 _alpm_log(PM_LOG_ERROR
, _("problem occurred while installing %s\n"),
657 alpm_logaction("error: problem occurred while installing %s\n",
663 /* make an install date (in UTC) */
664 newpkg
->installdate
= time(NULL
);
666 _alpm_log(PM_LOG_DEBUG
, "updating database\n");
667 _alpm_log(PM_LOG_DEBUG
, "adding database entry '%s'\n", newpkg
->name
);
669 if(_alpm_local_db_write(db
, newpkg
, INFRQ_ALL
)) {
670 _alpm_log(PM_LOG_ERROR
, _("could not update database entry %s-%s\n"),
671 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
672 alpm_logaction("error: could not update database entry %s-%s\n",
673 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
674 pm_errno
= PM_ERR_DB_WRITE
;
679 if(_alpm_db_add_pkgincache(db
, newpkg
) == -1) {
680 _alpm_log(PM_LOG_ERROR
, _("could not add entry '%s' in cache\n"),
681 alpm_pkg_get_name(newpkg
));
685 PROGRESS(trans
, PM_TRANS_PROGRESS_UPGRADE_START
,
686 alpm_pkg_get_name(newpkg
), 100, pkg_count
, pkg_current
);
688 PROGRESS(trans
, PM_TRANS_PROGRESS_ADD_START
,
689 alpm_pkg_get_name(newpkg
), 100, pkg_count
, pkg_current
);
692 /* run the post-install script if it exists */
693 if(alpm_pkg_has_scriptlet(newpkg
)
694 && !(trans
->flags
& PM_TRANS_FLAG_NOSCRIPTLET
)) {
696 _alpm_runscriptlet(handle
->root
, scriptlet
, "post_upgrade",
697 alpm_pkg_get_version(newpkg
),
698 oldpkg
? alpm_pkg_get_version(oldpkg
) : NULL
, trans
);
700 _alpm_runscriptlet(handle
->root
, scriptlet
, "post_install",
701 alpm_pkg_get_version(newpkg
), NULL
, trans
);
706 EVENT(trans
, PM_TRANS_EVT_UPGRADE_DONE
, newpkg
, oldpkg
);
708 EVENT(trans
, PM_TRANS_EVT_ADD_DONE
, newpkg
, oldpkg
);
712 _alpm_pkg_free(oldpkg
);
716 int _alpm_upgrade_packages(pmtrans_t
*trans
, pmdb_t
*db
)
718 size_t pkg_count
, pkg_current
;
719 int skip_ldconfig
= 0, ret
= 0;
724 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
725 ASSERT(db
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
727 if(trans
->add
== NULL
) {
731 pkg_count
= alpm_list_count(trans
->add
);
734 /* loop through our package list adding/upgrading one at a time */
735 for(targ
= trans
->add
; targ
; targ
= targ
->next
) {
736 if(handle
->trans
->state
== STATE_INTERRUPTED
) {
740 pmpkg_t
*newpkg
= (pmpkg_t
*)targ
->data
;
741 if(commit_single_pkg(newpkg
, pkg_current
, pkg_count
, trans
, db
)) {
742 /* something screwed up on the commit, abort the trans */
743 trans
->state
= STATE_INTERRUPTED
;
744 pm_errno
= PM_ERR_TRANS_ABORT
;
745 /* running ldconfig at this point could possibly screw system */
754 /* run ldconfig if it exists */
755 _alpm_ldconfig(handle
->root
);
761 /* vim: set ts=2 sw=2 noet: */