2005-03-14 20:51:43 -05:00
|
|
|
/*
|
|
|
|
* package.c
|
2007-11-16 21:18:45 -05:00
|
|
|
*
|
2011-01-05 23:45:15 -05:00
|
|
|
* Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org>
|
2009-07-01 03:08:33 -04:00
|
|
|
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
|
2007-11-16 21:18:45 -05:00
|
|
|
*
|
2005-03-14 20:51:43 -05:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2007-12-10 23:55:22 -05:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2005-03-14 20:51:43 -05:00
|
|
|
*/
|
|
|
|
|
2007-03-05 17:13:33 -05:00
|
|
|
#include "config.h"
|
|
|
|
|
2005-03-14 20:51:43 -05:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2008-06-15 20:15:36 -04:00
|
|
|
#include <unistd.h>
|
2005-03-20 17:03:30 -05:00
|
|
|
#include <limits.h>
|
2011-01-22 12:38:34 -05:00
|
|
|
#include <errno.h>
|
2005-03-14 20:51:43 -05:00
|
|
|
|
|
|
|
#include <alpm.h>
|
2007-01-22 03:46:12 -05:00
|
|
|
#include <alpm_list.h>
|
2007-03-05 17:13:33 -05:00
|
|
|
|
2005-03-14 20:51:43 -05:00
|
|
|
/* pacman */
|
2007-03-05 17:13:33 -05:00
|
|
|
#include "package.h"
|
2005-03-14 20:51:43 -05:00
|
|
|
#include "util.h"
|
2011-06-07 14:15:43 -04:00
|
|
|
#include "conf.h"
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2007-12-09 00:42:04 -05:00
|
|
|
#define CLBUF_SIZE 4096
|
|
|
|
|
2011-04-21 20:51:51 -04:00
|
|
|
/**
|
|
|
|
* Display the details of a package.
|
|
|
|
* Extra information entails 'required by' info for sync packages and backup
|
|
|
|
* files info for local packages.
|
|
|
|
* @param pkg package to display information for
|
|
|
|
* @param from the type of package we are dealing with
|
|
|
|
* @param extra should we show extra information
|
2005-03-14 20:51:43 -05:00
|
|
|
*/
|
2011-06-28 09:26:39 -04:00
|
|
|
void dump_pkg_full(alpm_pkg_t *pkg, enum pkg_from from, int extra)
|
2005-03-14 20:51:43 -05:00
|
|
|
{
|
2008-07-31 07:38:30 -04:00
|
|
|
const char *reason;
|
2007-09-19 01:21:56 -04:00
|
|
|
time_t bdate, idate;
|
2007-11-23 16:32:40 -05:00
|
|
|
char bdatestr[50] = "", idatestr[50] = "";
|
2011-02-20 13:38:32 -05:00
|
|
|
const char *label;
|
|
|
|
double size;
|
2007-11-13 01:37:11 -05:00
|
|
|
const alpm_list_t *i;
|
2007-11-29 17:16:13 -05:00
|
|
|
alpm_list_t *requiredby = NULL, *depstrings = NULL;
|
2005-03-14 20:51:43 -05:00
|
|
|
|
|
|
|
if(pkg == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-01-17 00:25:32 -05:00
|
|
|
/* set variables here, do all output below */
|
|
|
|
bdate = alpm_pkg_get_builddate(pkg);
|
2007-11-23 16:32:40 -05:00
|
|
|
if(bdate) {
|
|
|
|
strftime(bdatestr, 50, "%c", localtime(&bdate));
|
|
|
|
}
|
2007-01-17 00:25:32 -05:00
|
|
|
idate = alpm_pkg_get_installdate(pkg);
|
2007-11-23 16:32:40 -05:00
|
|
|
if(idate) {
|
|
|
|
strftime(idatestr, 50, "%c", localtime(&idate));
|
|
|
|
}
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2006-11-20 04:10:23 -05:00
|
|
|
switch((long)alpm_pkg_get_reason(pkg)) {
|
2011-07-01 12:01:38 -04:00
|
|
|
case ALPM_PKG_REASON_EXPLICIT:
|
2007-01-22 03:52:18 -05:00
|
|
|
reason = _("Explicitly installed");
|
2005-03-14 20:51:43 -05:00
|
|
|
break;
|
2011-07-01 12:01:38 -04:00
|
|
|
case ALPM_PKG_REASON_DEPEND:
|
2007-01-22 03:52:18 -05:00
|
|
|
reason = _("Installed as a dependency for another package");
|
2005-03-14 20:51:43 -05:00
|
|
|
break;
|
|
|
|
default:
|
2007-01-22 03:52:18 -05:00
|
|
|
reason = _("Unknown");
|
2005-03-14 20:51:43 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-11-13 01:37:11 -05:00
|
|
|
/* turn depends list into a text list */
|
|
|
|
for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) {
|
2011-06-28 00:29:55 -04:00
|
|
|
alpm_depend_t *dep = (alpm_depend_t *)alpm_list_getdata(i);
|
2008-08-26 06:57:08 -04:00
|
|
|
depstrings = alpm_list_add(depstrings, alpm_dep_compute_string(dep));
|
2007-11-13 01:37:11 -05:00
|
|
|
}
|
|
|
|
|
2011-04-21 20:51:51 -04:00
|
|
|
if(extra || from == PKG_FROM_LOCALDB) {
|
2009-09-16 15:22:11 -04:00
|
|
|
/* compute this here so we don't get a pause in the middle of output */
|
2007-11-29 17:16:13 -05:00
|
|
|
requiredby = alpm_pkg_compute_requiredby(pkg);
|
|
|
|
}
|
|
|
|
|
2007-01-17 00:25:32 -05:00
|
|
|
/* actual output */
|
2011-04-21 20:51:51 -04:00
|
|
|
if(from == PKG_FROM_SYNCDB) {
|
|
|
|
string_display(_("Repository :"),
|
|
|
|
alpm_db_get_name(alpm_pkg_get_db(pkg)));
|
|
|
|
}
|
2007-11-23 16:32:40 -05:00
|
|
|
string_display(_("Name :"), alpm_pkg_get_name(pkg));
|
|
|
|
string_display(_("Version :"), alpm_pkg_get_version(pkg));
|
|
|
|
string_display(_("URL :"), alpm_pkg_get_url(pkg));
|
|
|
|
list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg));
|
2007-01-25 21:13:16 -05:00
|
|
|
list_display(_("Groups :"), alpm_pkg_get_groups(pkg));
|
|
|
|
list_display(_("Provides :"), alpm_pkg_get_provides(pkg));
|
2007-11-13 01:37:11 -05:00
|
|
|
list_display(_("Depends On :"), depstrings);
|
2008-07-31 09:58:25 -04:00
|
|
|
list_display_linebreak(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg));
|
2011-04-21 20:51:51 -04:00
|
|
|
if(extra || from == PKG_FROM_LOCALDB) {
|
2007-11-12 20:40:08 -05:00
|
|
|
list_display(_("Required By :"), requiredby);
|
2007-01-29 23:15:14 -05:00
|
|
|
}
|
2007-01-25 21:13:16 -05:00
|
|
|
list_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg));
|
2007-04-04 21:01:55 -04:00
|
|
|
list_display(_("Replaces :"), alpm_pkg_get_replaces(pkg));
|
2011-02-20 13:38:32 -05:00
|
|
|
|
|
|
|
size = humanize_size(alpm_pkg_get_size(pkg), 'K', 1, &label);
|
2011-04-21 20:51:51 -04:00
|
|
|
if(from == PKG_FROM_SYNCDB) {
|
2011-02-20 13:38:32 -05:00
|
|
|
printf(_("Download Size : %6.2f %s\n"), size, label);
|
2011-04-21 20:51:51 -04:00
|
|
|
} else if(from == PKG_FROM_FILE) {
|
2011-02-20 13:38:32 -05:00
|
|
|
printf(_("Compressed Size: %6.2f %s\n"), size, label);
|
2007-11-23 16:32:40 -05:00
|
|
|
}
|
|
|
|
|
2011-02-20 13:38:32 -05:00
|
|
|
size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 1, &label);
|
|
|
|
printf(_("Installed Size : %6.2f %s\n"), size, label);
|
|
|
|
|
2007-11-23 16:32:40 -05:00
|
|
|
string_display(_("Packager :"), alpm_pkg_get_packager(pkg));
|
|
|
|
string_display(_("Architecture :"), alpm_pkg_get_arch(pkg));
|
|
|
|
string_display(_("Build Date :"), bdatestr);
|
2011-04-21 20:51:51 -04:00
|
|
|
if(from == PKG_FROM_LOCALDB) {
|
2007-11-23 16:32:40 -05:00
|
|
|
string_display(_("Install Date :"), idatestr);
|
|
|
|
string_display(_("Install Reason :"), reason);
|
|
|
|
}
|
2011-04-21 20:51:51 -04:00
|
|
|
if(from == PKG_FROM_FILE || from == PKG_FROM_LOCALDB) {
|
2007-11-23 16:32:40 -05:00
|
|
|
string_display(_("Install Script :"),
|
|
|
|
alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No"));
|
|
|
|
}
|
|
|
|
|
2011-04-21 20:51:51 -04:00
|
|
|
if(from == PKG_FROM_SYNCDB) {
|
2007-11-23 16:32:40 -05:00
|
|
|
string_display(_("MD5 Sum :"), alpm_pkg_get_md5sum(pkg));
|
2011-08-13 14:40:41 -04:00
|
|
|
string_display(_("Signatures :"), alpm_pkg_get_base64_sig(pkg) ? _("Yes") : _("No"));
|
2007-01-29 23:15:14 -05:00
|
|
|
}
|
2011-07-01 17:50:32 -04:00
|
|
|
if(from == PKG_FROM_FILE) {
|
|
|
|
alpm_sigresult_t result;
|
|
|
|
int err = alpm_pkg_check_pgp_signature(pkg, &result);
|
|
|
|
if(err) {
|
|
|
|
string_display(_("Signatures :"),
|
|
|
|
alpm_strerror(alpm_errno(config->handle)));
|
|
|
|
} else {
|
|
|
|
signature_display(_("Signatures :"), &result);
|
|
|
|
}
|
|
|
|
alpm_sigresult_cleanup(&result);
|
|
|
|
}
|
2008-07-31 07:38:30 -04:00
|
|
|
string_display(_("Description :"), alpm_pkg_get_desc(pkg));
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2007-01-17 00:25:32 -05:00
|
|
|
/* Print additional package info if info flag passed more than once */
|
2011-04-21 20:51:51 -04:00
|
|
|
if(from == PKG_FROM_LOCALDB && extra) {
|
2007-02-07 20:12:48 -05:00
|
|
|
dump_pkg_backups(pkg);
|
2005-03-20 17:03:30 -05:00
|
|
|
}
|
2007-11-13 01:37:11 -05:00
|
|
|
|
2008-08-28 14:55:26 -04:00
|
|
|
/* final newline to separate packages */
|
|
|
|
printf("\n");
|
|
|
|
|
2007-11-13 01:37:11 -05:00
|
|
|
FREELIST(depstrings);
|
2009-10-07 22:52:09 -04:00
|
|
|
FREELIST(requiredby);
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
2011-01-12 01:05:22 -05:00
|
|
|
static const char *get_backup_file_status(const char *root,
|
2011-06-28 00:39:43 -04:00
|
|
|
const alpm_backup_t *backup)
|
2011-01-12 01:05:22 -05:00
|
|
|
{
|
|
|
|
char path[PATH_MAX];
|
2011-05-04 16:48:47 -04:00
|
|
|
const char *ret;
|
2011-01-12 01:05:22 -05:00
|
|
|
|
2011-06-16 14:15:11 -04:00
|
|
|
snprintf(path, PATH_MAX, "%s%s", root, backup->name);
|
2011-01-12 01:05:22 -05:00
|
|
|
|
|
|
|
/* if we find the file, calculate checksums, otherwise it is missing */
|
|
|
|
if(access(path, R_OK) == 0) {
|
|
|
|
char *md5sum = alpm_compute_md5sum(path);
|
|
|
|
|
|
|
|
if(md5sum == NULL) {
|
2011-07-01 12:01:38 -04:00
|
|
|
pm_fprintf(stderr, ALPM_LOG_ERROR,
|
2011-01-12 01:05:22 -05:00
|
|
|
_("could not calculate checksums for %s\n"), path);
|
2011-03-20 20:45:57 -04:00
|
|
|
return NULL;
|
2011-01-12 01:05:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* if checksums don't match, file has been modified */
|
2011-06-16 14:15:11 -04:00
|
|
|
if(strcmp(md5sum, backup->hash) != 0) {
|
2011-01-12 01:06:39 -05:00
|
|
|
ret = "MODIFIED";
|
2011-01-12 01:05:22 -05:00
|
|
|
} else {
|
2011-01-12 01:06:39 -05:00
|
|
|
ret = "UNMODIFIED";
|
2011-01-12 01:05:22 -05:00
|
|
|
}
|
|
|
|
free(md5sum);
|
|
|
|
} else {
|
2011-01-22 12:38:34 -05:00
|
|
|
switch(errno) {
|
|
|
|
case EACCES:
|
|
|
|
ret = "UNREADABLE";
|
|
|
|
break;
|
|
|
|
case ENOENT:
|
|
|
|
ret = "MISSING";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = "UNKNOWN";
|
|
|
|
}
|
2011-01-12 01:05:22 -05:00
|
|
|
}
|
2011-03-20 20:45:57 -04:00
|
|
|
return ret;
|
2011-01-12 01:05:22 -05:00
|
|
|
}
|
|
|
|
|
2007-01-17 00:25:32 -05:00
|
|
|
/* Display list of backup files and their modification states
|
|
|
|
*/
|
2011-06-28 09:26:39 -04:00
|
|
|
void dump_pkg_backups(alpm_pkg_t *pkg)
|
2007-01-17 00:25:32 -05:00
|
|
|
{
|
2007-01-19 04:28:44 -05:00
|
|
|
alpm_list_t *i;
|
2011-06-07 14:15:43 -04:00
|
|
|
const char *root = alpm_option_get_root(config->handle);
|
2007-02-19 21:14:27 -05:00
|
|
|
printf(_("Backup Files:\n"));
|
|
|
|
if(alpm_pkg_get_backup(pkg)) {
|
|
|
|
/* package has backup files, so print them */
|
|
|
|
for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) {
|
2011-06-28 00:39:43 -04:00
|
|
|
const alpm_backup_t *backup = alpm_list_getdata(i);
|
2011-01-12 01:05:22 -05:00
|
|
|
const char *value;
|
2011-06-16 14:15:11 -04:00
|
|
|
if(!backup->hash) {
|
2007-01-17 00:25:32 -05:00
|
|
|
continue;
|
|
|
|
}
|
2011-06-16 14:15:11 -04:00
|
|
|
value = get_backup_file_status(root, backup);
|
|
|
|
printf("%s\t%s%s\n", value, root, backup->name);
|
2007-01-17 00:25:32 -05:00
|
|
|
}
|
2007-02-19 21:14:27 -05:00
|
|
|
} else {
|
|
|
|
/* package had no backup files */
|
|
|
|
printf(_("(none)\n"));
|
2007-01-17 00:25:32 -05:00
|
|
|
}
|
|
|
|
}
|
2007-11-16 21:18:45 -05:00
|
|
|
|
2007-01-17 00:25:32 -05:00
|
|
|
/* List all files contained in a package
|
|
|
|
*/
|
2011-06-28 09:26:39 -04:00
|
|
|
void dump_pkg_files(alpm_pkg_t *pkg, int quiet)
|
2005-03-14 20:51:43 -05:00
|
|
|
{
|
2011-06-16 14:16:49 -04:00
|
|
|
const char *pkgname, *root;
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
alpm_filelist_t *pkgfiles;
|
|
|
|
size_t i;
|
2005-03-14 20:51:43 -05:00
|
|
|
|
2006-11-20 04:10:23 -05:00
|
|
|
pkgname = alpm_pkg_get_name(pkg);
|
|
|
|
pkgfiles = alpm_pkg_get_files(pkg);
|
2011-06-07 14:15:43 -04:00
|
|
|
root = alpm_option_get_root(config->handle);
|
2005-03-14 20:51:43 -05:00
|
|
|
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 05:47:29 -04:00
|
|
|
for(i = 0; i < pkgfiles->count; i++) {
|
|
|
|
const alpm_file_t *file = pkgfiles->files + i;
|
|
|
|
if(!quiet) {
|
2011-06-16 14:16:49 -04:00
|
|
|
fprintf(stdout, "%s %s%s\n", pkgname, root, file->name);
|
2009-05-10 16:41:29 -04:00
|
|
|
} else {
|
2011-06-16 14:16:49 -04:00
|
|
|
fprintf(stdout, "%s%s\n", root, file->name);
|
2009-05-10 16:41:29 -04:00
|
|
|
}
|
2005-03-14 20:51:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|
2007-12-09 00:42:04 -05:00
|
|
|
/* Display the changelog of a package
|
2006-10-15 15:34:52 -04:00
|
|
|
*/
|
2011-06-28 09:26:39 -04:00
|
|
|
void dump_pkg_changelog(alpm_pkg_t *pkg)
|
2006-10-15 15:34:52 -04:00
|
|
|
{
|
2007-12-09 00:42:04 -05:00
|
|
|
void *fp = NULL;
|
2006-10-15 15:34:52 -04:00
|
|
|
|
2007-12-09 00:42:04 -05:00
|
|
|
if((fp = alpm_pkg_changelog_open(pkg)) == NULL) {
|
2011-07-01 12:01:38 -04:00
|
|
|
pm_fprintf(stderr, ALPM_LOG_ERROR, _("no changelog available for '%s'.\n"),
|
2007-12-09 00:42:04 -05:00
|
|
|
alpm_pkg_get_name(pkg));
|
2006-10-15 15:34:52 -04:00
|
|
|
return;
|
2007-12-09 00:42:04 -05:00
|
|
|
} else {
|
|
|
|
/* allocate a buffer to get the changelog back in chunks */
|
|
|
|
char buf[CLBUF_SIZE];
|
2011-01-07 22:06:06 -05:00
|
|
|
size_t ret = 0;
|
2007-12-09 00:42:04 -05:00
|
|
|
while((ret = alpm_pkg_changelog_read(buf, CLBUF_SIZE, pkg, fp))) {
|
|
|
|
if(ret < CLBUF_SIZE) {
|
|
|
|
/* if we hit the end of the file, we need to add a null terminator */
|
|
|
|
*(buf + ret) = '\0';
|
|
|
|
}
|
|
|
|
printf("%s", buf);
|
2006-10-15 15:34:52 -04:00
|
|
|
}
|
2007-12-09 00:42:04 -05:00
|
|
|
alpm_pkg_changelog_close(pkg, fp);
|
|
|
|
printf("\n");
|
2006-10-15 15:34:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-14 20:51:43 -05:00
|
|
|
/* vim: set ts=2 sw=2 noet: */
|