Hook new optdepend structures up
[pacman-ng.git] / src / pacman / package.c
blob54c035c3d9a3db0e09ba21680415c1d8454663ea
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)
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);
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)
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);
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 const char *reason;
80 time_t bdate, idate;
81 char bdatestr[50] = "", idatestr[50] = "";
82 const char *label;
83 double size;
84 alpm_list_t *requiredby = NULL;
85 alpm_pkgfrom_t from;
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 if(extra || from == PKG_FROM_LOCALDB) {
112 /* compute this here so we don't get a pause in the middle of output */
113 requiredby = alpm_pkg_compute_requiredby(pkg);
116 /* actual output */
117 if(from == PKG_FROM_SYNCDB) {
118 string_display(_("Repository :"),
119 alpm_db_get_name(alpm_pkg_get_db(pkg)));
121 string_display(_("Name :"), alpm_pkg_get_name(pkg));
122 string_display(_("Version :"), alpm_pkg_get_version(pkg));
123 string_display(_("URL :"), alpm_pkg_get_url(pkg));
124 list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg));
125 list_display(_("Groups :"), alpm_pkg_get_groups(pkg));
126 deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg));
127 deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg));
128 optdeplist_display(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg));
129 if(extra || from == PKG_FROM_LOCALDB) {
130 list_display(_("Required By :"), requiredby);
132 deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg));
133 deplist_display(_("Replaces :"), alpm_pkg_get_replaces(pkg));
135 size = humanize_size(alpm_pkg_get_size(pkg), 'K', 2, &label);
136 if(from == PKG_FROM_SYNCDB) {
137 printf(_("Download Size : %6.2f %s\n"), size, label);
138 } else if(from == PKG_FROM_FILE) {
139 printf(_("Compressed Size: %6.2f %s\n"), size, label);
142 size = humanize_size(alpm_pkg_get_isize(pkg), 'K', 2, &label);
143 printf(_("Installed Size : %6.2f %s\n"), size, label);
145 string_display(_("Packager :"), alpm_pkg_get_packager(pkg));
146 string_display(_("Architecture :"), alpm_pkg_get_arch(pkg));
147 string_display(_("Build Date :"), bdatestr);
148 if(from == PKG_FROM_LOCALDB) {
149 string_display(_("Install Date :"), idatestr);
150 string_display(_("Install Reason :"), reason);
152 if(from == PKG_FROM_FILE || from == PKG_FROM_LOCALDB) {
153 string_display(_("Install Script :"),
154 alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No"));
157 if(from == PKG_FROM_SYNCDB) {
158 string_display(_("MD5 Sum :"), alpm_pkg_get_md5sum(pkg));
159 string_display(_("SHA256 Sum :"), alpm_pkg_get_sha256sum(pkg));
160 string_display(_("Signatures :"),
161 alpm_pkg_get_base64_sig(pkg) ? _("Yes") : _("None"));
163 if(from == PKG_FROM_FILE) {
164 alpm_siglist_t siglist;
165 int err = alpm_pkg_check_pgp_signature(pkg, &siglist);
166 if(err && alpm_errno(config->handle) == ALPM_ERR_SIG_MISSING) {
167 string_display(_("Signatures :"), _("None"));
168 } else if(err) {
169 string_display(_("Signatures :"),
170 alpm_strerror(alpm_errno(config->handle)));
171 } else {
172 signature_display(_("Signatures :"), &siglist);
174 alpm_siglist_cleanup(&siglist);
176 string_display(_("Description :"), alpm_pkg_get_desc(pkg));
178 /* Print additional package info if info flag passed more than once */
179 if(from == PKG_FROM_LOCALDB && extra) {
180 dump_pkg_backups(pkg);
183 /* final newline to separate packages */
184 printf("\n");
186 FREELIST(requiredby);
189 static const char *get_backup_file_status(const char *root,
190 const alpm_backup_t *backup)
192 char path[PATH_MAX];
193 const char *ret;
195 snprintf(path, PATH_MAX, "%s%s", root, backup->name);
197 /* if we find the file, calculate checksums, otherwise it is missing */
198 if(access(path, R_OK) == 0) {
199 char *md5sum = alpm_compute_md5sum(path);
201 if(md5sum == NULL) {
202 pm_printf(ALPM_LOG_ERROR,
203 _("could not calculate checksums for %s\n"), path);
204 return NULL;
207 /* if checksums don't match, file has been modified */
208 if(strcmp(md5sum, backup->hash) != 0) {
209 ret = "MODIFIED";
210 } else {
211 ret = "UNMODIFIED";
213 free(md5sum);
214 } else {
215 switch(errno) {
216 case EACCES:
217 ret = "UNREADABLE";
218 break;
219 case ENOENT:
220 ret = "MISSING";
221 break;
222 default:
223 ret = "UNKNOWN";
226 return ret;
229 /* Display list of backup files and their modification states
231 void dump_pkg_backups(alpm_pkg_t *pkg)
233 alpm_list_t *i;
234 const char *root = alpm_option_get_root(config->handle);
235 printf(_("Backup Files:\n"));
236 if(alpm_pkg_get_backup(pkg)) {
237 /* package has backup files, so print them */
238 for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) {
239 const alpm_backup_t *backup = i->data;
240 const char *value;
241 if(!backup->hash) {
242 continue;
244 value = get_backup_file_status(root, backup);
245 printf("%s\t%s%s\n", value, root, backup->name);
247 } else {
248 /* package had no backup files */
249 printf(_("(none)\n"));
253 /* List all files contained in a package
255 void dump_pkg_files(alpm_pkg_t *pkg, int quiet)
257 const char *pkgname, *root;
258 alpm_filelist_t *pkgfiles;
259 size_t i;
261 pkgname = alpm_pkg_get_name(pkg);
262 pkgfiles = alpm_pkg_get_files(pkg);
263 root = alpm_option_get_root(config->handle);
265 for(i = 0; i < pkgfiles->count; i++) {
266 const alpm_file_t *file = pkgfiles->files + i;
267 /* Regular: '<pkgname> <root><filepath>\n'
268 * Quiet : '<root><filepath>\n'
270 if(!quiet) {
271 fputs(pkgname, stdout);
272 putchar(' ');
274 fputs(root, stdout);
275 fputs(file->name, stdout);
276 putchar('\n');
279 fflush(stdout);
282 /* Display the changelog of a package
284 void dump_pkg_changelog(alpm_pkg_t *pkg)
286 void *fp = NULL;
288 if((fp = alpm_pkg_changelog_open(pkg)) == NULL) {
289 pm_printf(ALPM_LOG_ERROR, _("no changelog available for '%s'.\n"),
290 alpm_pkg_get_name(pkg));
291 return;
292 } else {
293 /* allocate a buffer to get the changelog back in chunks */
294 char buf[CLBUF_SIZE];
295 size_t ret = 0;
296 while((ret = alpm_pkg_changelog_read(buf, CLBUF_SIZE, pkg, fp))) {
297 if(ret < CLBUF_SIZE) {
298 /* if we hit the end of the file, we need to add a null terminator */
299 *(buf + ret) = '\0';
301 fputs(buf, stdout);
303 alpm_pkg_changelog_close(pkg, fp);
304 putchar('\n');
308 /* vim: set ts=2 sw=2 noet: */