Move important information up in -Si output
[pacman-ng.git] / src / pacman / package.c
blobfc869b180ef708c33551a75a706bfe931cc278c1
1 /*
2 * package.c
4 * Copyright (c) 2006-2012 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/>.
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <limits.h>
26 #include <errno.h>
27 #include <time.h>
29 #include <alpm.h>
30 #include <alpm_list.h>
32 /* pacman */
33 #include "package.h"
34 #include "util.h"
35 #include "conf.h"
37 #define CLBUF_SIZE 4096
39 /** Turn a depends list into a text list.
40 * @param deps a list with items of type alpm_depend_t
42 static void deplist_display(const char *title,
43 alpm_list_t *deps, unsigned short cols)
45 alpm_list_t *i, *text = NULL;
46 for(i = deps; i; i = alpm_list_next(i)) {
47 alpm_depend_t *dep = i->data;
48 text = alpm_list_add(text, alpm_dep_compute_string(dep));
50 list_display(title, text, cols);
51 FREELIST(text);
54 /** Turn a optdepends list into a text list.
55 * @param optdeps a list with items of type alpm_optdepend_t
57 static void optdeplist_display(const char *title,
58 alpm_list_t *optdeps, unsigned short cols)
60 alpm_list_t *i, *text = NULL;
61 for(i = optdeps; i; i = alpm_list_next(i)) {
62 alpm_depend_t *optdep = i->data;
63 text = alpm_list_add(text, alpm_dep_compute_string(optdep));
65 list_display_linebreak(title, text, cols);
66 FREELIST(text);
69 /**
70 * Display the details of a package.
71 * Extra information entails 'required by' info for sync packages and backup
72 * files info for local packages.
73 * @param pkg package to display information for
74 * @param from the type of package we are dealing with
75 * @param extra should we show extra information
77 void dump_pkg_full(alpm_pkg_t *pkg, int extra)
79 unsigned short cols;
80 time_t bdate, idate;
81 alpm_pkgfrom_t from;
82 double size;
83 char bdatestr[50] = "", idatestr[50] = "";
84 const char *label, *reason;
85 alpm_list_t *validation = NULL, *requiredby = NULL;
87 from = alpm_pkg_get_origin(pkg);
89 /* set variables here, do all output below */
90 bdate = (time_t)alpm_pkg_get_builddate(pkg);
91 if(bdate) {
92 strftime(bdatestr, 50, "%c", localtime(&bdate));
94 idate = (time_t)alpm_pkg_get_installdate(pkg);
95 if(idate) {
96 strftime(idatestr, 50, "%c", localtime(&idate));
99 switch(alpm_pkg_get_reason(pkg)) {
100 case ALPM_PKG_REASON_EXPLICIT:
101 reason = _("Explicitly installed");
102 break;
103 case ALPM_PKG_REASON_DEPEND:
104 reason = _("Installed as a dependency for another package");
105 break;
106 default:
107 reason = _("Unknown");
108 break;
111 alpm_pkgvalidation_t v = alpm_pkg_get_validation(pkg);
112 if(v) {
113 if(v & ALPM_PKG_VALIDATION_NONE) {
114 validation = alpm_list_add(validation, _("None"));
115 } else {
116 if(v & ALPM_PKG_VALIDATION_MD5SUM) {
117 validation = alpm_list_add(validation, _("MD5 Sum"));
119 if(v & ALPM_PKG_VALIDATION_SHA256SUM) {
120 validation = alpm_list_add(validation, _("SHA256 Sum"));
122 if(v & ALPM_PKG_VALIDATION_SIGNATURE) {
123 validation = alpm_list_add(validation, _("Signature"));
126 } else {
127 validation = alpm_list_add(validation, _("Unknown"));
130 if(extra || from == ALPM_PKG_FROM_LOCALDB) {
131 /* compute this here so we don't get a pause in the middle of output */
132 requiredby = alpm_pkg_compute_requiredby(pkg);
135 cols = getcols(fileno(stdout));
137 /* actual output */
138 if(from == ALPM_PKG_FROM_SYNCDB) {
139 string_display(_("Repository :"),
140 alpm_db_get_name(alpm_pkg_get_db(pkg)), cols);
142 string_display(_("Name :"), alpm_pkg_get_name(pkg), cols);
143 string_display(_("Version :"), alpm_pkg_get_version(pkg), cols);
144 string_display(_("Description :"), alpm_pkg_get_desc(pkg), cols);
145 string_display(_("Architecture :"), alpm_pkg_get_arch(pkg), cols);
146 string_display(_("URL :"), alpm_pkg_get_url(pkg), cols);
147 list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg), cols);
148 list_display(_("Groups :"), alpm_pkg_get_groups(pkg), cols);
149 deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg), cols);
150 deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg), cols);
151 optdeplist_display(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg), cols);
152 if(extra || from == ALPM_PKG_FROM_LOCALDB) {
153 list_display(_("Required By :"), requiredby, cols);
155 deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg), cols);
156 deplist_display(_("Replaces :"), alpm_pkg_get_replaces(pkg), cols);
158 size = humanize_size(alpm_pkg_get_size(pkg), 'K', 2, &label);
159 if(from == ALPM_PKG_FROM_SYNCDB) {
160 printf(_("Download Size : %6.2f %s\n"), size, label);
161 } else if(from == ALPM_PKG_FROM_FILE) {
162 printf(_("Compressed Size: %6.2f %s\n"), size, label);
165 size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 2, &label);
166 printf(_("Installed Size : %6.2f %s\n"), size, label);
168 string_display(_("Packager :"), alpm_pkg_get_packager(pkg), cols);
169 string_display(_("Build Date :"), bdatestr, cols);
170 if(from == ALPM_PKG_FROM_LOCALDB) {
171 string_display(_("Install Date :"), idatestr, cols);
172 string_display(_("Install Reason :"), reason, cols);
174 if(from == ALPM_PKG_FROM_FILE || from == ALPM_PKG_FROM_LOCALDB) {
175 string_display(_("Install Script :"),
176 alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No"), cols);
179 if(from == ALPM_PKG_FROM_SYNCDB && extra) {
180 string_display(_("MD5 Sum :"), alpm_pkg_get_md5sum(pkg), cols);
181 string_display(_("SHA256 Sum :"), alpm_pkg_get_sha256sum(pkg), cols);
182 string_display(_("Signatures :"),
183 alpm_pkg_get_base64_sig(pkg) ? _("Yes") : _("None"), cols);
184 } else {
185 list_display(_("Validated By :"), validation, cols);
188 if(from == ALPM_PKG_FROM_FILE) {
189 alpm_siglist_t siglist;
190 int err = alpm_pkg_check_pgp_signature(pkg, &siglist);
191 if(err && alpm_errno(config->handle) == ALPM_ERR_SIG_MISSING) {
192 string_display(_("Signatures :"), _("None"), cols);
193 } else if(err) {
194 string_display(_("Signatures :"),
195 alpm_strerror(alpm_errno(config->handle)), cols);
196 } else {
197 signature_display(_("Signatures :"), &siglist, cols);
199 alpm_siglist_cleanup(&siglist);
202 /* Print additional package info if info flag passed more than once */
203 if(from == ALPM_PKG_FROM_LOCALDB && extra) {
204 dump_pkg_backups(pkg);
207 /* final newline to separate packages */
208 printf("\n");
210 FREELIST(requiredby);
211 alpm_list_free(validation);
214 static const char *get_backup_file_status(const char *root,
215 const alpm_backup_t *backup)
217 char path[PATH_MAX];
218 const char *ret;
220 snprintf(path, PATH_MAX, "%s%s", root, backup->name);
222 /* if we find the file, calculate checksums, otherwise it is missing */
223 if(access(path, R_OK) == 0) {
224 char *md5sum = alpm_compute_md5sum(path);
226 if(md5sum == NULL) {
227 pm_printf(ALPM_LOG_ERROR,
228 _("could not calculate checksums for %s\n"), path);
229 return NULL;
232 /* if checksums don't match, file has been modified */
233 if(strcmp(md5sum, backup->hash) != 0) {
234 ret = "MODIFIED";
235 } else {
236 ret = "UNMODIFIED";
238 free(md5sum);
239 } else {
240 switch(errno) {
241 case EACCES:
242 ret = "UNREADABLE";
243 break;
244 case ENOENT:
245 ret = "MISSING";
246 break;
247 default:
248 ret = "UNKNOWN";
251 return ret;
254 /* Display list of backup files and their modification states
256 void dump_pkg_backups(alpm_pkg_t *pkg)
258 alpm_list_t *i;
259 const char *root = alpm_option_get_root(config->handle);
260 printf(_("Backup Files:\n"));
261 if(alpm_pkg_get_backup(pkg)) {
262 /* package has backup files, so print them */
263 for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) {
264 const alpm_backup_t *backup = i->data;
265 const char *value;
266 if(!backup->hash) {
267 continue;
269 value = get_backup_file_status(root, backup);
270 printf("%s\t%s%s\n", value, root, backup->name);
272 } else {
273 /* package had no backup files */
274 printf(_("(none)\n"));
278 /* List all files contained in a package
280 void dump_pkg_files(alpm_pkg_t *pkg, int quiet)
282 const char *pkgname, *root;
283 alpm_filelist_t *pkgfiles;
284 size_t i;
286 pkgname = alpm_pkg_get_name(pkg);
287 pkgfiles = alpm_pkg_get_files(pkg);
288 root = alpm_option_get_root(config->handle);
290 for(i = 0; i < pkgfiles->count; i++) {
291 const alpm_file_t *file = pkgfiles->files + i;
292 /* Regular: '<pkgname> <root><filepath>\n'
293 * Quiet : '<root><filepath>\n'
295 if(!quiet) {
296 fputs(pkgname, stdout);
297 putchar(' ');
299 fputs(root, stdout);
300 fputs(file->name, stdout);
301 putchar('\n');
304 fflush(stdout);
307 /* Display the changelog of a package
309 void dump_pkg_changelog(alpm_pkg_t *pkg)
311 void *fp = NULL;
313 if((fp = alpm_pkg_changelog_open(pkg)) == NULL) {
314 pm_printf(ALPM_LOG_ERROR, _("no changelog available for '%s'.\n"),
315 alpm_pkg_get_name(pkg));
316 return;
317 } else {
318 /* allocate a buffer to get the changelog back in chunks */
319 char buf[CLBUF_SIZE];
320 size_t ret = 0;
321 while((ret = alpm_pkg_changelog_read(buf, CLBUF_SIZE, pkg, fp))) {
322 if(ret < CLBUF_SIZE) {
323 /* if we hit the end of the file, we need to add a null terminator */
324 *(buf + ret) = '\0';
326 fputs(buf, stdout);
328 alpm_pkg_changelog_close(pkg, fp);
329 putchar('\n');
333 /* vim: set ts=2 sw=2 noet: */