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>
41 #include "alpm_list.h"
52 /** Add a package to the transaction. */
53 int SYMEXPORT
alpm_add_pkg(alpm_handle_t
*handle
, alpm_pkg_t
*pkg
)
55 const char *pkgname
, *pkgver
;
60 CHECK_HANDLE(handle
, return -1);
61 ASSERT(pkg
!= NULL
, RET_ERR(handle
, ALPM_ERR_WRONG_ARGS
, -1));
62 ASSERT(handle
== pkg
->handle
, RET_ERR(handle
, ALPM_ERR_WRONG_ARGS
, -1));
63 trans
= handle
->trans
;
64 ASSERT(trans
!= NULL
, RET_ERR(handle
, ALPM_ERR_TRANS_NULL
, -1));
65 ASSERT(trans
->state
== STATE_INITIALIZED
,
66 RET_ERR(handle
, ALPM_ERR_TRANS_NOT_INITIALIZED
, -1));
69 pkgver
= pkg
->version
;
71 _alpm_log(handle
, ALPM_LOG_DEBUG
, "adding package '%s'\n", pkgname
);
73 if(_alpm_pkg_find(trans
->add
, pkgname
)) {
74 RET_ERR(handle
, ALPM_ERR_TRANS_DUP_TARGET
, -1);
77 local
= _alpm_db_get_pkgfromcache(handle
->db_local
, pkgname
);
79 const char *localpkgname
= alpm_pkg_get_name(local
);
80 const char *localpkgver
= alpm_pkg_get_version(local
);
81 int cmp
= _alpm_pkg_compare_versions(pkg
, local
);
84 if(trans
->flags
& ALPM_TRANS_FLAG_NEEDED
) {
85 /* with the NEEDED flag, packages up to date are not reinstalled */
86 _alpm_log(handle
, ALPM_LOG_WARNING
, _("%s-%s is up to date -- skipping\n"),
87 localpkgname
, localpkgver
);
89 } else if(!(trans
->flags
& ALPM_TRANS_FLAG_DOWNLOADONLY
)) {
90 _alpm_log(handle
, ALPM_LOG_WARNING
, _("%s-%s is up to date -- reinstalling\n"),
91 localpkgname
, localpkgver
);
94 /* local version is newer */
95 _alpm_log(handle
, ALPM_LOG_WARNING
, _("downgrading package %s (%s => %s)\n"),
96 localpkgname
, localpkgver
, pkgver
);
100 /* add the package to the transaction */
101 pkg
->reason
= ALPM_PKG_REASON_EXPLICIT
;
102 _alpm_log(handle
, ALPM_LOG_DEBUG
, "adding package %s-%s to the transaction add list\n",
104 trans
->add
= alpm_list_add(trans
->add
, pkg
);
109 static int perform_extraction(alpm_handle_t
*handle
, struct archive
*archive
,
110 struct archive_entry
*entry
, const char *filename
, const char *origname
)
113 const int archive_flags
= ARCHIVE_EXTRACT_OWNER
|
114 ARCHIVE_EXTRACT_PERM
|
115 ARCHIVE_EXTRACT_TIME
;
117 archive_entry_set_pathname(entry
, filename
);
119 ret
= archive_read_extract(archive
, entry
, archive_flags
);
120 if(ret
== ARCHIVE_WARN
&& archive_errno(archive
) != ENOSPC
) {
121 /* operation succeeded but a "non-critical" error was encountered */
122 _alpm_log(handle
, ALPM_LOG_WARNING
, _("warning given when extracting %s (%s)\n"),
123 origname
, archive_error_string(archive
));
124 } else if(ret
!= ARCHIVE_OK
) {
125 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not extract %s (%s)\n"),
126 origname
, archive_error_string(archive
));
127 alpm_logaction(handle
, "error: could not extract %s (%s)\n",
128 origname
, archive_error_string(archive
));
134 static int extract_single_file(alpm_handle_t
*handle
, struct archive
*archive
,
135 struct archive_entry
*entry
, alpm_pkg_t
*newpkg
, alpm_pkg_t
*oldpkg
)
137 const char *entryname
;
139 char filename
[PATH_MAX
]; /* the actual file we're extracting */
140 int needbackup
= 0, notouch
= 0;
141 const char *hash_orig
= NULL
;
142 char *entryname_orig
= NULL
;
145 entryname
= archive_entry_pathname(entry
);
146 entrymode
= archive_entry_mode(entry
);
148 memset(filename
, 0, PATH_MAX
); /* just to be sure */
150 if(strcmp(entryname
, ".INSTALL") == 0) {
151 /* the install script goes inside the db */
152 snprintf(filename
, PATH_MAX
, "%s%s-%s/install",
153 _alpm_db_path(handle
->db_local
), newpkg
->name
, newpkg
->version
);
154 archive_entry_set_perm(entry
, 0644);
155 } else if(strcmp(entryname
, ".CHANGELOG") == 0) {
156 /* the changelog goes inside the db */
157 snprintf(filename
, PATH_MAX
, "%s%s-%s/changelog",
158 _alpm_db_path(handle
->db_local
), newpkg
->name
, newpkg
->version
);
159 archive_entry_set_perm(entry
, 0644);
160 } else if(*entryname
== '.') {
161 /* for now, ignore all files starting with '.' that haven't
162 * already been handled (for future possibilities) */
163 _alpm_log(handle
, ALPM_LOG_DEBUG
, "skipping extraction of '%s'\n", entryname
);
164 archive_read_data_skip(archive
);
167 /* build the new entryname relative to handle->root */
168 snprintf(filename
, PATH_MAX
, "%s%s", handle
->root
, entryname
);
171 /* if a file is in NoExtract then we never extract it */
172 if(alpm_list_find_str(handle
->noextract
, entryname
)) {
173 _alpm_log(handle
, ALPM_LOG_DEBUG
, "%s is in NoExtract, skipping extraction\n",
175 alpm_logaction(handle
, "note: %s is in NoExtract, skipping extraction\n",
177 archive_read_data_skip(archive
);
181 /* Check for file existence. This is one of the more crucial parts
182 * to get 'right'. Here are the possibilities, with the filesystem
183 * on the left and the package on the top:
184 * (F=file, N=node, S=symlink, D=dir)
186 * non-existent | 1 | 2 | 3
191 * 1,2,3- extract, no magic necessary. lstat (_alpm_lstat) will fail here.
192 * 4,5,6,7,8- conflict checks should have caught this. either overwrite
193 * or backup the file.
194 * 9- follow the symlink, hopefully it is a directory, check it.
195 * 10- file replacing directory- don't allow it.
196 * 11- don't extract symlink- a dir exists here. we don't want links to
198 * 12- skip extraction, dir already exists.
201 /* do both a lstat and a stat, so we can see what symlinks point to */
202 struct stat lsbuf
, sbuf
;
203 if(_alpm_lstat(filename
, &lsbuf
) != 0 || stat(filename
, &sbuf
) != 0) {
204 /* cases 1,2,3: couldn't stat an existing file, skip all backup checks */
206 if(S_ISDIR(lsbuf
.st_mode
)) {
207 if(S_ISDIR(entrymode
)) {
208 /* case 12: existing dir, ignore it */
209 if(lsbuf
.st_mode
!= entrymode
) {
210 /* if filesystem perms are different than pkg perms, warn user */
212 _alpm_log(handle
, ALPM_LOG_WARNING
, _("directory permissions differ on %s\n"
213 "filesystem: %o package: %o\n"), entryname
, lsbuf
.st_mode
& mask
,
215 alpm_logaction(handle
, "warning: directory permissions differ on %s\n"
216 "filesystem: %o package: %o\n", entryname
, lsbuf
.st_mode
& mask
,
219 _alpm_log(handle
, ALPM_LOG_DEBUG
, "extract: skipping dir extraction of %s\n",
221 archive_read_data_skip(archive
);
224 /* case 10/11: trying to overwrite dir with file/symlink, don't allow it */
225 _alpm_log(handle
, ALPM_LOG_ERROR
, _("extract: not overwriting dir with file %s\n"),
227 archive_read_data_skip(archive
);
230 } else if(S_ISLNK(lsbuf
.st_mode
) && S_ISDIR(entrymode
)) {
231 /* case 9: existing symlink, dir in package */
232 if(S_ISDIR(sbuf
.st_mode
)) {
233 /* the symlink on FS is to a directory, so we'll use it */
234 _alpm_log(handle
, ALPM_LOG_DEBUG
, "extract: skipping symlink overwrite of %s\n",
236 archive_read_data_skip(archive
);
239 /* this is BAD. symlink was not to a directory */
240 _alpm_log(handle
, ALPM_LOG_ERROR
, _("extract: symlink %s does not point to dir\n"),
242 archive_read_data_skip(archive
);
245 } else if(S_ISREG(lsbuf
.st_mode
) && S_ISDIR(entrymode
)) {
246 /* case 6: trying to overwrite file with dir */
247 _alpm_log(handle
, ALPM_LOG_DEBUG
, "extract: overwriting file with dir %s\n",
249 } else if(S_ISREG(entrymode
)) {
251 /* if file is in NoUpgrade, don't touch it */
252 if(alpm_list_find_str(handle
->noupgrade
, entryname
)) {
255 alpm_backup_t
*backup
;
256 /* go to the backup array and see if our conflict is there */
257 /* check newpkg first, so that adding backup files is retroactive */
258 backup
= _alpm_needbackup(entryname
, alpm_pkg_get_backup(newpkg
));
260 /* if we force hash_orig to be non-NULL retroactive backup works */
265 /* check oldpkg for a backup entry, store the hash if available */
267 backup
= _alpm_needbackup(entryname
, alpm_pkg_get_backup(oldpkg
));
269 hash_orig
= backup
->hash
;
275 /* else if(S_ISLNK(entrymode)) */
276 /* case 5,8: don't need to do anything special */
279 /* we need access to the original entryname later after calls to
280 * archive_entry_set_pathname(), so we need to dupe it and free() later */
281 STRDUP(entryname_orig
, entryname
, RET_ERR(handle
, ALPM_ERR_MEMORY
, -1));
284 char checkfile
[PATH_MAX
];
285 char *hash_local
= NULL
, *hash_pkg
= NULL
;
288 snprintf(checkfile
, PATH_MAX
, "%s.paccheck", filename
);
290 ret
= perform_extraction(handle
, archive
, entry
, checkfile
, entryname_orig
);
293 FREE(entryname_orig
);
297 hash_local
= alpm_compute_md5sum(filename
);
298 hash_pkg
= alpm_compute_md5sum(checkfile
);
300 /* update the md5 hash in newpkg's backup (it will be the new orginal) */
302 for(i
= alpm_pkg_get_backup(newpkg
); i
; i
= i
->next
) {
303 alpm_backup_t
*backup
= i
->data
;
305 if(!backup
->name
|| strcmp(backup
->name
, entryname_orig
) != 0) {
308 STRDUP(newhash
, hash_pkg
, RET_ERR(handle
, ALPM_ERR_MEMORY
, -1));
310 backup
->hash
= newhash
;
313 _alpm_log(handle
, ALPM_LOG_DEBUG
, "checking hashes for %s\n", entryname_orig
);
314 _alpm_log(handle
, ALPM_LOG_DEBUG
, "current: %s\n", hash_local
);
315 _alpm_log(handle
, ALPM_LOG_DEBUG
, "new: %s\n", hash_pkg
);
316 _alpm_log(handle
, ALPM_LOG_DEBUG
, "original: %s\n", hash_orig
);
319 if(hash_local
&& hash_pkg
&& strcmp(hash_local
, hash_pkg
) != 0) {
320 /* looks like we have a local file that has a different hash as the
321 * file in the package, move it to a .pacorig */
322 char newpath
[PATH_MAX
];
323 snprintf(newpath
, PATH_MAX
, "%s.pacorig", filename
);
325 /* move the existing file to the "pacorig" */
326 if(rename(filename
, newpath
)) {
327 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not rename %s to %s (%s)\n"),
328 filename
, newpath
, strerror(errno
));
329 alpm_logaction(handle
, "error: could not rename %s to %s (%s)\n",
330 filename
, newpath
, strerror(errno
));
333 /* rename the file we extracted to the real name */
334 if(rename(checkfile
, filename
)) {
335 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not rename %s to %s (%s)\n"),
336 checkfile
, filename
, strerror(errno
));
337 alpm_logaction(handle
, "error: could not rename %s to %s (%s)\n",
338 checkfile
, filename
, strerror(errno
));
341 _alpm_log(handle
, ALPM_LOG_WARNING
, _("%s saved as %s\n"), filename
, newpath
);
342 alpm_logaction(handle
, "warning: %s saved as %s\n", filename
, newpath
);
346 /* local file is identical to pkg one, so just remove pkg one */
349 } else if(hash_orig
) {
352 if(hash_local
&& strcmp(hash_orig
, hash_local
) == 0) {
353 /* installed file has NOT been changed by user */
354 if(hash_pkg
&& strcmp(hash_orig
, hash_pkg
) != 0) {
355 _alpm_log(handle
, ALPM_LOG_DEBUG
, "action: installing new file: %s\n",
358 if(rename(checkfile
, filename
)) {
359 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not rename %s to %s (%s)\n"),
360 checkfile
, filename
, strerror(errno
));
361 alpm_logaction(handle
, "error: could not rename %s to %s (%s)\n",
362 checkfile
, filename
, strerror(errno
));
366 /* no sense in installing the same file twice, install
367 * ONLY if the original and package hashes differ */
368 _alpm_log(handle
, ALPM_LOG_DEBUG
, "action: leaving existing file in place\n");
371 } else if(hash_pkg
&& strcmp(hash_orig
, hash_pkg
) == 0) {
372 /* originally installed file and new file are the same - this
373 * implies the case above failed - i.e. the file was changed by a
375 _alpm_log(handle
, ALPM_LOG_DEBUG
, "action: leaving existing file in place\n");
377 } else if(hash_local
&& hash_pkg
&& strcmp(hash_local
, hash_pkg
) == 0) {
378 /* this would be magical. The above two cases failed, but the
379 * user changes just so happened to make the new file exactly the
380 * same as the one in the package... skip it */
381 _alpm_log(handle
, ALPM_LOG_DEBUG
, "action: leaving existing file in place\n");
384 char newpath
[PATH_MAX
];
385 _alpm_log(handle
, ALPM_LOG_DEBUG
, "action: keeping current file and installing"
386 " new one with .pacnew ending\n");
387 snprintf(newpath
, PATH_MAX
, "%s.pacnew", filename
);
388 if(rename(checkfile
, newpath
)) {
389 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not install %s as %s (%s)\n"),
390 filename
, newpath
, strerror(errno
));
391 alpm_logaction(handle
, "error: could not install %s as %s (%s)\n",
392 filename
, newpath
, strerror(errno
));
394 _alpm_log(handle
, ALPM_LOG_WARNING
, _("%s installed as %s\n"),
396 alpm_logaction(handle
, "warning: %s installed as %s\n",
407 /* we didn't need a backup */
409 /* change the path to a .pacnew extension */
410 _alpm_log(handle
, ALPM_LOG_DEBUG
, "%s is in NoUpgrade -- skipping\n", filename
);
411 _alpm_log(handle
, ALPM_LOG_WARNING
, _("extracting %s as %s.pacnew\n"), filename
, filename
);
412 alpm_logaction(handle
, "warning: extracting %s as %s.pacnew\n", filename
, filename
);
413 strncat(filename
, ".pacnew", PATH_MAX
- strlen(filename
));
415 _alpm_log(handle
, ALPM_LOG_DEBUG
, "extracting %s\n", filename
);
418 if(handle
->trans
->flags
& ALPM_TRANS_FLAG_FORCE
) {
419 /* if FORCE was used, unlink() each file (whether it's there
420 * or not) before extracting. This prevents the old "Text file busy"
421 * error that crops up if forcing a glibc or pacman upgrade. */
425 ret
= perform_extraction(handle
, archive
, entry
, filename
, entryname_orig
);
428 FREE(entryname_orig
);
432 /* calculate an hash if this is in newpkg's backup */
434 for(i
= alpm_pkg_get_backup(newpkg
); i
; i
= i
->next
) {
435 alpm_backup_t
*backup
= i
->data
;
437 if(!backup
->name
|| strcmp(backup
->name
, entryname_orig
) != 0) {
440 _alpm_log(handle
, ALPM_LOG_DEBUG
, "appending backup entry for %s\n", entryname_orig
);
441 newhash
= alpm_compute_md5sum(filename
);
443 backup
->hash
= newhash
;
446 FREE(entryname_orig
);
450 static int commit_single_pkg(alpm_handle_t
*handle
, alpm_pkg_t
*newpkg
,
451 size_t pkg_current
, size_t pkg_count
)
453 int i
, ret
= 0, errors
= 0;
454 char scriptlet
[PATH_MAX
];
456 alpm_pkg_t
*oldpkg
= NULL
;
457 alpm_db_t
*db
= handle
->db_local
;
458 alpm_trans_t
*trans
= handle
->trans
;
460 ASSERT(trans
!= NULL
, return -1);
462 snprintf(scriptlet
, PATH_MAX
, "%s%s-%s/install",
463 _alpm_db_path(db
), alpm_pkg_get_name(newpkg
),
464 alpm_pkg_get_version(newpkg
));
466 /* see if this is an upgrade. if so, remove the old package first */
467 alpm_pkg_t
*local
= _alpm_db_get_pkgfromcache(db
, newpkg
->name
);
471 /* we'll need to save some record for backup checks later */
472 oldpkg
= _alpm_pkg_dup(local
);
474 EVENT(trans
, ALPM_TRANS_EVT_UPGRADE_START
, newpkg
, oldpkg
);
475 _alpm_log(handle
, ALPM_LOG_DEBUG
, "upgrading package %s-%s\n",
476 newpkg
->name
, newpkg
->version
);
478 /* copy over the install reason */
479 newpkg
->reason
= alpm_pkg_get_reason(oldpkg
);
481 /* pre_upgrade scriptlet */
482 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& ALPM_TRANS_FLAG_NOSCRIPTLET
)) {
483 _alpm_runscriptlet(handle
, newpkg
->origin_data
.file
,
484 "pre_upgrade", newpkg
->version
, oldpkg
->version
);
489 EVENT(trans
, ALPM_TRANS_EVT_ADD_START
, newpkg
, NULL
);
490 _alpm_log(handle
, ALPM_LOG_DEBUG
, "adding package %s-%s\n",
491 newpkg
->name
, newpkg
->version
);
493 /* pre_install scriptlet */
494 if(alpm_pkg_has_scriptlet(newpkg
) && !(trans
->flags
& ALPM_TRANS_FLAG_NOSCRIPTLET
)) {
495 _alpm_runscriptlet(handle
, newpkg
->origin_data
.file
,
496 "pre_install", newpkg
->version
, NULL
);
500 /* we override any pre-set reason if we have alldeps or allexplicit set */
501 if(trans
->flags
& ALPM_TRANS_FLAG_ALLDEPS
) {
502 newpkg
->reason
= ALPM_PKG_REASON_DEPEND
;
503 } else if(trans
->flags
& ALPM_TRANS_FLAG_ALLEXPLICIT
) {
504 newpkg
->reason
= ALPM_PKG_REASON_EXPLICIT
;
508 /* set up fake remove transaction */
509 if(_alpm_remove_single_package(handle
, oldpkg
, newpkg
, 0, 0) == -1) {
510 handle
->pm_errno
= ALPM_ERR_TRANS_ABORT
;
516 /* prepare directory for database entries so permission are correct after
517 changelog/install script installation (FS#12263) */
518 if(_alpm_local_db_prepare(db
, newpkg
)) {
519 alpm_logaction(handle
, "error: could not create database entry %s-%s\n",
520 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
521 handle
->pm_errno
= ALPM_ERR_DB_WRITE
;
526 if(!(trans
->flags
& ALPM_TRANS_FLAG_DBONLY
)) {
527 struct archive
*archive
;
528 struct archive_entry
*entry
;
529 char cwd
[PATH_MAX
] = "";
532 _alpm_log(handle
, ALPM_LOG_DEBUG
, "extracting files\n");
534 if((archive
= archive_read_new()) == NULL
) {
535 handle
->pm_errno
= ALPM_ERR_LIBARCHIVE
;
540 archive_read_support_compression_all(archive
);
541 archive_read_support_format_all(archive
);
543 _alpm_log(handle
, ALPM_LOG_DEBUG
, "archive: %s\n", newpkg
->origin_data
.file
);
544 if(archive_read_open_filename(archive
, newpkg
->origin_data
.file
,
545 ARCHIVE_DEFAULT_BYTES_PER_BLOCK
) != ARCHIVE_OK
) {
546 handle
->pm_errno
= ALPM_ERR_PKG_OPEN
;
551 /* save the cwd so we can restore it later */
552 if(getcwd(cwd
, PATH_MAX
) == NULL
) {
553 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not get current working directory\n"));
558 /* libarchive requires this for extracting hard links */
559 if(chdir(handle
->root
) != 0) {
560 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not change directory to %s (%s)\n"),
561 handle
->root
, strerror(errno
));
566 /* call PROGRESS once with 0 percent, as we sort-of skip that here */
568 PROGRESS(trans
, ALPM_TRANS_PROGRESS_UPGRADE_START
,
569 alpm_pkg_get_name(newpkg
), 0, pkg_count
, pkg_current
);
571 PROGRESS(trans
, ALPM_TRANS_PROGRESS_ADD_START
,
572 alpm_pkg_get_name(newpkg
), 0, pkg_count
, pkg_current
);
575 for(i
= 0; archive_read_next_header(archive
, &entry
) == ARCHIVE_OK
; i
++) {
578 if(newpkg
->size
!= 0) {
579 /* Using compressed size for calculations here, as newpkg->isize is not
580 * exact when it comes to comparing to the ACTUAL uncompressed size
581 * (missing metadata sizes) */
582 int64_t pos
= archive_position_compressed(archive
);
583 percent
= (pos
* 100) / newpkg
->size
;
584 _alpm_log(handle
, ALPM_LOG_DEBUG
, "decompression progress: "
585 "%d%% (%"PRId64
" / %jd)\n",
586 percent
, pos
, (intmax_t)newpkg
->size
);
595 PROGRESS(trans
, ALPM_TRANS_PROGRESS_UPGRADE_START
,
596 alpm_pkg_get_name(newpkg
), percent
, pkg_count
,
599 PROGRESS(trans
, ALPM_TRANS_PROGRESS_ADD_START
,
600 alpm_pkg_get_name(newpkg
), percent
, pkg_count
,
604 /* extract the next file from the archive */
605 errors
+= extract_single_file(handle
, archive
, entry
, newpkg
, oldpkg
);
607 archive_read_finish(archive
);
609 /* restore the old cwd if we have it */
610 if(restore_cwd
&& chdir(cwd
) != 0) {
611 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not change directory to %s (%s)\n"), cwd
, strerror(errno
));
617 _alpm_log(handle
, ALPM_LOG_ERROR
, _("problem occurred while upgrading %s\n"),
619 alpm_logaction(handle
, "error: problem occurred while upgrading %s\n",
622 _alpm_log(handle
, ALPM_LOG_ERROR
, _("problem occurred while installing %s\n"),
624 alpm_logaction(handle
, "error: problem occurred while installing %s\n",
630 /* make an install date (in UTC) */
631 newpkg
->installdate
= time(NULL
);
633 _alpm_log(handle
, ALPM_LOG_DEBUG
, "updating database\n");
634 _alpm_log(handle
, ALPM_LOG_DEBUG
, "adding database entry '%s'\n", newpkg
->name
);
636 if(_alpm_local_db_write(db
, newpkg
, INFRQ_ALL
)) {
637 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not update database entry %s-%s\n"),
638 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
639 alpm_logaction(handle
, "error: could not update database entry %s-%s\n",
640 alpm_pkg_get_name(newpkg
), alpm_pkg_get_version(newpkg
));
641 handle
->pm_errno
= ALPM_ERR_DB_WRITE
;
646 if(_alpm_db_add_pkgincache(db
, newpkg
) == -1) {
647 _alpm_log(handle
, ALPM_LOG_ERROR
, _("could not add entry '%s' in cache\n"),
648 alpm_pkg_get_name(newpkg
));
652 PROGRESS(trans
, ALPM_TRANS_PROGRESS_UPGRADE_START
,
653 alpm_pkg_get_name(newpkg
), 100, pkg_count
, pkg_current
);
655 PROGRESS(trans
, ALPM_TRANS_PROGRESS_ADD_START
,
656 alpm_pkg_get_name(newpkg
), 100, pkg_count
, pkg_current
);
659 /* run the post-install script if it exists */
660 if(alpm_pkg_has_scriptlet(newpkg
)
661 && !(trans
->flags
& ALPM_TRANS_FLAG_NOSCRIPTLET
)) {
663 _alpm_runscriptlet(handle
, scriptlet
, "post_upgrade",
664 alpm_pkg_get_version(newpkg
),
665 oldpkg
? alpm_pkg_get_version(oldpkg
) : NULL
);
667 _alpm_runscriptlet(handle
, scriptlet
, "post_install",
668 alpm_pkg_get_version(newpkg
), NULL
);
673 EVENT(trans
, ALPM_TRANS_EVT_UPGRADE_DONE
, newpkg
, oldpkg
);
675 EVENT(trans
, ALPM_TRANS_EVT_ADD_DONE
, newpkg
, oldpkg
);
679 _alpm_pkg_free(oldpkg
);
683 int _alpm_upgrade_packages(alpm_handle_t
*handle
)
685 size_t pkg_count
, pkg_current
;
686 int skip_ldconfig
= 0, ret
= 0;
688 alpm_trans_t
*trans
= handle
->trans
;
690 if(trans
->add
== NULL
) {
694 pkg_count
= alpm_list_count(trans
->add
);
697 /* loop through our package list adding/upgrading one at a time */
698 for(targ
= trans
->add
; targ
; targ
= targ
->next
) {
699 alpm_pkg_t
*newpkg
= targ
->data
;
701 if(handle
->trans
->state
== STATE_INTERRUPTED
) {
705 if(commit_single_pkg(handle
, newpkg
, pkg_current
, pkg_count
)) {
706 /* something screwed up on the commit, abort the trans */
707 trans
->state
= STATE_INTERRUPTED
;
708 handle
->pm_errno
= ALPM_ERR_TRANS_ABORT
;
709 /* running ldconfig at this point could possibly screw system */
718 /* run ldconfig if it exists */
719 _alpm_ldconfig(handle
);
725 /* vim: set ts=2 sw=2 noet: */