Exemple #1
0
static alpm_list_t *get_pkg_dep_names(alpm_pkg_t *pkg)
{
	alpm_list_t *i, *names = NULL;
	for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) {
		alpm_depend_t *d = i->data;
		names = alpm_list_add(names, d->name);
	}
	return names;
}
Exemple #2
0
/** Check if pkg2 satisfies a dependency of pkg1 */
static int _alpm_pkg_depends_on(alpm_pkg_t *pkg1, alpm_pkg_t *pkg2)
{
	alpm_list_t *i;
	for(i = alpm_pkg_get_depends(pkg1); i; i = i->next) {
		if(_alpm_depcmp(pkg2, i->data)) {
			return 1;
		}
	}
	return 0;
}
static gboolean
asb_package_alpm_ensure_depends (AsbPackage *pkg, GError **error)
{
	AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
	AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
	alpm_list_t *alpm_depends;
	alpm_list_t *current;

	alpm_depends = alpm_pkg_get_depends (priv->package);
	for (current = alpm_depends; current; current = alpm_list_next (current))
		asb_package_add_dep (pkg, current->data);

	return TRUE;
}
Exemple #4
0
static int check_depends(alpm_pkg_t *p)
{
	int ret = 0;
	alpm_list_t *i;
	for(i = alpm_pkg_get_depends(p); i; i = alpm_list_next(i)) {
		char *depstring = alpm_dep_compute_string(i->data);
		if(!alpm_find_satisfier(pkgcache, depstring)) {
			eprintf("%s: unsatisfied dependency '%s'\n",
					alpm_pkg_get_name(p), depstring);
			ret = 1;
		}
		free(depstring);
	}
	if(!quiet && !ret) {
		eprintf("%s: all dependencies satisfied\n", alpm_pkg_get_name(p));
	}
	return ret;
}
Exemple #5
0
void add_deps(alpm_pkg_t *pkg)
{
	alpm_list_t *i;
	for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) {
		char *depstring = alpm_dep_compute_string(i->data);
		alpm_pkg_t *p = alpm_find_satisfier(pkgcache, depstring);
		if(p && !alpm_list_find_ptr(packages, p)) {
			packages = alpm_list_add(packages, p);
			add_deps(p);
		}
		free(depstring);
	}
	if(checks & CHECK_OPT_DEPENDS) {
		for(i = alpm_pkg_get_optdepends(pkg); i; i = alpm_list_next(i)) {
			char *depstring = alpm_dep_compute_string(i->data);
			alpm_pkg_t *p = alpm_find_satisfier(pkgcache, depstring);
			if(p && !alpm_list_find_ptr(packages, p)) {
				packages = alpm_list_add(packages, p);
				add_deps(p);
			}
			free(depstring);
		}
	}
}
Exemple #6
0
/** Checks dependencies and returns missing ones in a list.
 * Dependencies can include versions with depmod operators.
 * @param handle the context handle
 * @param pkglist the list of local packages
 * @param remove an alpm_list_t* of packages to be removed
 * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade)
 * @param reversedeps handles the backward dependencies
 * @return an alpm_list_t* of alpm_depmissing_t pointers.
 */
alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle,
		alpm_list_t *pkglist, alpm_list_t *rem, alpm_list_t *upgrade,
		int reversedeps)
{
	alpm_list_t *i, *j;
	alpm_list_t *dblist = NULL, *modified = NULL;
	alpm_list_t *baddeps = NULL;
	int nodepversion;

	CHECK_HANDLE(handle, return NULL);

	for(i = pkglist; i; i = i->next) {
		alpm_pkg_t *pkg = i->data;
		if(alpm_pkg_find(rem, pkg->name) || alpm_pkg_find(upgrade, pkg->name)) {
			modified = alpm_list_add(modified, pkg);
		} else {
			dblist = alpm_list_add(dblist, pkg);
		}
	}

	nodepversion = no_dep_version(handle);

	/* look for unsatisfied dependencies of the upgrade list */
	for(i = upgrade; i; i = i->next) {
		alpm_pkg_t *tp = i->data;
		_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: package %s-%s\n",
				tp->name, tp->version);

		for(j = alpm_pkg_get_depends(tp); j; j = j->next) {
			alpm_depend_t *depend = j->data;
			depend = filtered_depend(depend, nodepversion);
			/* 1. we check the upgrade list */
			/* 2. we check database for untouched satisfying packages */
			if(!find_dep_satisfier(upgrade, depend) &&
					!find_dep_satisfier(dblist, depend)) {
				/* Unsatisfied dependency in the upgrade list */
				alpm_depmissing_t *miss;
				char *missdepstring = alpm_dep_compute_string(depend);
				_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n",
						missdepstring, tp->name);
				free(missdepstring);
				miss = depmiss_new(tp->name, depend, NULL);
				baddeps = alpm_list_add(baddeps, miss);
			}
			release_filtered_depend(depend, nodepversion);
		}
	}

	if(reversedeps) {
		/* reversedeps handles the backwards dependencies, ie,
		 * the packages listed in the requiredby field. */
		for(i = dblist; i; i = i->next) {
			alpm_pkg_t *lp = i->data;
			for(j = alpm_pkg_get_depends(lp); j; j = j->next) {
				alpm_depend_t *depend = j->data;
				depend = filtered_depend(depend, nodepversion);
				alpm_pkg_t *causingpkg = find_dep_satisfier(modified, depend);
				/* we won't break this depend, if it is already broken, we ignore it */
				/* 1. check upgrade list for satisfiers */
				/* 2. check dblist for satisfiers */
				if(causingpkg &&
				   !find_dep_satisfier(upgrade, depend) &&
				   !find_dep_satisfier(dblist, depend)) {
					alpm_depmissing_t *miss;
					char *missdepstring = alpm_dep_compute_string(depend);
					_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n",
							missdepstring, lp->name);
					free(missdepstring);
					miss = depmiss_new(lp->name, depend, causingpkg->name);
					baddeps = alpm_list_add(baddeps, miss);
				}
				release_filtered_depend(depend, nodepversion);
			}
		}
	}

	alpm_list_free(modified);
	alpm_list_free(dblist);

	return baddeps;
}
Exemple #7
0
static int print_pkg(alpm_pkg_t *pkg, const char *format) {
  const char *f, *end;
  char fmt[64], buf[64];
  int len, out = 0;

  end = format + strlen(format);

  for (f = format; f < end; f++) {
    len = 0;
    if (*f == '%') {
      len = strspn(f + 1 + len, printf_flags);
      len += strspn(f + 1 + len, digits);
      snprintf(fmt, len + 3, "%ss", f);
      fmt[len + 1] = 's';
      f += len + 1;
      switch (*f) {
        /* simple attributes */
        case 'f': /* filename */
          out += printf(fmt, alpm_pkg_get_filename(pkg));
          break;
        case 'n': /* package name */
          out += printf(fmt, alpm_pkg_get_name(pkg));
          break;
        case 'v': /* version */
          out += printf(fmt, alpm_pkg_get_version(pkg));
          break;
        case 'd': /* description */
          out += printf(fmt, alpm_pkg_get_desc(pkg));
          break;
        case 'u': /* project url */
          out += printf(fmt, alpm_pkg_get_url(pkg));
          break;
        case 'p': /* packager name */
          out += printf(fmt, alpm_pkg_get_packager(pkg));
          break;
        case 's': /* md5sum */
          out += printf(fmt, alpm_pkg_get_md5sum(pkg));
          break;
        case 'a': /* architecutre */
          out += printf(fmt, alpm_pkg_get_arch(pkg));
          break;
        case 'i': /* has install scriptlet? */
          out += printf(fmt, alpm_pkg_has_scriptlet(pkg) ? "yes" : "no");
          break;
        case 'r': /* repo */
          out += printf(fmt, alpm_db_get_name(alpm_pkg_get_db(pkg)));
          break;
        case 'w': /* install reason */
          out += printf(fmt, alpm_pkg_get_reason(pkg) ? "dependency" : "explicit");
          break;
        case '!': /* result number */
          snprintf(buf, sizeof(buf), "%d", opt_pkgcounter++);
          out += printf(fmt, buf);
          break;
        case 'g': /* base64 gpg sig */
          out += printf(fmt, alpm_pkg_get_base64_sig(pkg));
          break;
        case 'h': /* sha256sum */
          out += printf(fmt, alpm_pkg_get_sha256sum(pkg));
          break;

        /* times */
        case 'b': /* build date */
          out += print_time(alpm_pkg_get_builddate(pkg));
          break;
        case 'l': /* install date */
          out += print_time(alpm_pkg_get_installdate(pkg));
          break;

        /* sizes */
        case 'k': /* download size */
          out += printf(fmt, size_to_string(alpm_pkg_get_size(pkg)));
          break;
        case 'm': /* install size */
          out += printf(fmt, size_to_string(alpm_pkg_get_isize(pkg)));
          break;

        /* lists */
        case 'F': /* files */
          out += print_filelist(alpm_pkg_get_files(pkg));
          break;
        case 'N': /* requiredby */
          out += print_list(alpm_pkg_compute_requiredby(pkg), NULL);
          break;
        case 'L': /* licenses */
          out += print_list(alpm_pkg_get_licenses(pkg), NULL);
          break;
        case 'G': /* groups */
          out += print_list(alpm_pkg_get_groups(pkg), NULL);
          break;
        case 'E': /* depends (shortdeps) */
          out += print_list(alpm_pkg_get_depends(pkg), (extractfn)alpm_dep_get_name);
          break;
        case 'D': /* depends */
          out += print_list(alpm_pkg_get_depends(pkg), (extractfn)alpm_dep_compute_string);
          break;
        case 'O': /* optdepends */
          out += print_list(alpm_pkg_get_optdepends(pkg), (extractfn)format_optdep);
          break;
        case 'o': /* optdepends (shortdeps) */
          out += print_list(alpm_pkg_get_optdepends(pkg), (extractfn)alpm_dep_get_name);
          break;
        case 'C': /* conflicts */
          out += print_list(alpm_pkg_get_conflicts(pkg), (extractfn)alpm_dep_get_name);
          break;
        case 'S': /* provides (shortdeps) */
          out += print_list(alpm_pkg_get_provides(pkg), (extractfn)alpm_dep_get_name);
          break;
        case 'P': /* provides */
          out += print_list(alpm_pkg_get_provides(pkg), (extractfn)alpm_dep_compute_string);
          break;
        case 'R': /* replaces */
          out += print_list(alpm_pkg_get_replaces(pkg), (extractfn)alpm_dep_get_name);
          break;
        case 'B': /* backup */
          out += print_list(alpm_pkg_get_backup(pkg), alpm_backup_get_name);
          break;
        case 'V': /* package validation */
          out += print_allocated_list(get_validation_method(pkg), NULL);
          break;
        case 'M': /* modified */
          out += print_allocated_list(get_modified_files(pkg), NULL);
          break;
        case '%':
          fputc('%', stdout);
          out++;
          break;
        default:
          fputc('?', stdout);
          out++;
          break;
      }
    } else if (*f == '\\') {
      char esc[3] = { f[0], f[1], '\0' };
      out += print_escaped(esc);
      ++f;
    } else {
      fputc(*f, stdout);
      out++;
    }
  }

  /* only print a delimeter if any package data was outputted */
  if (out > 0) {
    print_escaped(opt_delim);
  }

  return !out;
}
Exemple #8
0
/* Resolve dependencies for a given package
 * @param curl curl handle
 * @param hashdb hash database
 * @param curpkg current package we are resolving
 * @param dep_list pointer to list to store resulting dependencies
 * @param resolve_lvl level of dep resolution. RESOLVE_THOROUGH forces
 *        downloading of AUR PKGBUILDs
 *
 * returns -1 on error, 0 on success
 */
