9d0c5bb4ee
Modulo some code cleanup, this gives NetBSD full wildcard support not only in pkgsrc, but esp. for binary packages installed from local disk and via FTP. For more information, see: http://www.feyrer.de/NetBSD/wildcards.html
339 lines
8.1 KiB
C
339 lines
8.1 KiB
C
/* $NetBSD: perform.c,v 1.30 2000/01/19 23:28:31 hubertf Exp $ */
|
|
|
|
#include <sys/cdefs.h>
|
|
#ifndef lint
|
|
#if 0
|
|
static const char *rcsid = "from FreeBSD Id: perform.c,v 1.23 1997/10/13 15:03:53 jkh Exp";
|
|
#else
|
|
__RCSID("$NetBSD: perform.c,v 1.30 2000/01/19 23:28:31 hubertf Exp $");
|
|
#endif
|
|
#endif
|
|
|
|
/*
|
|
* FreeBSD install - a package for the installation and maintainance
|
|
* of non-core utilities.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* Jordan K. Hubbard
|
|
* 23 Aug 1993
|
|
*
|
|
* This is the main body of the info module.
|
|
*
|
|
*/
|
|
|
|
#include "lib.h"
|
|
#include "info.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <err.h>
|
|
#include <signal.h>
|
|
#include <dirent.h>
|
|
#include <ctype.h>
|
|
|
|
static char *Home;
|
|
|
|
static int
|
|
pkg_do(char *pkg)
|
|
{
|
|
Boolean installed = FALSE, isTMP = FALSE;
|
|
char log_dir[FILENAME_MAX];
|
|
char fname[FILENAME_MAX];
|
|
package_t plist;
|
|
FILE *fp;
|
|
struct stat sb;
|
|
char *cp = NULL;
|
|
int code = 0;
|
|
|
|
if (IS_URL(pkg)) {
|
|
if ((cp = fileGetURL(NULL, pkg)) != NULL) {
|
|
strcpy(fname, cp);
|
|
isTMP = TRUE;
|
|
}
|
|
} else if (fexists(pkg) && isfile(pkg)) {
|
|
int len;
|
|
|
|
if (*pkg != '/') {
|
|
if (!getcwd(fname, FILENAME_MAX)) {
|
|
cleanup(0);
|
|
err(1, "fatal error during execution: getcwd");
|
|
}
|
|
len = strlen(fname);
|
|
(void) snprintf(&fname[len], sizeof(fname) - len, "/%s", pkg);
|
|
} else
|
|
strcpy(fname, pkg);
|
|
cp = fname;
|
|
} else {
|
|
if ((cp = fileFindByPath(NULL, pkg)) != NULL)
|
|
strncpy(fname, cp, FILENAME_MAX);
|
|
}
|
|
|
|
if (cp) {
|
|
if (IS_URL(pkg)) {
|
|
/* file is already unpacked by fileGetURL() */
|
|
strcpy(PlayPen, cp);
|
|
} else {
|
|
/*
|
|
* Apply a crude heuristic to see how much space the package will
|
|
* take up once it's unpacked. I've noticed that most packages
|
|
* compress an average of 75%, but we're only unpacking the + files so
|
|
* be very optimistic.
|
|
*/
|
|
if (stat(fname, &sb) == FAIL) {
|
|
warnx("can't stat package file '%s'", fname);
|
|
code = 1;
|
|
goto bail;
|
|
}
|
|
Home = make_playpen(PlayPen, PlayPenSize, sb.st_size / 2);
|
|
if (unpack(fname, "+*")) {
|
|
warnx("error during unpacking, no info for '%s' available", pkg);
|
|
code = 1;
|
|
goto bail;
|
|
}
|
|
}
|
|
} else {
|
|
/*
|
|
* It's not an uninstalled package, try and find it among the
|
|
* installed
|
|
*/
|
|
char *tmp;
|
|
|
|
(void) snprintf(log_dir, sizeof(log_dir), "%s/%s",
|
|
(tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
|
|
pkg);
|
|
if (!fexists(log_dir) || !isdir(log_dir)) {
|
|
{
|
|
/* Check if the given package name matches
|
|
* something with 'pkg-[0-9]*' */
|
|
char try[FILENAME_MAX];
|
|
snprintf(try, FILENAME_MAX, "%s-[0-9]*", pkg);
|
|
if (findmatchingname(_pkgdb_getPKGDB_DIR(), try,
|
|
find_fn, NULL) != 0) {
|
|
return 0; /* we've just appended some names to the pkgs list,
|
|
* they will be processed after this package. */
|
|
}
|
|
}
|
|
|
|
/* No match */
|
|
warnx("can't find package `%s' installed or in a file!", pkg);
|
|
return 1;
|
|
}
|
|
if (chdir(log_dir) == FAIL) {
|
|
warnx("can't change directory to '%s'!", log_dir);
|
|
return 1;
|
|
}
|
|
installed = TRUE;
|
|
}
|
|
|
|
/* Suck in the contents list */
|
|
plist.head = plist.tail = NULL;
|
|
fp = fopen(CONTENTS_FNAME, "r");
|
|
if (!fp) {
|
|
warnx("unable to open %s file", CONTENTS_FNAME);
|
|
code = 1;
|
|
goto bail;
|
|
}
|
|
/* If we have a prefix, add it now */
|
|
read_plist(&plist, fp);
|
|
fclose(fp);
|
|
|
|
/*
|
|
* Index is special info type that has to override all others to make
|
|
* any sense.
|
|
*/
|
|
if (Flags & SHOW_INDEX) {
|
|
char tmp[FILENAME_MAX];
|
|
|
|
(void) snprintf(tmp, sizeof(tmp), "%-19s ", pkg);
|
|
show_index(tmp, COMMENT_FNAME);
|
|
} else {
|
|
/* Start showing the package contents */
|
|
if (!Quiet) {
|
|
printf("%sInformation for %s:\n\n", InfoPrefix, pkg);
|
|
}
|
|
if (Flags & SHOW_COMMENT) {
|
|
show_file("Comment:\n", COMMENT_FNAME);
|
|
}
|
|
if (Flags & SHOW_DEPENDS) {
|
|
show_depends("Requires:\n", &plist);
|
|
}
|
|
if ((Flags & SHOW_REQBY) && !isemptyfile(REQUIRED_BY_FNAME)) {
|
|
show_file("Required by:\n", REQUIRED_BY_FNAME);
|
|
}
|
|
if (Flags & SHOW_DESC) {
|
|
show_file("Description:\n", DESC_FNAME);
|
|
}
|
|
if ((Flags & SHOW_DISPLAY) && fexists(DISPLAY_FNAME)) {
|
|
show_file("Install notice:\n", DISPLAY_FNAME);
|
|
}
|
|
if (Flags & SHOW_PLIST) {
|
|
show_plist("Packing list:\n", &plist, PLIST_SHOW_ALL);
|
|
}
|
|
if ((Flags & SHOW_INSTALL) && fexists(INSTALL_FNAME)) {
|
|
show_file("Install script:\n", INSTALL_FNAME);
|
|
}
|
|
if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME)) {
|
|
show_file("De-Install script:\n", DEINSTALL_FNAME);
|
|
}
|
|
if ((Flags & SHOW_MTREE) && fexists(MTREE_FNAME)) {
|
|
show_file("mtree file:\n", MTREE_FNAME);
|
|
}
|
|
if (Flags & SHOW_PREFIX) {
|
|
show_plist("Prefix(s):\n", &plist, PLIST_CWD);
|
|
}
|
|
if (Flags & SHOW_FILES) {
|
|
show_files("Files:\n", &plist);
|
|
}
|
|
if ((Flags & SHOW_BUILD_VERSION) && fexists(BUILD_VERSION_FNAME)) {
|
|
show_file("Build version:\n", BUILD_VERSION_FNAME);
|
|
}
|
|
if ((Flags & SHOW_BUILD_INFO) && fexists(BUILD_INFO_FNAME)) {
|
|
show_file("Build information:\n", BUILD_INFO_FNAME);
|
|
}
|
|
if ((Flags & SHOW_PKG_SIZE) && fexists(SIZE_PKG_FNAME)) {
|
|
show_file("Size of this package in bytes: ", SIZE_PKG_FNAME);
|
|
}
|
|
if ((Flags & SHOW_ALL_SIZE) && fexists(SIZE_ALL_FNAME)) {
|
|
show_file("Size in bytes including required pkgs: ", SIZE_ALL_FNAME);
|
|
}
|
|
if (!Quiet) {
|
|
puts(InfoPrefix);
|
|
}
|
|
}
|
|
free_plist(&plist);
|
|
bail:
|
|
leave_playpen(Home);
|
|
if (isTMP)
|
|
unlink(fname);
|
|
return code;
|
|
}
|
|
|
|
/*
|
|
* Function to be called for pkgs found
|
|
*/
|
|
static int
|
|
foundpkg(const char *found, char *data)
|
|
{
|
|
if (!Quiet) {
|
|
printf("%s\n", found);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Check if a package "pkgspec" (which can be a pattern) is installed.
|
|
* Return 0 if found, 1 otherwise (indicating an error).
|
|
*/
|
|
static int
|
|
CheckForPkg(char *pkgspec, char *dbdir)
|
|
{
|
|
struct stat st;
|
|
char buf[FILENAME_MAX];
|
|
int error;
|
|
|
|
if (strpbrk(pkgspec, "<>[]?*{")) {
|
|
/* expensive (pattern) match */
|
|
return !findmatchingname(dbdir, pkgspec, foundpkg, NULL);
|
|
}
|
|
/* simple match */
|
|
(void) snprintf(buf, sizeof(buf), "%s/%s", dbdir, pkgspec);
|
|
error = (stat(buf, &st) < 0);
|
|
if (!error && !Quiet) {
|
|
printf("%s\n", pkgspec);
|
|
}
|
|
if (error) {
|
|
/* found nothing - try 'pkg-[0-9]*' */
|
|
|
|
char try[FILENAME_MAX];
|
|
snprintf(try, FILENAME_MAX, "%s-[0-9]*", pkgspec);
|
|
if (findmatchingname(_pkgdb_getPKGDB_DIR(), try,
|
|
foundpkg, NULL) != 0) {
|
|
error = 0;
|
|
}
|
|
}
|
|
return error;
|
|
}
|
|
|
|
void
|
|
cleanup(int sig)
|
|
{
|
|
leave_playpen(Home);
|
|
exit(1);
|
|
}
|
|
|
|
int
|
|
pkg_perform(lpkg_head_t *pkgs)
|
|
{
|
|
struct dirent *dp;
|
|
char *tmp;
|
|
DIR *dirp;
|
|
int err_cnt = 0;
|
|
|
|
signal(SIGINT, cleanup);
|
|
|
|
if ((tmp = getenv(PKG_DBDIR)) == (char *) NULL) {
|
|
tmp = DEF_LOG_DIR;
|
|
}
|
|
/* Overriding action? */
|
|
if (CheckPkg) {
|
|
err_cnt += CheckForPkg(CheckPkg, tmp);
|
|
} else if (AllInstalled) {
|
|
if (!(isdir(tmp) || islinktodir(tmp)))
|
|
return 1;
|
|
|
|
if (File2Pkg) {
|
|
/* Show all files with the package they belong to */
|
|
char *file, *pkg;
|
|
|
|
/* pkg_info -Fa => Dump pkgdb */
|
|
if (pkgdb_open(1) == -1) {
|
|
err(1, "cannot open pkgdb");
|
|
}
|
|
while ((file = pkgdb_iter())) {
|
|
pkg = pkgdb_retrieve(file);
|
|
printf("%-50s %s\n", file, pkg);
|
|
}
|
|
pkgdb_close();
|
|
} else {
|
|
/* Show all packges with description */
|
|
if ((dirp = opendir(tmp)) != (DIR *) NULL) {
|
|
while ((dp = readdir(dirp)) != (struct dirent *) NULL) {
|
|
char tmp2[FILENAME_MAX];
|
|
|
|
if (strcmp(dp->d_name, ".") == 0 ||
|
|
strcmp(dp->d_name, "..") == 0)
|
|
continue;
|
|
|
|
(void) snprintf(tmp2, sizeof(tmp2), "%s/%s",
|
|
tmp, dp->d_name);
|
|
if (isfile(tmp2))
|
|
continue;
|
|
|
|
err_cnt += pkg_do(dp->d_name);
|
|
}
|
|
(void) closedir(dirp);
|
|
}
|
|
}
|
|
} else {
|
|
/* Show info on individual pkg(s) */
|
|
lpkg_t *lpp;
|
|
|
|
while ((lpp = TAILQ_FIRST(pkgs))) {
|
|
TAILQ_REMOVE(pkgs, lpp, lp_link);
|
|
err_cnt += pkg_do(lpp->lp_name);
|
|
free_lpkg(lpp);
|
|
}
|
|
}
|
|
ftp_stop();
|
|
return err_cnt;
|
|
}
|