libalpm
Arch Linux Package Manager Library
|
00001 /* 00002 * package.c 00003 * 00004 * Copyright (c) 2006-2011 Pacman Development Team <pacman-dev@archlinux.org> 00005 * Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org> 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include <stdlib.h> 00022 #include <stdio.h> 00023 #include <string.h> 00024 #include <unistd.h> 00025 #include <limits.h> 00026 #include <errno.h> 00027 #include <time.h> 00028 00029 #include <alpm.h> 00030 #include <alpm_list.h> 00031 00032 /* pacman */ 00033 #include "package.h" 00034 #include "util.h" 00035 #include "conf.h" 00036 00037 #define CLBUF_SIZE 4096 00038 00039 /** Turn a depends list into a text list. 00040 * @param deps a list with items of type alpm_depend_t 00041 * @return a string list, must be freed 00042 */ 00043 static void deplist_display(const char *title, 00044 alpm_list_t *deps) 00045 { 00046 alpm_list_t *i, *text = NULL; 00047 for(i = deps; i; i = alpm_list_next(i)) { 00048 alpm_depend_t *dep = i->data; 00049 text = alpm_list_add(text, alpm_dep_compute_string(dep)); 00050 } 00051 list_display(title, text); 00052 FREELIST(text); 00053 } 00054 00055 /** 00056 * Display the details of a package. 00057 * Extra information entails 'required by' info for sync packages and backup 00058 * files info for local packages. 00059 * @param pkg package to display information for 00060 * @param from the type of package we are dealing with 00061 * @param extra should we show extra information 00062 */ 00063 void dump_pkg_full(alpm_pkg_t *pkg, int extra) 00064 { 00065 const char *reason; 00066 time_t bdate, idate; 00067 char bdatestr[50] = "", idatestr[50] = ""; 00068 const char *label; 00069 double size; 00070 alpm_list_t *requiredby = NULL; 00071 alpm_pkgfrom_t from; 00072 00073 from = alpm_pkg_get_origin(pkg); 00074 00075 /* set variables here, do all output below */ 00076 bdate = (time_t)alpm_pkg_get_builddate(pkg); 00077 if(bdate) { 00078 strftime(bdatestr, 50, "%c", localtime(&bdate)); 00079 } 00080 idate = (time_t)alpm_pkg_get_installdate(pkg); 00081 if(idate) { 00082 strftime(idatestr, 50, "%c", localtime(&idate)); 00083 } 00084 00085 switch(alpm_pkg_get_reason(pkg)) { 00086 case ALPM_PKG_REASON_EXPLICIT: 00087 reason = _("Explicitly installed"); 00088 break; 00089 case ALPM_PKG_REASON_DEPEND: 00090 reason = _("Installed as a dependency for another package"); 00091 break; 00092 default: 00093 reason = _("Unknown"); 00094 break; 00095 } 00096 00097 if(extra || from == PKG_FROM_LOCALDB) { 00098 /* compute this here so we don't get a pause in the middle of output */ 00099 requiredby = alpm_pkg_compute_requiredby(pkg); 00100 } 00101 00102 /* actual output */ 00103 if(from == PKG_FROM_SYNCDB) { 00104 string_display(_("Repository :"), 00105 alpm_db_get_name(alpm_pkg_get_db(pkg))); 00106 } 00107 string_display(_("Name :"), alpm_pkg_get_name(pkg)); 00108 string_display(_("Version :"), alpm_pkg_get_version(pkg)); 00109 string_display(_("URL :"), alpm_pkg_get_url(pkg)); 00110 list_display(_("Licenses :"), alpm_pkg_get_licenses(pkg)); 00111 list_display(_("Groups :"), alpm_pkg_get_groups(pkg)); 00112 deplist_display(_("Provides :"), alpm_pkg_get_provides(pkg)); 00113 deplist_display(_("Depends On :"), alpm_pkg_get_depends(pkg)); 00114 list_display_linebreak(_("Optional Deps :"), alpm_pkg_get_optdepends(pkg)); 00115 if(extra || from == PKG_FROM_LOCALDB) { 00116 list_display(_("Required By :"), requiredby); 00117 } 00118 deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg)); 00119 deplist_display(_("Replaces :"), alpm_pkg_get_replaces(pkg)); 00120 00121 size = humanize_size(alpm_pkg_get_size(pkg), 'K', &label); 00122 if(from == PKG_FROM_SYNCDB) { 00123 printf(_("Download Size : %6.2f %s\n"), size, label); 00124 } else if(from == PKG_FROM_FILE) { 00125 printf(_("Compressed Size: %6.2f %s\n"), size, label); 00126 } 00127 00128 size = humanize_size(alpm_pkg_get_isize(pkg), 'K', &label); 00129 printf(_("Installed Size : %6.2f %s\n"), size, label); 00130 00131 string_display(_("Packager :"), alpm_pkg_get_packager(pkg)); 00132 string_display(_("Architecture :"), alpm_pkg_get_arch(pkg)); 00133 string_display(_("Build Date :"), bdatestr); 00134 if(from == PKG_FROM_LOCALDB) { 00135 string_display(_("Install Date :"), idatestr); 00136 string_display(_("Install Reason :"), reason); 00137 } 00138 if(from == PKG_FROM_FILE || from == PKG_FROM_LOCALDB) { 00139 string_display(_("Install Script :"), 00140 alpm_pkg_has_scriptlet(pkg) ? _("Yes") : _("No")); 00141 } 00142 00143 if(from == PKG_FROM_SYNCDB) { 00144 string_display(_("MD5 Sum :"), alpm_pkg_get_md5sum(pkg)); 00145 string_display(_("SHA256 Sum :"), alpm_pkg_get_sha256sum(pkg)); 00146 string_display(_("Signatures :"), 00147 alpm_pkg_get_base64_sig(pkg) ? _("Yes") : _("None")); 00148 } 00149 if(from == PKG_FROM_FILE) { 00150 alpm_siglist_t siglist; 00151 int err = alpm_pkg_check_pgp_signature(pkg, &siglist); 00152 if(err && alpm_errno(config->handle) == ALPM_ERR_SIG_MISSING) { 00153 string_display(_("Signatures :"), _("None")); 00154 } else if(err) { 00155 string_display(_("Signatures :"), 00156 alpm_strerror(alpm_errno(config->handle))); 00157 } else { 00158 signature_display(_("Signatures :"), &siglist); 00159 } 00160 alpm_siglist_cleanup(&siglist); 00161 } 00162 string_display(_("Description :"), alpm_pkg_get_desc(pkg)); 00163 00164 /* Print additional package info if info flag passed more than once */ 00165 if(from == PKG_FROM_LOCALDB && extra) { 00166 dump_pkg_backups(pkg); 00167 } 00168 00169 /* final newline to separate packages */ 00170 printf("\n"); 00171 00172 FREELIST(requiredby); 00173 } 00174 00175 static const char *get_backup_file_status(const char *root, 00176 const alpm_backup_t *backup) 00177 { 00178 char path[PATH_MAX]; 00179 const char *ret; 00180 00181 snprintf(path, PATH_MAX, "%s%s", root, backup->name); 00182 00183 /* if we find the file, calculate checksums, otherwise it is missing */ 00184 if(access(path, R_OK) == 0) { 00185 char *md5sum = alpm_compute_md5sum(path); 00186 00187 if(md5sum == NULL) { 00188 pm_printf(ALPM_LOG_ERROR, 00189 _("could not calculate checksums for %s\n"), path); 00190 return NULL; 00191 } 00192 00193 /* if checksums don't match, file has been modified */ 00194 if(strcmp(md5sum, backup->hash) != 0) { 00195 ret = "MODIFIED"; 00196 } else { 00197 ret = "UNMODIFIED"; 00198 } 00199 free(md5sum); 00200 } else { 00201 switch(errno) { 00202 case EACCES: 00203 ret = "UNREADABLE"; 00204 break; 00205 case ENOENT: 00206 ret = "MISSING"; 00207 break; 00208 default: 00209 ret = "UNKNOWN"; 00210 } 00211 } 00212 return ret; 00213 } 00214 00215 /* Display list of backup files and their modification states 00216 */ 00217 void dump_pkg_backups(alpm_pkg_t *pkg) 00218 { 00219 alpm_list_t *i; 00220 const char *root = alpm_option_get_root(config->handle); 00221 printf(_("Backup Files:\n")); 00222 if(alpm_pkg_get_backup(pkg)) { 00223 /* package has backup files, so print them */ 00224 for(i = alpm_pkg_get_backup(pkg); i; i = alpm_list_next(i)) { 00225 const alpm_backup_t *backup = i->data; 00226 const char *value; 00227 if(!backup->hash) { 00228 continue; 00229 } 00230 value = get_backup_file_status(root, backup); 00231 printf("%s\t%s%s\n", value, root, backup->name); 00232 } 00233 } else { 00234 /* package had no backup files */ 00235 printf(_("(none)\n")); 00236 } 00237 } 00238 00239 /* List all files contained in a package 00240 */ 00241 void dump_pkg_files(alpm_pkg_t *pkg, int quiet) 00242 { 00243 const char *pkgname, *root; 00244 alpm_filelist_t *pkgfiles; 00245 size_t i; 00246 00247 pkgname = alpm_pkg_get_name(pkg); 00248 pkgfiles = alpm_pkg_get_files(pkg); 00249 root = alpm_option_get_root(config->handle); 00250 00251 for(i = 0; i < pkgfiles->count; i++) { 00252 const alpm_file_t *file = pkgfiles->files + i; 00253 /* Regular: '<pkgname> <root><filepath>\n' 00254 * Quiet : '<root><filepath>\n' 00255 */ 00256 if(!quiet) { 00257 fputs(pkgname, stdout); 00258 putchar(' '); 00259 } 00260 fputs(root, stdout); 00261 fputs(file->name, stdout); 00262 putchar('\n'); 00263 } 00264 00265 fflush(stdout); 00266 } 00267 00268 /* Display the changelog of a package 00269 */ 00270 void dump_pkg_changelog(alpm_pkg_t *pkg) 00271 { 00272 void *fp = NULL; 00273 00274 if((fp = alpm_pkg_changelog_open(pkg)) == NULL) { 00275 pm_printf(ALPM_LOG_ERROR, _("no changelog available for '%s'.\n"), 00276 alpm_pkg_get_name(pkg)); 00277 return; 00278 } else { 00279 /* allocate a buffer to get the changelog back in chunks */ 00280 char buf[CLBUF_SIZE]; 00281 size_t ret = 0; 00282 while((ret = alpm_pkg_changelog_read(buf, CLBUF_SIZE, pkg, fp))) { 00283 if(ret < CLBUF_SIZE) { 00284 /* if we hit the end of the file, we need to add a null terminator */ 00285 *(buf + ret) = '\0'; 00286 } 00287 fputs(buf, stdout); 00288 } 00289 alpm_pkg_changelog_close(pkg, fp); 00290 putchar('\n'); 00291 } 00292 } 00293 00294 /* vim: set ts=2 sw=2 noet: */