static int crawl_resolve(CURL *curl, struct pw_hashdb *hashdb, struct pkgpair *curpkg,
                         alpm_list_t **dep_list, int resolve_lvl)
{
    alpm_list_t *i, *depmod_list, *deps = NULL;
    struct pkgpair *pkgpair;
    struct pkgpair tmppkg;
    void *pkg_provides;
    void *memlist_ptr;
    const char *cache_result;
    const char *depname, *final_pkgname;
    char cwd[PATH_MAX];
    char buf[PATH_MAX];

    /* Normalize package before doing anything else */
    final_pkgname = normalize_package(curl, hashdb, curpkg->pkgname, resolve_lvl);
    if (!final_pkgname) {
        return -1;
    }

    enum pkgfrom_t *from = hashmap_search(hashdb->pkg_from, (void *) final_pkgname);
    if (!from) {
        die("Failed to find out where package \"%s\" is from!\n", final_pkgname);
    }

    switch (*from) {
    case PKG_FROM_LOCAL:
        tmppkg.pkgname = final_pkgname;
        pkgpair = hash_search(hashdb->local, &tmppkg);
        goto get_deps;
    case PKG_FROM_SYNC:
        tmppkg.pkgname = final_pkgname;
        pkgpair = hash_search(hashdb->sync, &tmppkg);
        goto get_deps;
    default:
        goto aur_deps;
    }

aur_uptodate:
    tmppkg.pkgname = final_pkgname;
    tmppkg.pkg = NULL;
    pkgpair = hash_search(hashdb->aur, &tmppkg);

get_deps:
    if (!pkgpair) {
        /* Shouldn't happen */
        die("Unable to find package \"%s\" in local/sync db!", final_pkgname);
    }

    depmod_list = alpm_pkg_get_depends(pkgpair->pkg);
    for (i = depmod_list; i; i = i->next) {
        char *s = alpm_dep_compute_string(i->data);
        strncpy(buf, s, sizeof(buf));
        free(s);
        chompversion(buf);
        depname = normalize_package(curl, hashdb, buf, resolve_lvl);
        /* Possibility of normalize_package fail due to AUR download failing */
        if (!depname) {
            alpm_list_free(deps);
            return -1;
        }
        deps = alpm_list_add(deps, (void *) depname);
    }

    if (dep_list) {
        *dep_list = deps;
    } else {
        alpm_list_free(deps);
    }

    return 0;

aur_deps:
    tmppkg.pkgname = final_pkgname;
    tmppkg.pkg = NULL;

    /* For installed AUR packages which are up to date */
    if (resolve_lvl != RESOLVE_THOROUGH) {
        if (hash_search(hashdb->aur, &tmppkg) &&
                !hash_search(hashdb->aur_outdated, (void *) final_pkgname)) {
            /* NOTE: top goto ! */
            goto aur_uptodate;
        }
    }

    /* RESOLVE_THOROUGH / out to date AUR package.
     * Download pkgbuild and extract deps */
    if (!getcwd(cwd, PATH_MAX)) {
        return error(PW_ERR_GETCWD);
    }

    if (chdir(final_pkgname)) {
        return error(PW_ERR_CHDIR);
    }

    deps = grab_dependencies("PKGBUILD");
    if (chdir(cwd)) {
        alpm_list_free(deps);
        return error(PW_ERR_RESTORECWD);
    }

    if (dep_list) {
        const char *normdep;
        alpm_list_t *new_deps = NULL;

        /* Transfer control to memlist and normalize packages */
        for (i = deps; i; i = i->next) {
            memlist_ptr = memlist_add(hashdb->strpool, &i->data);
            normdep = normalize_package(curl, hashdb, memlist_ptr, resolve_lvl);
            new_deps = alpm_list_add(new_deps, (void *) normdep);
        }

        *dep_list = new_deps;
    }

    alpm_list_free(deps);
    return 0;
}
Exemple #9
0
void pacman_pkgdump(pmpkg_t *pkg, enum pkgfrom_t from)
{
	static const char *datefmt = "%a %d %b %Y %I:%M:%S %p %Z";

	alpm_list_t *i, *results = NULL;
	pmdb_t *db;
	pmdepend_t *dep;
	pmpkgreason_t reason;

	int has_script;
	time_t inst_time;
	struct tm tm_st;

	char installdate[60];
	char builddate[60];

	db = alpm_pkg_get_db(pkg);
	if (!db) {
		return;
	}

	memset(&tm_st, 0, sizeof(struct tm));
	inst_time = alpm_pkg_get_builddate(pkg);
	localtime_r(&inst_time, &tm_st);
	strftime(builddate, 60, datefmt, &tm_st);

	/* Local pkg specific */
	if (from == PKG_FROM_LOCAL) {
		has_script = alpm_pkg_has_scriptlet(pkg);
		reason = alpm_pkg_get_reason(pkg);

		memset(&tm_st, 0, sizeof(struct tm));
		inst_time = alpm_pkg_get_installdate(pkg);
		localtime_r(&inst_time, &tm_st);
		strftime(installdate, 60, datefmt, &tm_st);
	}

	if (from == PKG_FROM_SYNC) {
		printf("%s%s ", color.bold, REPO);
		const char *repo = alpm_db_get_name(db);
		if (!strcmp(repo, "core")) {
			printf("%s", color.bred);
		} else if (!strcmp(repo, "extra")) {
			printf("%s", color.bgreen);
		} else {
			printf("%s", color.bmag);
		}

		printf("%s%s\n", repo, color.nocolor);
	}

	printf("%s%s%s %s%s%s\n", color.bold, NAME, color.nocolor,
		   color.bold, alpm_pkg_get_name(pkg), color.nocolor);
	printf("%s%s %s%s%s\n", color.bold, VERSION, color.bgreen,
		   alpm_pkg_get_version(pkg), color.nocolor);
	printf("%s%s %s%s%s\n", color.bold, URL, color.bcyan,
		   alpm_pkg_get_url(pkg), color.nocolor);

	print_list_prefix(alpm_pkg_get_licenses(pkg), LICENSES);
	print_list_prefix(alpm_pkg_get_groups(pkg), GROUPS);
	print_list_prefix(alpm_pkg_get_provides(pkg), PROVIDES);

	print_list_deps(alpm_pkg_get_depends(pkg), DEPS);
	print_list_break(alpm_pkg_get_optdepends(pkg), OPTDEPS);

	if (from == PKG_FROM_LOCAL) {
		results = alpm_pkg_compute_requiredby(pkg);
		print_list_prefix(results, REQBY);
	}

	print_list_prefix(alpm_pkg_get_conflicts(pkg), CONFLICTS);
	print_list_prefix(alpm_pkg_get_replaces(pkg), REPLACES);

	if (from == PKG_FROM_SYNC) {
		humanize_size(alpm_pkg_get_size(pkg), DLSZ);
	}

	humanize_size(alpm_pkg_get_isize(pkg), INSTSZ);
	printf("%s%s%s %s\n", color.bold, PKGER, color.nocolor,
		   alpm_pkg_get_packager(pkg));
	printf("%s%s%s %s\n", color.bold, ARCH, color.nocolor, alpm_pkg_get_arch(pkg));
	printf("%s%s%s %s\n", color.bold, BDATE, color.nocolor, builddate);

	if (from == PKG_FROM_LOCAL) {
		printf("%s%s%s %s\n", color.bold, IDATE, color.nocolor, installdate);

		printf("%s%s%s ", color.bold, REASON, color.nocolor);
		switch (reason) {
		case PM_PKG_REASON_EXPLICIT:
			printf("Explicitly installed");
			break;
		case PM_PKG_REASON_DEPEND:
			printf("Installed as a dependency for another package");
			break;
		default:
			printf("Unknown");
			break;
		}

		printf("\n");
		printf("%s%s%s %s\n", color.bold, SCRIPT, color.nocolor,
			   has_script ? "Yes" : "No");
	}

	if (from == PKG_FROM_SYNC) {
		printf("%s%s%s %s\n", color.bold, MD5SUM, color.nocolor,
			   alpm_pkg_get_md5sum(pkg));
	}

	printf("%s%s%s %s\n", color.bold, DESC, color.nocolor, alpm_pkg_get_desc(pkg));
	FREELIST(results);
}
Exemple #10
0
/**
 * 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
 */
