4 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
5 * Copyright (c) 2005 by Aurelien Foret <orelien@chez.com>
6 * Copyright (c) 2005 by Christian Hamar <krics@linuxforum.hu>
7 * Copyright (c) 2006 by David Kimpe <dnaku@frugalware.org>
8 * Copyright (c) 2005, 2006 by Miklos Vajna <vmiklos@frugalware.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
26 #if defined(__APPLE__) || defined(__OpenBSD__)
27 #include <sys/syslimits.h>
29 #if defined(__APPLE__) || defined(__OpenBSD__) || defined(__sun__)
45 #include "alpm_list.h"
50 #include "versioncmp.h"
63 int _alpm_add_loadtarget(pmtrans_t
*trans
, pmdb_t
*db
, char *name
)
67 char pkgname
[PKG_NAME_LEN
], pkgver
[PKG_VERSION_LEN
];
73 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
74 ASSERT(db
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
75 ASSERT(name
!= NULL
&& strlen(name
) != 0, RET_ERR(PM_ERR_WRONG_ARGS
, -1));
77 _alpm_log(PM_LOG_DEBUG
, _("loading target '%s'"), name
);
79 /* TODO FS#5120 we need a better way to check if a package is a valid package,
80 * and read the metadata instead of relying on the filename for package name
82 if(stat(name
, &buf
)) {
83 pm_errno
= PM_ERR_NOT_A_FILE
;
87 if(_alpm_pkg_splitname(name
, pkgname
, pkgver
, 1) == -1) {
88 pm_errno
= PM_ERR_PKG_INVALID_NAME
;
92 /* no additional hyphens in version strings */
93 if(strchr(pkgver
, '-') != strrchr(pkgver
, '-')) {
94 pm_errno
= PM_ERR_PKG_INVALID_NAME
;
98 if(trans
->type
!= PM_TRANS_TYPE_UPGRADE
) {
99 /* only install this package if it is not already installed */
100 if(_alpm_db_get_pkgfromcache(db
, pkgname
)) {
101 pm_errno
= PM_ERR_PKG_INSTALLED
;
105 if(trans
->flags
& PM_TRANS_FLAG_FRESHEN
) {
106 /* only upgrade/install this package if it is already installed and at a lesser version */
107 dummy
= _alpm_db_get_pkgfromcache(db
, pkgname
);
108 if(dummy
== NULL
|| _alpm_versioncmp(dummy
->version
, pkgver
) >= 0) {
109 pm_errno
= PM_ERR_PKG_CANT_FRESH
;
115 /* check if an older version of said package is already in transaction packages.
116 * if so, replace it in the list */
117 for(i
= trans
->packages
; i
; i
= i
->next
) {
118 pmpkg_t
*pkg
= i
->data
;
119 if(strcmp(pkg
->name
, pkgname
) == 0) {
120 if(_alpm_versioncmp(pkg
->version
, pkgver
) < 0) {
122 _alpm_log(PM_LOG_WARNING
, _("replacing older version %s-%s by %s in target list"),
123 pkg
->name
, pkg
->version
, pkgver
);
124 if((newpkg
= _alpm_pkg_load(name
)) == NULL
) {
125 /* pm_errno is already set by pkg_load() */
131 _alpm_log(PM_LOG_WARNING
, _("newer version %s-%s is in the target list -- skipping"),
132 pkg
->name
, pkg
->version
);
138 _alpm_log(PM_LOG_DEBUG
, _("reading '%s' metadata"), pkgname
);
139 info
= _alpm_pkg_load(name
);
141 /* pm_errno is already set by pkg_load() */
144 /* check to verify we're not getting fooled by a corrupted package */
145 if(strcmp(pkgname
, info
->name
) != 0 || strcmp(pkgver
, info
->version
) != 0) {
146 pm_errno
= PM_ERR_PKG_INVALID
;
150 if(trans
->flags
& PM_TRANS_FLAG_ALLDEPS
) {
151 info
->reason
= PM_PKG_REASON_DEPEND
;
154 /* add the package to the transaction */
155 trans
->packages
= alpm_list_add(trans
->packages
, info
);
165 /* This is still messy. We have a lot of compare functions, and we should
166 * try to consolidate them as much as we can (between add and sync) */
167 /*static int deppkg_cmp(const void *p1, const void *p2)
169 return(strcmp(((pmdepmissing_t *)p1)->target,
170 ((pmdepmissing_t *)p2)->target));
173 int _alpm_add_prepare(pmtrans_t
*trans
, pmdb_t
*db
, alpm_list_t
**data
)
175 alpm_list_t
*lp
= NULL
, *i
= NULL
;
176 alpm_list_t
*rmlist
= NULL
;
177 char rm_fname
[PATH_MAX
];
178 pmpkg_t
*info
= NULL
;
182 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
183 ASSERT(db
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
185 /* Check dependencies
187 if(!(trans
->flags
& PM_TRANS_FLAG_NODEPS
)) {
188 EVENT(trans
, PM_TRANS_EVT_CHECKDEPS_START
, NULL
, NULL
);
190 /* look for unsatisfied dependencies */
191 _alpm_log(PM_LOG_DEBUG
, _("looking for unsatisfied dependencies"));
192 lp
= _alpm_checkdeps(trans
, db
, trans
->type
, trans
->packages
);
199 RET_ERR(PM_ERR_UNSATISFIED_DEPS
, -1);
202 /* no unsatisfied deps, so look for conflicts */
203 _alpm_log(PM_LOG_DEBUG
, _("looking for conflicts"));
204 lp
= _alpm_checkconflicts(db
, trans
->packages
);
205 for(i
= lp
; i
; i
= i
->next
) {
206 pmdepmissing_t
*miss
= i
->data
;
208 _alpm_log(PM_LOG_ERROR
, _("replacing packages with -A and -U is not supported yet"));
209 _alpm_log(PM_LOG_ERROR
, _("please remove '%s' first, using -Rd"), miss
->depend
.name
);
210 RET_ERR(PM_ERR_CONFLICTING_DEPS
, -1);
212 /* Attempt to resolve conflicts */
215 QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, miss->target, miss->depend.name, NULL, &skip_this);
217 pmdepmissing_t *pkg = NULL;
218 lp = alpm_list_remove(lp, (void *)miss, deppkg_cmp, (void*)&pkg);
220 /* TODO: We remove the conflict from the list but never actually remove
221 * the package. Need to do this to fix FS #3492. The sync code should
222 * provide an example of how to do this, as it handles replaces and
223 * removes. We run into problems because we do a file conflict check
224 * below and it fails there. A force flag will skip that part, but
225 * still not remove the original package designated here for removal.
226 * Better yet, dump all this shitty duplicate code and somehow combine
227 * it with the sync code. */
236 /* Removal code should go here, as described above. Instead of simply
237 * removing items, perhaps throw them in another list to be removed, then
238 * proceed as sync.c would? I'm not sure because I'm not familiar enough
239 * with the codebase. */
246 RET_ERR(PM_ERR_CONFLICTING_DEPS
, -1);
249 /* re-order w.r.t. dependencies */
250 _alpm_log(PM_LOG_DEBUG
, _("sorting by dependencies"));
251 lp
= _alpm_sortbydeps(trans
->packages
, PM_TRANS_TYPE_ADD
);
252 /* free the old alltargs */
253 FREELISTPTR(trans
->packages
);
254 trans
->packages
= lp
;
256 EVENT(trans
, PM_TRANS_EVT_CHECKDEPS_DONE
, NULL
, NULL
);
261 EVENT(trans
, PM_TRANS_EVT_CLEANUP_START
, NULL
, NULL
);
262 _alpm_log(PM_LOG_DEBUG
, _("cleaning up"));
263 for (lp
=trans
->packages
; lp
!=NULL
; lp
=lp
->next
) {
264 info
=(pmpkg_t
*)lp
->data
;
265 for (rmlist
= alpm_pkg_get_removes(info
); rmlist
; rmlist
= rmlist
->next
) {
266 snprintf(rm_fname
, PATH_MAX
, "%s%s", handle
->root
, (char *)rmlist
->data
);
270 EVENT(trans
, PM_TRANS_EVT_CLEANUP_DONE
, NULL
, NULL
);
272 /* Check for file conflicts
274 if(!(trans
->flags
& PM_TRANS_FLAG_FORCE
)) {
275 EVENT(trans
, PM_TRANS_EVT_FILECONFLICTS_START
, NULL
, NULL
);
277 _alpm_log(PM_LOG_DEBUG
, _("looking for file conflicts"));
278 lp
= _alpm_db_find_conflicts(db
, trans
, handle
->root
);
285 RET_ERR(PM_ERR_FILE_CONFLICTS
, -1);
288 EVENT(trans
, PM_TRANS_EVT_FILECONFLICTS_DONE
, NULL
, NULL
);
292 if(_alpm_check_freespace(trans
, data
) == -1) {
293 /* pm_errno is set by check_freespace */
301 int _alpm_add_commit(pmtrans_t
*trans
, pmdb_t
*db
)
303 int i
, ret
= 0, errors
= 0, pkg_count
= 0;
304 struct archive
*archive
;
305 struct archive_entry
*entry
;
306 char cwd
[PATH_MAX
] = "";
307 alpm_list_t
*targ
, *lp
;
311 ASSERT(trans
!= NULL
, RET_ERR(PM_ERR_TRANS_NULL
, -1));
312 ASSERT(db
!= NULL
, RET_ERR(PM_ERR_DB_NULL
, -1));
314 if(trans
->packages
== NULL
) {
318 pkg_count
= alpm_list_count(trans
->targets
);
320 for(targ
= trans
->packages
; targ
; targ
= targ
->next
) {
321 char scriptlet
[PATH_MAX
+1];
322 int targ_count
= 0, is_upgrade
= 0, use_md5
= 0;
323 double percent
= 0.0;
324 pmpkg_t
*newpkg
= (pmpkg_t
*)targ
->data
;
325 pmpkg_t
*oldpkg
= NULL
;
328 if(handle
->trans
->state
== STATE_INTERRUPTED
) {
332 snprintf(scriptlet
, PATH_MAX
, "%s%s-%s/install", db
->path
,
333 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
335 /* check if we have a valid sha1sum, if not, use MD5 */
336 if(strlen(newpkg
->sha1sum
) == 0) {
340 /* see if this is an upgrade. if so, remove the old package first */
341 pmpkg_t
*local
= _alpm_db_get_pkgfromcache(db
, newpkg
->name
);
345 EVENT(trans
, PM_TRANS_EVT_UPGRADE_START
, newpkg
, NULL
);
346 _alpm_log(PM_LOG_DEBUG
, _("upgrading package %s-%s"), newpkg
->name
, newpkg
->version
);
348 /* we'll need to save some record for backup checks later */
349 oldpkg
= _alpm_pkg_new(local
->name
, local
->version
);
351 oldpkg
->backup
= alpm_list_strdup(alpm_pkg_get_backup(local
));
352 oldpkg
->provides
= alpm_list_strdup(alpm_pkg_get_provides(local
));
353 strncpy(oldpkg
->name
, local
->name
, PKG_NAME_LEN
);
354 strncpy(oldpkg
->version
, local
->version
, PKG_VERSION_LEN
);
356 RET_ERR(PM_ERR_MEMORY
, -1);
359 /* copy over the install reason */
360 newpkg
->reason
= alpm_pkg_get_reason(local
);
362 /* pre_upgrade scriptlet */
363 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& PM_TRANS_FLAG_NOSCRIPTLET
)) {
364 _alpm_runscriptlet(handle
->root
, newpkg
->data
, "pre_upgrade", newpkg
->version
, oldpkg
->version
, trans
);
369 EVENT(trans
, PM_TRANS_EVT_ADD_START
, newpkg
, NULL
);
370 _alpm_log(PM_LOG_DEBUG
, _("adding package %s-%s"), newpkg
->name
, newpkg
->version
);
372 /* pre_install scriptlet */
373 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& PM_TRANS_FLAG_NOSCRIPTLET
)) {
374 _alpm_runscriptlet(handle
->root
, newpkg
->data
, "pre_install", newpkg
->version
, NULL
, trans
);
379 /* this is kinda odd. If the old package exists, at this point we make a
380 * NEW transaction, unrelated to handle->trans, and instantiate a "remove"
381 * with the type PM_TRANS_TYPE_UPGRADE. TODO: kill this weird behavior. */
382 pmtrans_t
*tr
= _alpm_trans_new();
383 _alpm_log(PM_LOG_DEBUG
, _("removing old package first (%s-%s)"), oldpkg
->name
, oldpkg
->version
);
386 RET_ERR(PM_ERR_TRANS_ABORT
, -1);
389 if(_alpm_trans_init(tr
, PM_TRANS_TYPE_UPGRADE
, trans
->flags
, NULL
, NULL
, NULL
) == -1) {
391 RET_ERR(PM_ERR_TRANS_ABORT
, -1);
394 if(_alpm_remove_loadtarget(tr
, db
, newpkg
->name
) == -1) {
396 RET_ERR(PM_ERR_TRANS_ABORT
, -1);
399 /* copy the remove skiplist over */
400 tr
->skip_remove
= alpm_list_strdup(trans
->skip_remove
);
403 /* Add files in the NEW package's backup array to the noupgrade array
404 * so this removal operation doesn't kill them */
405 /* TODO if we add here, all backup=() entries for all targets, new and
406 * old, we cover all bases, including backup=() locations changing hands.
407 * But is this viable? */
408 alpm_list_t
*old_noupgrade
= alpm_list_strdup(handle
->noupgrade
);
409 for(b
= alpm_pkg_get_backup(newpkg
); b
; b
= b
->next
) {
410 const char *backup
= b
->data
;
411 _alpm_log(PM_LOG_DEBUG
, _("adding %s to the NoUpgrade array temporarily"), backup
);
412 handle
->noupgrade
= alpm_list_add(handle
->noupgrade
, strdup(backup
));
415 int ret
= _alpm_remove_commit(tr
, db
);
418 /* restore our "NoUpgrade" list to previous state */
419 alpm_list_free_inner(handle
->noupgrade
, free
);
420 alpm_list_free(handle
->noupgrade
);
421 handle
->noupgrade
= old_noupgrade
;
424 RET_ERR(PM_ERR_TRANS_ABORT
, -1);
428 if(!(trans
->flags
& PM_TRANS_FLAG_DBONLY
)) {
429 _alpm_log(PM_LOG_DEBUG
, _("extracting files"));
431 if ((archive
= archive_read_new()) == NULL
) {
432 RET_ERR(PM_ERR_LIBARCHIVE_ERROR
, -1);
435 archive_read_support_compression_all(archive
);
436 archive_read_support_format_all(archive
);
438 if(archive_read_open_file(archive
, newpkg
->data
, ARCHIVE_DEFAULT_BYTES_PER_BLOCK
) != ARCHIVE_OK
) {
439 RET_ERR(PM_ERR_PKG_OPEN
, -1);
442 /* save the cwd so we can restore it later */
443 if(getcwd(cwd
, PATH_MAX
) == NULL
) {
444 _alpm_log(PM_LOG_ERROR
, _("could not get current working directory"));
448 /* libarchive requires this for extracting hard links */
451 targ_count
= alpm_list_count(targ
);
452 /* call PROGRESS once with 0 percent, as we sort-of skip that here */
453 PROGRESS(trans
, (is_upgrade
? PM_TRANS_PROGRESS_UPGRADE_START
: PM_TRANS_PROGRESS_ADD_START
),
454 newpkg
->name
, 0, pkg_count
, (pkg_count
- targ_count
+1));
456 for(i
= 0; archive_read_next_header(archive
, &entry
) == ARCHIVE_OK
; i
++) {
457 const char *entryname
; /* the name of the file in the archive */
458 char filename
[PATH_MAX
]; /* the actual file we're extracting */
459 int needbackup
= 0, notouch
= 0;
460 char *hash_orig
= NULL
;
463 entryname
= archive_entry_pathname(entry
);
465 if(newpkg
->size
!= 0) {
466 /* Using compressed size for calculations here, as newpkg->isize is not
467 * exact when it comes to comparing to the ACTUAL uncompressed size
468 * (missing metadata sizes) */
469 unsigned long pos
= archive_position_compressed(archive
);
470 percent
= (double)pos
/ (double)newpkg
->size
;
471 _alpm_log(PM_LOG_DEBUG
, "decompression progress: %f%% (%ld / %ld)", percent
*100.0, pos
, newpkg
->size
);
477 PROGRESS(trans
, (is_upgrade
? PM_TRANS_PROGRESS_UPGRADE_START
: PM_TRANS_PROGRESS_ADD_START
),
478 newpkg
->name
, (int)(percent
* 100), pkg_count
, (pkg_count
- targ_count
+1));
480 memset(filename
, 0, PATH_MAX
); /* just to be sure */
482 if(strcmp(entryname
, ".PKGINFO") == 0 || strcmp(entryname
, ".FILELIST") == 0) {
483 archive_read_data_skip(archive
);
485 } else if(strcmp(entryname
, ".INSTALL") == 0) {
486 /* the install script goes inside the db */
487 snprintf(filename
, PATH_MAX
, "%s/%s-%s/install", db
->path
,
488 newpkg
->name
, newpkg
->version
);
489 } else if(strcmp(entryname
, ".CHANGELOG") == 0) {
490 /* the changelog goes inside the db */
491 snprintf(filename
, PATH_MAX
, "%s/%s-%s/changelog", db
->path
,
492 newpkg
->name
, newpkg
->version
);
494 /* build the new entryname relative to handle->root */
495 snprintf(filename
, PATH_MAX
, "%s%s", handle
->root
, entryname
);
498 /* if a file is in NoExtract then we never extract it */
499 if(alpm_list_find_str(handle
->noextract
, entryname
)) {
500 _alpm_log(PM_LOG_DEBUG
, _("%s is in NoExtract, skipping extraction"), entryname
);
501 alpm_logaction(_("%s is in NoExtract, skipping extraction"), entryname
);
502 archive_read_data_skip(archive
);
506 /* if a file is in the add skiplist we never extract it */
507 if(alpm_list_find_str(trans
->skip_add
, filename
)) {
508 _alpm_log(PM_LOG_DEBUG
, _("%s is in trans->skip_add, skipping extraction"), entryname
);
509 archive_read_data_skip(archive
);
513 /* check is file already exists */
514 if(stat(filename
, &buf
) == 0 && !S_ISDIR(buf
.st_mode
)) {
515 /* it does, is it a backup=() file?
516 * always check the newpkg first, so when we do add a backup=() file,
517 * we don't have to wait a full upgrade cycle */
518 needbackup
= alpm_list_find_str(alpm_pkg_get_backup(newpkg
), entryname
);
521 hash_orig
= _alpm_needbackup(entryname
, alpm_pkg_get_backup(oldpkg
));
527 /* this is kind of gross. if we force hash_orig to be non-NULL we can
528 * catch the pro-active backup=() case (when the backup entry is in
529 * the new package, and not the old */
530 if(needbackup
&& !hash_orig
) {
531 hash_orig
= strdup("");
534 /* NoUpgrade skips all this backup stuff, because it's just never
536 if(alpm_list_find_str(handle
->noupgrade
, entryname
)) {
543 char *tempfile
= NULL
;
544 char *hash_local
= NULL
, *hash_pkg
= NULL
;
547 /* extract the package's version to a temporary file and md5 it */
548 tempfile
= strdup("/tmp/alpm_XXXXXX");
549 fd
= mkstemp(tempfile
);
551 archive_entry_set_pathname(entry
, tempfile
);
553 if(archive_read_extract(archive
, entry
, ARCHIVE_EXTRACT_FLAGS
) != ARCHIVE_OK
) {
554 _alpm_log(PM_LOG_ERROR
, _("could not extract %s (%s)"), entryname
, strerror(errno
));
555 alpm_logaction(_("could not extract %s (%s)"), entryname
, strerror(errno
));
564 hash_local
= _alpm_MDFile(filename
);
565 hash_pkg
= _alpm_MDFile(tempfile
);
567 hash_local
= _alpm_SHAFile(filename
);
568 hash_pkg
= _alpm_SHAFile(tempfile
);
571 /* append the new md5 or sha1 hash to it's respective entry in newpkg's backup
572 * (it will be the new orginal) */
573 for(lp
= alpm_pkg_get_backup(newpkg
); lp
; lp
= lp
->next
) {
574 if(!lp
->data
|| strcmp(lp
->data
, entryname
) != 0) {
578 int backup_len
= strlen(lp
->data
) + 2; /* tab char and null byte */
581 backup_len
+= 32; /* MD5s are 32 chars in length */
583 backup_len
+= 40; /* SHA1s are 40 chars in length */
586 backup
= malloc(backup_len
);
588 RET_ERR(PM_ERR_MEMORY
, -1);
591 sprintf(backup
, "%s\t%s", (char *)lp
->data
, hash_pkg
);
592 backup
[backup_len
-1] = '\0';
598 _alpm_log(PM_LOG_DEBUG
, _("checking md5 hashes for %s"), entryname
);
600 _alpm_log(PM_LOG_DEBUG
, _("checking sha1 hashes for %s"), entryname
);
602 _alpm_log(PM_LOG_DEBUG
, _("current: %s"), hash_local
);
603 _alpm_log(PM_LOG_DEBUG
, _("new: %s"), hash_pkg
);
604 _alpm_log(PM_LOG_DEBUG
, _("original: %s"), hash_orig
);
607 /* looks like we have a local file that has a different hash as the
608 * file in the package, move it to a .pacorig */
609 if(strcmp(hash_local
, hash_pkg
) != 0) {
610 char newpath
[PATH_MAX
];
611 snprintf(newpath
, PATH_MAX
, "%s.pacorig", filename
);
613 /* move the existing file to the "pacorig" */
614 if(rename(filename
, newpath
)) {
615 archive_entry_set_pathname(entry
, filename
);
616 _alpm_log(PM_LOG_ERROR
, _("could not rename %s (%s)"), filename
, strerror(errno
));
617 alpm_logaction(_("error: could not rename %s (%s)"), filename
, strerror(errno
));
620 /* copy the tempfile we extracted to the real path */
621 if(_alpm_copyfile(tempfile
, filename
)) {
622 archive_entry_set_pathname(entry
, filename
);
623 _alpm_log(PM_LOG_ERROR
, _("could not copy tempfile to %s (%s)"), filename
, strerror(errno
));
624 alpm_logaction(_("error: could not copy tempfile to %s (%s)"), filename
, strerror(errno
));
627 archive_entry_set_pathname(entry
, filename
);
628 _alpm_log(PM_LOG_WARNING
, _("%s saved as %s"), filename
, newpath
);
629 alpm_logaction(_("warning: %s saved as %s"), filename
, newpath
);
633 } else if(hash_orig
) {
636 if(strcmp(hash_orig
, hash_local
) == 0) {
637 /* installed file has NOT been changed by user */
638 if(strcmp(hash_orig
, hash_pkg
) != 0) {
639 _alpm_log(PM_LOG_DEBUG
, _("action: installing new file: %s"), entryname
);
641 if(_alpm_copyfile(tempfile
, filename
)) {
642 _alpm_log(PM_LOG_ERROR
, _("could not copy tempfile to %s (%s)"), filename
, strerror(errno
));
645 archive_entry_set_pathname(entry
, filename
);
647 /* there's no sense in installing the same file twice, install
648 * ONLY is the original and package hashes differ */
649 _alpm_log(PM_LOG_DEBUG
, _("action: leaving existing file in place"));
651 } else if(strcmp(hash_orig
, hash_pkg
) == 0) {
652 /* originally installed file and new file are the same - this
653 * implies the case above failed - i.e. the file was changed by a
655 _alpm_log(PM_LOG_DEBUG
, _("action: leaving existing file in place"));
656 } else if(strcmp(hash_local
, hash_pkg
) == 0) {
657 /* this would be magical. The above two cases failed, but the
658 * user changes just so happened to make the new file exactly the
659 * same as the one in the package... skip it */
660 _alpm_log(PM_LOG_DEBUG
, _("action: leaving existing file in place"));
662 char newpath
[PATH_MAX
];
663 _alpm_log(PM_LOG_DEBUG
, _("action: keeping current file and installing new one with .pacnew ending"));
664 snprintf(newpath
, PATH_MAX
, "%s.pacnew", filename
);
665 if(_alpm_copyfile(tempfile
, newpath
)) {
666 _alpm_log(PM_LOG_ERROR
, _("could not install %s as %s: %s"), filename
, newpath
, strerror(errno
));
667 alpm_logaction(_("error: could not install %s as %s: %s"), filename
, newpath
, strerror(errno
));
669 _alpm_log(PM_LOG_WARNING
, _("%s installed as %s"), filename
, newpath
);
670 alpm_logaction(_("warning: %s installed as %s"), filename
, newpath
);
681 } else { /* ! needbackup */
684 _alpm_log(PM_LOG_DEBUG
, _("%s is in NoUpgrade -- skipping"), filename
);
685 _alpm_log(PM_LOG_WARNING
, _("extracting %s as %s.pacnew"), filename
, filename
);
686 alpm_logaction(_("warning: extracting %s as %s.pacnew"), filename
, filename
);
687 strncat(filename
, ".pacnew", PATH_MAX
);
689 _alpm_log(PM_LOG_DEBUG
, _("extracting %s"), filename
);
692 if(trans
->flags
& PM_TRANS_FLAG_FORCE
) {
693 /* if FORCE was used, then unlink() each file (whether it's there
694 * or not) before extracting. this prevents the old "Text file busy"
695 * error that crops up if one tries to --force a glibc or pacman
701 archive_entry_set_pathname(entry
, filename
);
703 int ret
= archive_read_extract(archive
, entry
,
704 ARCHIVE_EXTRACT_FLAGS
| ARCHIVE_EXTRACT_NO_OVERWRITE
);
705 if(ret
!= ARCHIVE_OK
&& ret
!= ARCHIVE_WARN
) {
706 _alpm_log(PM_LOG_ERROR
, _("could not extract %s (%s)"), filename
, strerror(errno
));
707 alpm_logaction(_("error: could not extract %s (%s)"), filename
, strerror(errno
));
711 /* calculate an hash if this is in newpkg's backup */
712 for(lp
= alpm_pkg_get_backup(newpkg
); lp
; lp
= lp
->next
) {
713 char *backup
= NULL
, *hash
= NULL
;
714 int backup_len
= strlen(lp
->data
) + 2; /* tab char and null byte */
716 if(!lp
->data
|| strcmp(lp
->data
, entryname
) != 0) {
719 _alpm_log(PM_LOG_DEBUG
, _("appending backup entry for %s"), filename
);
722 backup_len
+= 32; /* MD5s are 32 chars in length */
723 hash
= _alpm_MDFile(filename
);
725 backup_len
+= 40; /* SHA1s are 40 chars in length */
726 hash
= _alpm_SHAFile(filename
);
729 backup
= malloc(backup_len
);
731 RET_ERR(PM_ERR_MEMORY
, -1);
734 sprintf(backup
, "%s\t%s", (char *)lp
->data
, hash
);
735 backup
[backup_len
-1] = '\0';
742 archive_read_finish(archive
);
744 /* restore the old cwd is we have it */
751 _alpm_log(PM_LOG_ERROR
, _("errors occurred while %s %s"),
752 (is_upgrade
? _("upgrading") : _("installing")), newpkg
->name
);
753 alpm_logaction(_("errors occurred while %s %s"),
754 (is_upgrade
? _("upgrading") : _("installing")), newpkg
->name
);
758 /* Update the requiredby field by scanning the whole database
759 * looking for packages depending on the package to add */
760 _alpm_pkg_update_requiredby(newpkg
);
762 /* special case: if our provides list has changed from oldpkg to newpkg AND
763 * we get here, we need to make sure we find the actual provision that
764 * still satisfies this case, and update its 'requiredby' field... ugh */
765 alpm_list_t
*provdiff
, *prov
;
766 provdiff
= alpm_list_diff(alpm_pkg_get_provides(oldpkg
),
767 alpm_pkg_get_provides(newpkg
),
769 for(prov
= provdiff
; prov
; prov
= prov
->next
) {
770 const char *provname
= prov
->data
;
771 _alpm_log(PM_LOG_DEBUG
, _("provision '%s' has been removed from package %s (%s => %s)"),
772 provname
, alpm_pkg_get_name(oldpkg
),
773 alpm_pkg_get_version(oldpkg
), alpm_pkg_get_version(newpkg
));
775 alpm_list_t
*p
= _alpm_db_whatprovides(handle
->db_local
, provname
);
777 /* we now have all the provisions in the local DB for this virtual
778 * package... seeing as we can't really determine which is the 'correct'
779 * provision, we'll use the FIRST for now.
780 * TODO figure out a way to find a "correct" provision */
781 pmpkg_t
*provpkg
= p
->data
;
782 const char *pkgname
= alpm_pkg_get_name(provpkg
);
783 _alpm_log(PM_LOG_DEBUG
, _("updating '%s' due to provision change (%s)"), pkgname
, provname
);
784 _alpm_pkg_update_requiredby(provpkg
);
786 if(_alpm_db_write(db
, provpkg
, INFRQ_DEPENDS
)) {
787 _alpm_log(PM_LOG_ERROR
, _("could not update provision '%s' from '%s'"), provname
, pkgname
);
788 alpm_logaction(_("could not update provision '%s' from '%s'"), provname
, pkgname
);
789 RET_ERR(PM_ERR_DB_WRITE
, -1);
793 alpm_list_free(provdiff
);
795 /* make an install date (in UTC) */
796 time_t t
= time(NULL
);
797 strncpy(newpkg
->installdate
, asctime(gmtime(&t
)), PKG_DATE_LEN
);
798 /* remove the extra line feed appended by asctime() */
799 newpkg
->installdate
[strlen(newpkg
->installdate
)-1] = 0;
801 _alpm_log(PM_LOG_DEBUG
, _("updating database"));
802 _alpm_log(PM_LOG_DEBUG
, _("adding database entry '%s'"), newpkg
->name
);
804 if(_alpm_db_write(db
, newpkg
, INFRQ_ALL
)) {
805 _alpm_log(PM_LOG_ERROR
, _("could not update database entry %s-%s"),
806 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
807 alpm_logaction(_("could not update database entry %s-%s"),
808 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
809 RET_ERR(PM_ERR_DB_WRITE
, -1);
812 if(_alpm_db_add_pkgincache(db
, newpkg
) == -1) {
813 _alpm_log(PM_LOG_ERROR
, _("could not add entry '%s' in cache"),
814 alpm_pkg_get_name(newpkg
));
817 /* update dependency packages' REQUIREDBY fields */
818 _alpm_trans_update_depends(trans
, newpkg
);
820 PROGRESS(trans
, (is_upgrade
? PM_TRANS_PROGRESS_UPGRADE_START
: PM_TRANS_PROGRESS_ADD_START
),
821 alpm_pkg_get_name(newpkg
), 100, pkg_count
, (pkg_count
- targ_count
+1));
822 EVENT(trans
, PM_TRANS_EVT_EXTRACT_DONE
, NULL
, NULL
);
824 /* run the post-install script if it exists */
825 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& PM_TRANS_FLAG_NOSCRIPTLET
)) {
827 _alpm_runscriptlet(handle
->root
, scriptlet
, "post_upgrade",
828 alpm_pkg_get_version(newpkg
), oldpkg
? alpm_pkg_get_version(oldpkg
) : NULL
,
831 _alpm_runscriptlet(handle
->root
, scriptlet
, "post_install",
832 alpm_pkg_get_version(newpkg
), NULL
, trans
);
836 EVENT(trans
, (is_upgrade
) ? PM_TRANS_EVT_UPGRADE_DONE
: PM_TRANS_EVT_ADD_DONE
, newpkg
, oldpkg
);
841 /* run ldconfig if it exists */
842 if(handle
->trans
->state
!= STATE_INTERRUPTED
) {
843 _alpm_log(PM_LOG_DEBUG
, _("running \"ldconfig -r %s\""), handle
->root
);
844 _alpm_ldconfig(handle
->root
);
850 /* vim: set ts=2 sw=2 noet: */