void dump_pkg_full(alpm_pkg_t *pkg, int extra)
{
    unsigned short cols;
    time_t bdate, idate;
    alpm_pkgfrom_t from;
    double size;
    char bdatestr[50] = "", idatestr[50] = "";
    const char *label, *reason;
    alpm_list_t *validation = NULL, *requiredby = NULL, *optionalfor = NULL;

    from = alpm_pkg_get_origin(pkg);

    /* set variables here, do all output below */
    bdate = (time_t)alpm_pkg_get_builddate(pkg);
    if(bdate) {
        strftime(bdatestr, 50, "%c", localtime(&bdate));
    }
    idate = (time_t)alpm_pkg_get_installdate(pkg);
    if(idate) {
        strftime(idatestr, 50, "%c", localtime(&idate));
    }

    switch(alpm_pkg_get_reason(pkg)) {
    case ALPM_PKG_REASON_EXPLICIT:
        reason = _("Explicitly installed");
        break;
    case ALPM_PKG_REASON_DEPEND:
        reason = _("Installed as a dependency for another package");
        break;
    default:
        reason = _("Unknown");
        break;
    }

    alpm_pkgvalidation_t v = alpm_pkg_get_validation(pkg);
    if(v) {
        if(v & ALPM_PKG_VALIDATION_NONE) {
            validation = alpm_list_add(validation, _("None"));
        } else {
            if(v & ALPM_PKG_VALIDATION_MD5SUM) {
                validation = alpm_list_add(validation, _("MD5 Sum"));
            }
            if(v & ALPM_PKG_VALIDATION_SHA256SUM) {
                validation = alpm_list_add(validation, _("SHA256 Sum"));
            }
            if(v & ALPM_PKG_VALIDATION_SIGNATURE) {
                validation = alpm_list_add(validation, _("Signature"));
            }
        }
    } else {
        validation = alpm_list_add(validation, _("Unknown"));
    }

    if(extra || from == ALPM_PKG_FROM_LOCALDB) {
        /* compute this here so we don't get a pause in the middle of output */
        requiredby = alpm_pkg_compute_requiredby(pkg);
        optionalfor = alpm_pkg_compute_optionalfor(pkg);
    }

    cols = getcols(fileno(stdout));

    /* actual output */
    if(from == ALPM_PKG_FROM_SYNCDB) {
        string_display(_("Repository     :"),
                       alpm_db_get_name(alpm_pkg_get_db(pkg)), cols);
    }
    string_display(_("Name           :"), alpm_pkg_get_name(pkg), cols);
    string_display(_("Version        :"), alpm_pkg_get_version(pkg), cols);
    string_display(_("Description    :"), alpm_pkg_get_desc(pkg), cols);
    string_display(_("Architecture   :"), alpm_pkg_get_arch(pkg), cols);
    string_display(_("URL            :"), alpm_pkg_get_url(pkg), cols);
    list_display(_("Licenses       :"), alpm_pkg_get_licenses(pkg), cols);
    list_display(_("Groups         :"), alpm_pkg_get_groups(pkg), cols);
    deplist_display(_("Provides       :"), alpm_pkg_get_provides(pkg), cols);
    deplist_display(_("Depends On     :"), alpm_pkg_get_depends(pkg), cols);
    optdeplist_display(pkg, cols);

    if(extra || from == ALPM_PKG_FROM_LOCALDB) {
        list_display(_("Required By    :"), requiredby, cols);
        list_display(_("Optional For   :"), optionalfor, cols);
    }
    deplist_display(_("Conflicts With :"), alpm_pkg_get_conflicts(pkg), cols);
    deplist_display(_("Replaces       :"), alpm_pkg_get_replaces(pkg), cols);

    size = humanize_size(alpm_pkg_get_size(pkg), '\0', 2, &label);
    if(from == ALPM_PKG_FROM_SYNCDB) {
        printf("%s%s%s %6.2f %s\n", config->colstr.title, _("Download Size  :"),
               config->colstr.nocolor, size, label);
    } else if(from == ALPM_PKG_FROM_FILE) {
        printf("%s%s%s %6.2f %s\n", config->colstr.title, _("Compressed Size:"),
               config->colstr.nocolor, size, label);
    } else {
        // autodetect size for "Installed Size"
        label = "\0";
    }

    size = humanize_size(alpm_pkg_get_isize(pkg), label[0], 2, &label);
    printf("%s%s%s %6.2f %s\n", config->colstr.title, _("Installed Size :"),
           config->colstr.nocolor, size, label);

    string_display(_("Packager       :"), alpm_pkg_get_packager(pkg), cols);
    string_display(_("Build Date     :"), bdatestr, cols);
    if(from == ALPM_PKG_FROM_LOCALDB) {
        string_display(_("Install Date   :"), idatestr, cols);
        string_display(_("Install Reason :"), reason, cols);
    }
    if(from == ALPM_PKG_FROM_FILE || from == ALPM_PKG_FROM_LOCALDB) {
        string_display(_("Install Script :"),
                       alpm_pkg_has_scriptlet(pkg) ?  _("Yes") : _("No"), cols);
    }

    if(from == ALPM_PKG_FROM_SYNCDB && extra) {
        const char *base64_sig = alpm_pkg_get_base64_sig(pkg);
        alpm_list_t *keys = NULL;
        if(base64_sig) {
            unsigned char *decoded_sigdata = NULL;
            size_t data_len;
            alpm_decode_signature(base64_sig, &decoded_sigdata, &data_len);
            alpm_extract_keyid(config->handle, alpm_pkg_get_name(pkg),
                               decoded_sigdata, data_len, &keys);
        } else {
            keys = alpm_list_add(keys, _("None"));
        }

        string_display(_("MD5 Sum        :"), alpm_pkg_get_md5sum(pkg), cols);
        string_display(_("SHA256 Sum     :"), alpm_pkg_get_sha256sum(pkg), cols);
        list_display(_("Signatures     :"), keys, cols);
    } else {
        list_display(_("Validated By   :"), validation, cols);
    }

    if(from == ALPM_PKG_FROM_FILE) {
        alpm_siglist_t siglist;
        int err = alpm_pkg_check_pgp_signature(pkg, &siglist);
        if(err && alpm_errno(config->handle) == ALPM_ERR_SIG_MISSING) {
            string_display(_("Signatures     :"), _("None"), cols);
        } else if(err) {
            string_display(_("Signatures     :"),
                           alpm_strerror(alpm_errno(config->handle)), cols);
        } else {
            signature_display(_("Signatures     :"), &siglist, cols);
        }
        alpm_siglist_cleanup(&siglist);
    }

    /* Print additional package info if info flag passed more than once */
    if(from == ALPM_PKG_FROM_LOCALDB && extra) {
        dump_pkg_backups(pkg);
    }

    /* final newline to separate packages */
    printf("\n");

    FREELIST(requiredby);
    alpm_list_free(validation);
}