take pkg_install out of the base system and pre-install it using the
pkgsrc binary packages. rationale: . pkg_install (which is the pkg_* tools) is entangled with pkgsrc, not with minix, so tracking it from pkgsrc (easier than with base system) makes more sense . simplifies upstreaming minix specific changes for pkg_* tools . reduce pkgsrc-in-basesystem maintenance burden
This commit is contained in:
parent
b0aea49465
commit
e912f6ac38
89 changed files with 4 additions and 19972 deletions
|
@ -32,7 +32,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
||||||
truncate tsort ttt tty udpstat umount uname unexpand \
|
truncate tsort ttt tty udpstat umount uname unexpand \
|
||||||
uniq unstack update uud uue version vol wc \
|
uniq unstack update uud uue version vol wc \
|
||||||
whereis which who write writeisofs fetch \
|
whereis which who write writeisofs fetch \
|
||||||
xargs yacc yes zdump zic zmodem pkg_install pkgin_cd \
|
xargs yacc yes zdump zic zmodem pkgin_cd \
|
||||||
mktemp
|
mktemp
|
||||||
|
|
||||||
.if ${ARCH} == "i386"
|
.if ${ARCH} == "i386"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
SUBDIR= lib add admin bpm create delete info
|
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
|
|
@ -1,20 +0,0 @@
|
||||||
.include <bsd.own.mk>
|
|
||||||
|
|
||||||
BINDIR= /usr/sbin
|
|
||||||
# These have to be passed as strings to the c files.
|
|
||||||
PKG_LOG_DIR= \"/usr/var/db/pkg\"
|
|
||||||
PKG_SYCONFDIR= \"/etc\"
|
|
||||||
PKG_OPSYS_NAME= \"Minix\"
|
|
||||||
PKG_MACHINE_ARCH= \"${ARCH}\"
|
|
||||||
PKG_BINDIR= \"${BINDIR}\"
|
|
||||||
CPPFLAGS+= -DHAVE_CONFIG_H -D_MINIX -D_POSIX_SOURCE
|
|
||||||
CPPFLAGS+= -DDEF_LOG_DIR=${PKG_LOG_DIR}
|
|
||||||
CPPFLAGS+= -DSYSCONFDIR=${PKG_SYCONFDIR}
|
|
||||||
CPPFLAGS+= -DMACHINE_ARCH=${PKG_MACHINE_ARCH}
|
|
||||||
CPPFLAGS+= -DOPSYS_NAME=${PKG_OPSYS_NAME}
|
|
||||||
CPPFLAGS+= -DBINDIR=${PKG_BINDIR}
|
|
||||||
|
|
||||||
CPPFLAGS+= -I../ -I../lib
|
|
||||||
|
|
||||||
LDFLAGS+= -L../lib
|
|
||||||
LDADD= -linstall -lfetch -larchive -lz -lbz2 -lutil
|
|
|
@ -1,21 +0,0 @@
|
||||||
# $NetBSD: README,v 1.9 2007/07/16 09:57:56 joerg Exp $
|
|
||||||
# Original from FreeBSD, no rcs id.
|
|
||||||
|
|
||||||
This is the pkg_install suite of tools for doing maintainance of
|
|
||||||
software "packages". More documentation is available in the man pages
|
|
||||||
for each individual command.
|
|
||||||
|
|
||||||
This code was written by Jordan Hubbard for FreeBSD, snatched and
|
|
||||||
mildly reshaped by John Kohl in NetBSD and the changes taken back into
|
|
||||||
FreeBSD again by Jordan, who then proceeded to add another couple
|
|
||||||
of dozen features on top. Whee! :-)
|
|
||||||
|
|
||||||
In another round of enhancements, NetBSD changes were added by
|
|
||||||
Alistair Crooks, Hubert Feyrer, Thorsten Frueauf, Rene Hexel,
|
|
||||||
Christian E. Hopps, Thomas Klausner, Johnny Lam, Matthias Scheler and
|
|
||||||
Adrian Portelli.
|
|
||||||
|
|
||||||
When making snapshots, please modify PKGTOOLS_VERSION in lib/version.h
|
|
||||||
to that day's date.
|
|
||||||
|
|
||||||
pkgsrc/pkgtools/pkg_install is the canonical location for these sources.
|
|
|
@ -1,6 +0,0 @@
|
||||||
PROG= pkg_add
|
|
||||||
|
|
||||||
SRCS= main.c perform.c
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* $NetBSD: add.h,v 1.18 2010/01/30 20:09:34 joerg Exp $ */
|
|
||||||
|
|
||||||
/* from FreeBSD Id: add.h,v 1.8 1997/02/22 16:09:15 peter Exp */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Include and define various things wanted by the add command.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INST_ADD_H_INCLUDE
|
|
||||||
#define _INST_ADD_H_INCLUDE
|
|
||||||
|
|
||||||
extern char *Destdir;
|
|
||||||
extern char *OverrideMachine;
|
|
||||||
extern char *Prefix;
|
|
||||||
extern char *View;
|
|
||||||
extern char *Viewbase;
|
|
||||||
extern Boolean NoView;
|
|
||||||
extern Boolean NoInstall;
|
|
||||||
extern Boolean NoRecord;
|
|
||||||
extern Boolean Force;
|
|
||||||
extern Boolean Automatic;
|
|
||||||
extern int LicenseCheck;
|
|
||||||
extern int Replace;
|
|
||||||
extern int ReplaceSame;
|
|
||||||
|
|
||||||
extern Boolean ForceDepends;
|
|
||||||
|
|
||||||
int make_hierarchy(char *);
|
|
||||||
void apply_perms(char *, char **, int);
|
|
||||||
|
|
||||||
int pkg_perform(lpkg_head_t *);
|
|
||||||
|
|
||||||
#endif /* _INST_ADD_H_INCLUDE */
|
|
|
@ -1,213 +0,0 @@
|
||||||
/* $NetBSD: main.c,v 1.26 2010/06/16 23:02:48 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: main.c,v 1.26 2010/06/16 23:02:48 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* This is the add module.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_PARAM_H
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#include "lib.h"
|
|
||||||
#include "add.h"
|
|
||||||
|
|
||||||
static char Options[] = "AC:IK:LP:RVW:fhm:np:t:Uuvw:";
|
|
||||||
|
|
||||||
char *Destdir = NULL;
|
|
||||||
char *OverrideMachine = NULL;
|
|
||||||
char *Prefix = NULL;
|
|
||||||
char *View = NULL;
|
|
||||||
char *Viewbase = NULL;
|
|
||||||
Boolean NoView = FALSE;
|
|
||||||
Boolean NoInstall = FALSE;
|
|
||||||
Boolean NoRecord = FALSE;
|
|
||||||
Boolean Automatic = FALSE;
|
|
||||||
Boolean ForceDepends = FALSE;
|
|
||||||
|
|
||||||
int LicenseCheck = 0;
|
|
||||||
int Replace = 0;
|
|
||||||
int ReplaceSame = 0;
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
(void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
|
||||||
"usage: pkg_add [-AfhILnRuVv] [-C config] [-P destdir] [-K pkg_dbdir]",
|
|
||||||
" [-m machine] [-p prefix] [-s verification-type",
|
|
||||||
" [-W viewbase] [-w view]\n",
|
|
||||||
" [[ftp|http]://[user[:password]@]host[:port]][/path/]pkg-name ...");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int ch, error=0;
|
|
||||||
lpkg_head_t pkgs;
|
|
||||||
|
|
||||||
setprogname(argv[0]);
|
|
||||||
while ((ch = getopt(argc, argv, Options)) != -1) {
|
|
||||||
switch (ch) {
|
|
||||||
case 'A':
|
|
||||||
Automatic = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
config_file = optarg;
|
|
||||||
|
|
||||||
case 'P':
|
|
||||||
Destdir = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
Force = TRUE;
|
|
||||||
ForceDepends = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
NoInstall = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'K':
|
|
||||||
pkgdb_set_dir(optarg, 3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'L':
|
|
||||||
NoView = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R':
|
|
||||||
NoRecord = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
OverrideMachine = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
Fake = TRUE;
|
|
||||||
Verbose = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
Prefix = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'U':
|
|
||||||
ReplaceSame = 1;
|
|
||||||
Replace = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u':
|
|
||||||
Replace = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'V':
|
|
||||||
show_version();
|
|
||||||
/* NOTREACHED */
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
Verbose = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'W':
|
|
||||||
Viewbase = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
View = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
pkg_install_config();
|
|
||||||
|
|
||||||
if (Destdir != NULL) {
|
|
||||||
char *pkgdbdir;
|
|
||||||
|
|
||||||
pkgdbdir = xasprintf("%s/%s", Destdir, config_pkg_dbdir);
|
|
||||||
pkgdb_set_dir(pkgdbdir, 4);
|
|
||||||
free(pkgdbdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
process_pkg_path();
|
|
||||||
TAILQ_INIT(&pkgs);
|
|
||||||
|
|
||||||
if (argc == 0) {
|
|
||||||
/* If no packages, yelp */
|
|
||||||
warnx("missing package name(s)");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(do_license_check, "no") == 0)
|
|
||||||
LicenseCheck = 0;
|
|
||||||
else if (strcasecmp(do_license_check, "yes") == 0)
|
|
||||||
LicenseCheck = 1;
|
|
||||||
else if (strcasecmp(do_license_check, "always") == 0)
|
|
||||||
LicenseCheck = 2;
|
|
||||||
else
|
|
||||||
errx(1, "Unknown value of the configuration variable"
|
|
||||||
"CHECK_LICENSE");
|
|
||||||
|
|
||||||
if (LicenseCheck)
|
|
||||||
load_license_lists();
|
|
||||||
|
|
||||||
/* Get all the remaining package names, if any */
|
|
||||||
for (; argc > 0; --argc, ++argv) {
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
if (IS_STDIN(*argv))
|
|
||||||
lpp = alloc_lpkg("-");
|
|
||||||
else
|
|
||||||
lpp = alloc_lpkg(*argv);
|
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
error += pkg_perform(&pkgs);
|
|
||||||
if (error != 0) {
|
|
||||||
warnx("%d package addition%s failed", error, error == 1 ? "" : "s");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,443 +0,0 @@
|
||||||
.\" $NetBSD: pkg_add.1,v 1.44 2010/06/16 23:02:48 joerg Exp $
|
|
||||||
.\"
|
|
||||||
.\" FreeBSD install - a package for the installation and maintenance
|
|
||||||
.\" 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
|
|
||||||
.\"
|
|
||||||
.\"
|
|
||||||
.\" @(#)pkg_add.1
|
|
||||||
.\"
|
|
||||||
.Dd June 16, 2010
|
|
||||||
.Dt PKG_ADD 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pkg_add
|
|
||||||
.Nd a utility for installing and upgrading software package distributions
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl AfILnRUuVv
|
|
||||||
.Op Fl C Ar config
|
|
||||||
.Op Fl K Ar pkg_dbdir
|
|
||||||
.Op Fl m Ar machine
|
|
||||||
.Op Fl P Ar destdir
|
|
||||||
.Op Fl p Ar prefix
|
|
||||||
.Op Fl W Ar viewbase
|
|
||||||
.Op Fl w Ar view
|
|
||||||
.Ar Oo Oo Li ftp|http Oc Ns Li :// Ns Oo Ar user Oc Ns \
|
|
||||||
Oo Li \&: Ns Ar password Oc \
|
|
||||||
Ns Li @ Oc Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns \
|
|
||||||
Oo Li / Ns Ar path/ Oc Ns Ar pkg-name ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command is used to extract and upgrade packages that have been
|
|
||||||
previously created with the
|
|
||||||
.Xr pkg_create 1
|
|
||||||
command.
|
|
||||||
Packages are prepared collections of pre-built binaries, documentation,
|
|
||||||
configurations, installation instructions and/or other files.
|
|
||||||
.Nm
|
|
||||||
can recursively install other packages that the current package
|
|
||||||
depends on or requires from both local disk and via FTP or HTTP.
|
|
||||||
.Sh WARNING
|
|
||||||
.Bf -emphasis
|
|
||||||
Since the
|
|
||||||
.Nm
|
|
||||||
command may execute scripts or programs contained within a package file,
|
|
||||||
your system may be susceptible to
|
|
||||||
.Dq Trojan horses
|
|
||||||
or other subtle
|
|
||||||
attacks from miscreants who create dangerous package files.
|
|
||||||
.Pp
|
|
||||||
You are advised to verify the competence and identity of those who
|
|
||||||
provide installable package files.
|
|
||||||
For extra protection, use the digital signatures provided where possible
|
|
||||||
(see the
|
|
||||||
.Xr pkg_install.conf 5 ) ,
|
|
||||||
or, failing that, use
|
|
||||||
.Xr tar 1
|
|
||||||
to extract the package file, and inspect its contents and scripts
|
|
||||||
to ensure it poses no danger to your system's integrity.
|
|
||||||
Pay particular attention to any
|
|
||||||
.Pa +INSTALL
|
|
||||||
or
|
|
||||||
.Pa +DEINSTALL
|
|
||||||
files, and inspect the
|
|
||||||
.Pa +CONTENTS
|
|
||||||
file for
|
|
||||||
.Cm @cwd ,
|
|
||||||
.Cm @mode
|
|
||||||
(check for setuid),
|
|
||||||
.Cm @dirrm ,
|
|
||||||
.Cm @exec ,
|
|
||||||
and
|
|
||||||
.Cm @unexec
|
|
||||||
directives, and/or use the
|
|
||||||
.Xr pkg_info 1
|
|
||||||
command to examine the package file.
|
|
||||||
.Ef
|
|
||||||
.Sh OPTIONS
|
|
||||||
The following command line arguments are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Ar pkg-name [ ... ]
|
|
||||||
The named packages are installed.
|
|
||||||
.Nm
|
|
||||||
will first try to use
|
|
||||||
.Ar pkg-name
|
|
||||||
as full URL or path name without any wildcard processing.
|
|
||||||
If that fails,
|
|
||||||
.Nm
|
|
||||||
will try to match packages using wildcard processing.
|
|
||||||
If that fails as well and
|
|
||||||
.Ar pkg-name
|
|
||||||
does not contain any /, the entries of the
|
|
||||||
.Dv PKG_PATH
|
|
||||||
variable are searched using the wildcard processing rules.
|
|
||||||
.It Fl A
|
|
||||||
Mark package as installed automatically, as dependency of another
|
|
||||||
package.
|
|
||||||
You can use
|
|
||||||
.Dl Ic pkg_admin set automatic=YES
|
|
||||||
to mark packages this way after installation, and
|
|
||||||
.Dl Ic pkg_admin unset automatic
|
|
||||||
to remove the mark.
|
|
||||||
If you
|
|
||||||
.Nm
|
|
||||||
a package without specifying
|
|
||||||
.Fl A
|
|
||||||
after it had already been automatically installed, the mark is
|
|
||||||
removed.
|
|
||||||
.It Fl C Ar config
|
|
||||||
Read the configuration file from
|
|
||||||
.Ar config
|
|
||||||
instead of the system default.
|
|
||||||
.It Fl f
|
|
||||||
Force installation to proceed even if prerequisite packages are not
|
|
||||||
installed or the install script fails.
|
|
||||||
Although
|
|
||||||
.Nm
|
|
||||||
will still try to find and auto-install missing prerequisite packages,
|
|
||||||
a failure to find one will not be fatal.
|
|
||||||
This flag also overrides the fatal error when the operating system or
|
|
||||||
architecture the package was built on differ from that of the host.
|
|
||||||
.It Fl I
|
|
||||||
If an installation script exists for a given package, do not execute it.
|
|
||||||
.It Fl K Ar pkg_dbdir
|
|
||||||
Override the value of the
|
|
||||||
.Dv PKG_DBDIR
|
|
||||||
configuration option with the value
|
|
||||||
.Ar pkg_dbdir .
|
|
||||||
.It Fl L
|
|
||||||
Don't add the package to any views after installation.
|
|
||||||
.It Fl m
|
|
||||||
Override the machine architecture returned by uname with
|
|
||||||
.Ar machine .
|
|
||||||
.It Fl n
|
|
||||||
Don't actually install a package, just report the steps that
|
|
||||||
would be taken if it was.
|
|
||||||
.It Fl P Ar destdir
|
|
||||||
Prefix all file and directory names with
|
|
||||||
.Ar destdir .
|
|
||||||
For packages without install scripts this has the same behavior as
|
|
||||||
using
|
|
||||||
.Xr chroot 8 .
|
|
||||||
.It Fl p Ar prefix
|
|
||||||
Override the prefix stored in the package with
|
|
||||||
.Ar prefix .
|
|
||||||
.It Fl R
|
|
||||||
Do not record the installation of a package.
|
|
||||||
This implies
|
|
||||||
.Fl I .
|
|
||||||
This means that you cannot deinstall it later, so only use this option if
|
|
||||||
you know what you are doing!
|
|
||||||
.It Fl U
|
|
||||||
Replace an already installed version from a package.
|
|
||||||
Implies
|
|
||||||
.Fl u .
|
|
||||||
.It Fl u
|
|
||||||
If the package that's being installed is already installed,
|
|
||||||
an update is performed.
|
|
||||||
Installed dependent packages are updated recursively, if they are too
|
|
||||||
old to fulfill the dependencies of the to-be-installed version.
|
|
||||||
See below for a more detailed description of the process.
|
|
||||||
.It Fl V
|
|
||||||
Print version number and exit.
|
|
||||||
.It Fl v
|
|
||||||
Turn on verbose output.
|
|
||||||
.It Fl W Ar viewbase
|
|
||||||
Passed down to
|
|
||||||
.Xr pkg_view 1
|
|
||||||
for managed views.
|
|
||||||
.It Fl w Ar view
|
|
||||||
Passed down to
|
|
||||||
.Xr pkg_view 1
|
|
||||||
for managed views.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
One or more
|
|
||||||
.Ar pkg-name
|
|
||||||
arguments may be specified, each being either a file containing the
|
|
||||||
package (these usually ending with the
|
|
||||||
.Dq .tgz
|
|
||||||
suffix) or a
|
|
||||||
URL pointing at a file available on an ftp or web site.
|
|
||||||
Thus you may extract files directly from their anonymous ftp or WWW
|
|
||||||
locations (e.g.,
|
|
||||||
.Nm
|
|
||||||
ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/i386/3.1_2007Q2/shells/bash-3.2.9.tgz
|
|
||||||
or
|
|
||||||
.Nm
|
|
||||||
http://www.example.org/packages/screen-4.0.tbz).
|
|
||||||
Note: For ftp transfers, if you wish to use
|
|
||||||
.Bf -emphasis
|
|
||||||
passive mode
|
|
||||||
.Ef
|
|
||||||
ftp in such transfers, set the variable
|
|
||||||
.Bf -emphasis
|
|
||||||
FTP_PASSIVE_MODE
|
|
||||||
.Ef
|
|
||||||
to some value in your environment.
|
|
||||||
Otherwise, the more standard ACTIVE mode may be used.
|
|
||||||
If
|
|
||||||
.Nm
|
|
||||||
consistently fails to fetch a package from a site known to work,
|
|
||||||
it may be because you have a firewall that demands the usage of
|
|
||||||
.Bf -emphasis
|
|
||||||
passive mode
|
|
||||||
.Ef
|
|
||||||
ftp.
|
|
||||||
.Sh TECHNICAL DETAILS
|
|
||||||
.Nm
|
|
||||||
extracts each package's meta data (including the
|
|
||||||
.Dq packing list )
|
|
||||||
to memory and then runs through the following sequence to fully extract
|
|
||||||
the contents of the package:
|
|
||||||
.Bl -enum -offset indent
|
|
||||||
.It
|
|
||||||
A check is made to determine if the package or another version of it
|
|
||||||
is already recorded as installed.
|
|
||||||
If it is,
|
|
||||||
installation is terminated if the
|
|
||||||
.Fl u
|
|
||||||
or
|
|
||||||
.Fl U
|
|
||||||
options are not given.
|
|
||||||
.Pp
|
|
||||||
If the same version is installed and
|
|
||||||
.Fl U
|
|
||||||
is not given, it is marked as manually installed and process stops.
|
|
||||||
If the
|
|
||||||
.Fl u
|
|
||||||
option is given, it's assumed the package should be replaced by the
|
|
||||||
new version instead.
|
|
||||||
Before doing so, all packages that depend on the
|
|
||||||
pkg being upgraded are checked if they also work with the new version.
|
|
||||||
If that test is not successful, the dependent packages are updated first.
|
|
||||||
The replacing is then prepared by moving an existing
|
|
||||||
.Pa +REQUIRED_BY
|
|
||||||
file aside (if it exists), and running
|
|
||||||
.Xr pkg_delete 1
|
|
||||||
on the installed package.
|
|
||||||
Installation then proceeds as if the package
|
|
||||||
was not installed, and restores the
|
|
||||||
.Pa +REQUIRED_BY
|
|
||||||
file afterwards.
|
|
||||||
.It
|
|
||||||
The package build information is extracted from the
|
|
||||||
.Pa +BUILD_INFO
|
|
||||||
file and compared against the result of
|
|
||||||
.Xr uname 3 .
|
|
||||||
If the operating system or architecture of the package differ from
|
|
||||||
that of the host, installation is aborted.
|
|
||||||
This behavior is overridable with the
|
|
||||||
.Fl f
|
|
||||||
flag.
|
|
||||||
.It
|
|
||||||
The package build information from
|
|
||||||
.Pa +BUILD_INFO
|
|
||||||
is then checked for
|
|
||||||
.Ev USE_ABI_DEPENDS=NO
|
|
||||||
(or
|
|
||||||
.Ev IGNORE_RECOMMENDED ) .
|
|
||||||
If the package was built with ABI dependency recommendations ignored,
|
|
||||||
a warning will be issued.
|
|
||||||
.It
|
|
||||||
A check is made to determine if the package conflicts (from
|
|
||||||
.Cm @pkgcfl
|
|
||||||
directives, see
|
|
||||||
.Xr pkg_create 1 )
|
|
||||||
with an already recorded as installed package or if an installed package
|
|
||||||
conflicts with the package.
|
|
||||||
If it is, installation is terminated.
|
|
||||||
.It
|
|
||||||
The file list of the package is compared to the file lists of the
|
|
||||||
installed packages.
|
|
||||||
If there is any overlap, the installation is terminated.
|
|
||||||
.It
|
|
||||||
All package dependencies (from
|
|
||||||
.Cm @pkgdep
|
|
||||||
directives, see
|
|
||||||
.Xr pkg_create 1 )
|
|
||||||
are read from the packing list.
|
|
||||||
If any of these required packages are not currently installed,
|
|
||||||
an attempt is made to find and install it;
|
|
||||||
if the missing package cannot be found or installed,
|
|
||||||
the installation is terminated.
|
|
||||||
.It
|
|
||||||
If the package contains an
|
|
||||||
.Ar install
|
|
||||||
script, it is executed with the following arguments:
|
|
||||||
.Bl -tag -width indentindent
|
|
||||||
.It Ar pkg-name
|
|
||||||
The name of the package being installed.
|
|
||||||
.It Cm PRE-INSTALL
|
|
||||||
Keyword denoting that the script is to perform any actions needed before
|
|
||||||
the package is installed.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
If the
|
|
||||||
.Ar install
|
|
||||||
script exits with a non-zero status code, the installation is terminated.
|
|
||||||
.It
|
|
||||||
The files from the file list are extracted to the chosen prefix.
|
|
||||||
.It
|
|
||||||
If an
|
|
||||||
.Ar install
|
|
||||||
script exists for the package, it is executed with the following arguments:
|
|
||||||
.Bl -tag -width indentindent
|
|
||||||
.It Ar pkg_name
|
|
||||||
The name of the package being installed.
|
|
||||||
.It Cm POST-INSTALL
|
|
||||||
Keyword denoting that the script is to perform any actions needed
|
|
||||||
after the package has been installed.
|
|
||||||
.El
|
|
||||||
.It
|
|
||||||
After installation is complete, a copy of the packing list,
|
|
||||||
.Ar deinstall
|
|
||||||
script, description, and display files are copied into
|
|
||||||
.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt]
|
|
||||||
for subsequent possible use by
|
|
||||||
.Xr pkg_delete 1 .
|
|
||||||
Any package dependencies are recorded in the other packages'
|
|
||||||
.Pa +REQUIRED_BY
|
|
||||||
file.
|
|
||||||
.It
|
|
||||||
If the package is a depoted package, then add it to the registered
|
|
||||||
by calling
|
|
||||||
.Xr pkg_view 1
|
|
||||||
accordingly.
|
|
||||||
.It
|
|
||||||
Finally, if we were upgrading a package, any
|
|
||||||
.Pa +REQUIRED_BY
|
|
||||||
file that was moved aside before upgrading was started is now moved
|
|
||||||
back into place.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Ar install
|
|
||||||
script is called with the environment variable
|
|
||||||
.Ev PKG_PREFIX
|
|
||||||
set to the installation prefix (see the
|
|
||||||
.Fl p
|
|
||||||
option above).
|
|
||||||
This allows a package author to write a script
|
|
||||||
that reliably performs some action on the directory where the package
|
|
||||||
is installed, even if the user might change it with the
|
|
||||||
.Fl p
|
|
||||||
flag to
|
|
||||||
.Cm pkg_add .
|
|
||||||
The scripts are also called with the
|
|
||||||
.Ev PKG_METADATA_DIR
|
|
||||||
environment variable set to the location of the
|
|
||||||
.Pa +*
|
|
||||||
meta-data files, and with the
|
|
||||||
.Ev PKG_REFCOUNT_DBDIR
|
|
||||||
environment variable set to the location of the package reference counts
|
|
||||||
database directory.
|
|
||||||
If the
|
|
||||||
.Fl P
|
|
||||||
flag was given to
|
|
||||||
.Nm ,
|
|
||||||
.Ev PKG_DESTDIR
|
|
||||||
will be set to
|
|
||||||
.Ar destdir .
|
|
||||||
Additionally,
|
|
||||||
.Ev PKG_METADATA_DIR
|
|
||||||
and
|
|
||||||
.Ev PKG_REFCOUNT_DBDIR
|
|
||||||
are prefixed with
|
|
||||||
.Ar destdir .
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
See
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
for options, that can also be specified using the environment.
|
|
||||||
Packages using views are also affected by the environment variables
|
|
||||||
documented for
|
|
||||||
.Xr pkg_view 1 .
|
|
||||||
.Sh EXAMPLES
|
|
||||||
In all cases,
|
|
||||||
.Nm
|
|
||||||
will try to install binary packages listed in dependencies list.
|
|
||||||
.Pp
|
|
||||||
You can specify a compiled binary package explicitly on the command line.
|
|
||||||
.Bd -literal
|
|
||||||
# pkg_add /usr/pkgsrc/packages/All/tcsh-6.14.00.tgz
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
If you omit the version number,
|
|
||||||
.Nm
|
|
||||||
will install the latest version available.
|
|
||||||
With
|
|
||||||
.Fl v ,
|
|
||||||
.Nm
|
|
||||||
emits more messages to terminal.
|
|
||||||
.Bd -literal
|
|
||||||
# pkg_add -v /usr/pkgsrc/packages/All/unzip
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
You can grab a compiled binary package from remote location by specifying
|
|
||||||
a URL.
|
|
||||||
The base URL can also be provided by the configuration variable,
|
|
||||||
.Dv PKG_PATH .
|
|
||||||
.Bd -literal
|
|
||||||
# pkg_add -v ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/i386/3.1_2007Q2/All/firefox-2.0.0.4.tgz
|
|
||||||
|
|
||||||
# export PKG_PATH=ftp://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/i386/3.1_2007Q2/All
|
|
||||||
# pkg_add -v firefox
|
|
||||||
.Ed
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_admin 1 ,
|
|
||||||
.Xr pkg_create 1 ,
|
|
||||||
.Xr pkg_delete 1 ,
|
|
||||||
.Xr pkg_info 1 ,
|
|
||||||
.Xr pkg_install.conf 5 ,
|
|
||||||
.Xr pkgsrc 7
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Bl -tag -width indent -compact
|
|
||||||
.It "Jordan Hubbard"
|
|
||||||
Initial work and ongoing development.
|
|
||||||
.It "John Kohl"
|
|
||||||
.Nx
|
|
||||||
refinements.
|
|
||||||
.It "Hubert Feyrer"
|
|
||||||
.Nx
|
|
||||||
wildcard dependency processing, pkgdb, upgrading, etc.
|
|
||||||
.It Thomas Klausner
|
|
||||||
HTTP support.
|
|
||||||
.It Joerg Sonnenberger
|
|
||||||
Rewrote most of the code base to work without external commands.
|
|
||||||
.El
|
|
||||||
.Sh BUGS
|
|
||||||
Package upgrading needs a lot more work to be really universal.
|
|
||||||
.Pp
|
|
||||||
Sure to be others.
|
|
|
@ -1,8 +0,0 @@
|
||||||
PROG= pkg_admin
|
|
||||||
SCRIPTS= audit-packages download-vulnerability-list
|
|
||||||
FILES=
|
|
||||||
SRCS= main.c audit.c check.c
|
|
||||||
MAN= pkg_admin.1 download-vulnerability-list.8 audit-packages.8
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern int quiet;
|
|
||||||
extern int verbose;
|
|
||||||
|
|
||||||
void check(char **);
|
|
||||||
|
|
||||||
void audit_pkgdb(int, char **);
|
|
||||||
void audit_pkg(int, char **);
|
|
||||||
void audit_batch(int, char **);
|
|
||||||
void audit_history(int, char **);
|
|
||||||
void check_pkg_vulnerabilities(int, char **);
|
|
||||||
void fetch_pkg_vulnerabilities(int, char **);
|
|
||||||
|
|
||||||
void usage(void);
|
|
|
@ -1,130 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
pkg_admin=/usr/bin/sbin/pkg_admin
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo 'Usage: audit-packages [-deqsVv] [-c config_file] [-F file]' >& $2
|
|
||||||
echo ' [-g file] [-h file]' >& $2
|
|
||||||
echo ' [-K pkg_dbdir] [-n package] [-p package]' >& $2
|
|
||||||
echo ' [-Q varname] [-t type]' >& $2
|
|
||||||
echo "Please use the audit, audit-pkg, audit-batch and fetch-pkg-vulnerabilities" >& $2
|
|
||||||
echo "commands of pkg_admin instead." >& $2
|
|
||||||
exit $1
|
|
||||||
}
|
|
||||||
|
|
||||||
do_pkgdb=
|
|
||||||
do_eol=
|
|
||||||
do_fetch=
|
|
||||||
do_quiet=
|
|
||||||
do_sign=
|
|
||||||
do_verbose=
|
|
||||||
do_check_file=
|
|
||||||
do_check_pattern=
|
|
||||||
do_check_installed=
|
|
||||||
do_check_vul_file=
|
|
||||||
do_limit_type=
|
|
||||||
do_print_var=
|
|
||||||
|
|
||||||
args=`getopt F:K:Q:Vc:deg:h:n:p:qst:v $*`
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
usage 1 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -- $args
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
-F)
|
|
||||||
do_check_file=$2
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-K)
|
|
||||||
do_pkgdb="$1 $2"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-Q)
|
|
||||||
do_print_var="$2"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-V)
|
|
||||||
exec ${pkg_admin} -V
|
|
||||||
;;
|
|
||||||
-c)
|
|
||||||
echo "The audit-packages wrapper does not support -c" >&2
|
|
||||||
echo "Please use the audit, audit-pkg, audit-batch and fetch-pkg-vulnerabilities" >& 2
|
|
||||||
echo "commands of pkg_admin instead." >& 2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
-d)
|
|
||||||
do_fetch=1
|
|
||||||
;;
|
|
||||||
-e)
|
|
||||||
do_eol=-e
|
|
||||||
;;
|
|
||||||
-g)
|
|
||||||
echo "The audit-packages wrapper does not support -g" >&2
|
|
||||||
echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
-h)
|
|
||||||
do_check_vul_file=$2
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-n)
|
|
||||||
do_check_pattern=$2
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-p)
|
|
||||||
do_check_installed=$2
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-q)
|
|
||||||
do_quiet=-q
|
|
||||||
;;
|
|
||||||
-s)
|
|
||||||
do_sign=-s
|
|
||||||
;;
|
|
||||||
-t)
|
|
||||||
do_limit_type="-t $2"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-v)
|
|
||||||
do_verbose="$do_verbose -v"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "${do_fetch}" ]; then
|
|
||||||
exec ${pkg_admin} ${do_pkgdb} fetch-pkg-vulnerabilities ${do_sign}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${do_check_vul_file}" ]; then
|
|
||||||
exec ${pkg_admin} ${do_pkgdb} check-pkg-vulnerabilities ${do_sign} "${do_check_vul_file}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${do_print_var}" ]; then
|
|
||||||
exec ${pkg_admin} ${do_pkgdb} config-var "${do_print_var}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${do_check_file}" ]; then
|
|
||||||
if [ -n "${do_check_pattern}" -o -n "${do_check_installed}" ]; then
|
|
||||||
echo "Only one of -F, -n or -p is interpreted at a time." >& 2
|
|
||||||
usage 1 2
|
|
||||||
fi
|
|
||||||
exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit-pkg \
|
|
||||||
${do_eol} ${do_limit_type} ${do_check_file}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${do_check_pattern}" ]; then
|
|
||||||
if [ -n "${do_check_installed}" ]; then
|
|
||||||
echo "Only one of -F, -n or -p is interpreted at a time." >& 2
|
|
||||||
usage 1 2
|
|
||||||
fi
|
|
||||||
exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit-pkg \
|
|
||||||
${do_eol} ${do_limit_type} ${do_check_pattern}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If do_check_installed is empty, all packages are checked.
|
|
||||||
exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit \
|
|
||||||
${do_eol} ${do_limit_type} ${do_check_installed}
|
|
|
@ -1,66 +0,0 @@
|
||||||
.\" $NetBSD: audit-packages.8,v 1.1 2010/03/19 12:49:53 wiz Exp $
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
.\" by Thomas Klausner.
|
|
||||||
.\"
|
|
||||||
.\" 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.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd March 18, 2010
|
|
||||||
.Dt AUDIT-PACKAGES 8
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm audit-packages
|
|
||||||
.Nd report vulnerabilities for the installed packages
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl deqsVv
|
|
||||||
.Op Fl c Ar config_file
|
|
||||||
.Op Fl F Ar file
|
|
||||||
.Op Fl g Ar file
|
|
||||||
.Op Fl h Ar file
|
|
||||||
.Op Fl K Ar pkg_dbdir
|
|
||||||
.Op Fl n Ar package
|
|
||||||
.Op Fl p Ar package
|
|
||||||
.Op Fl Q Ar varname
|
|
||||||
.Op Fl t Ar type
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
is deprecated.
|
|
||||||
Please use the
|
|
||||||
.Cm audit ,
|
|
||||||
.Cm audit-pkg ,
|
|
||||||
.Cm audit-batch ,
|
|
||||||
and
|
|
||||||
.Cm fetch-pkg-vulnerabilities
|
|
||||||
commands of
|
|
||||||
.Xr pkg_admin 1
|
|
||||||
instead.
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script is installed for backwards compatibility only and will
|
|
||||||
eventually be removed.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_admin 1
|
|
|
@ -1,508 +0,0 @@
|
||||||
/* $NetBSD: audit.c,v 1.16 2010/06/16 23:02:48 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: audit.c,v 1.16 2010/06/16 23:02:48 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SIGNAL_H
|
|
||||||
#include <signal.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_TIME_H
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#if defined(NETBSD) || defined(__minix)
|
|
||||||
#include <unistd.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <fetch.h>
|
|
||||||
|
|
||||||
#include "admin.h"
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static int check_signature = 0;
|
|
||||||
static const char *limit_vul_types = NULL;
|
|
||||||
static int update_pkg_vuln = 0;
|
|
||||||
|
|
||||||
static struct pkg_vulnerabilities *pv;
|
|
||||||
|
|
||||||
static const char audit_options[] = "est:";
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_options(int argc, char **argv, const char *options)
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
optreset = 1;
|
|
||||||
/*
|
|
||||||
* optind == 0 is interpreted as partial reset request
|
|
||||||
* by GNU getopt, so compensate against this and cleanup
|
|
||||||
* at the end.
|
|
||||||
*/
|
|
||||||
optind = 1;
|
|
||||||
++argc;
|
|
||||||
--argv;
|
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, options)) != -1) {
|
|
||||||
switch (ch) {
|
|
||||||
case 'e':
|
|
||||||
check_eol = "yes";
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
check_signature = 1;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
limit_vul_types = optarg;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
update_pkg_vuln = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
--optind; /* See above comment. */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_exact_pkg(const char *pkg)
|
|
||||||
{
|
|
||||||
return audit_package(pv, pkg, limit_vul_types, quiet ? 0 : 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_batch_exact_pkgs(const char *fname)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
char buf[4096], *line, *eol;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
if (strcmp(fname, "-") == 0)
|
|
||||||
f = stdin;
|
|
||||||
else {
|
|
||||||
f = fopen(fname, "r");
|
|
||||||
if (f == NULL)
|
|
||||||
err(EXIT_FAILURE, "Failed to open input file %s",
|
|
||||||
fname);
|
|
||||||
}
|
|
||||||
while ((line = fgets(buf, sizeof(buf), f)) != NULL) {
|
|
||||||
eol = line + strlen(line);
|
|
||||||
if (eol == line)
|
|
||||||
continue;
|
|
||||||
--eol;
|
|
||||||
if (*eol == '\n') {
|
|
||||||
if (eol == line)
|
|
||||||
continue;
|
|
||||||
*eol = '\0';
|
|
||||||
}
|
|
||||||
ret |= check_exact_pkg(line);
|
|
||||||
}
|
|
||||||
if (f != stdin)
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_one_installed_pkg(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
int *ret = cookie;
|
|
||||||
|
|
||||||
*ret |= check_exact_pkg(pkg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_installed_pattern(const char *pattern)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
match_installed_pkgs(pattern, check_one_installed_pkg, &ret);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_and_read_pkg_vulnerabilities(void)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
time_t now;
|
|
||||||
|
|
||||||
if (pkg_vulnerabilities_file == NULL)
|
|
||||||
errx(EXIT_FAILURE, "PKG_VULNERABILITIES is not set");
|
|
||||||
|
|
||||||
if (verbose >= 1) {
|
|
||||||
if (stat(pkg_vulnerabilities_file, &st) == -1) {
|
|
||||||
if (errno == ENOENT)
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"pkg-vulnerabilities not found, run %s -d",
|
|
||||||
getprogname());
|
|
||||||
errx(EXIT_FAILURE, "pkg-vulnerabilities not readable");
|
|
||||||
}
|
|
||||||
now = time(NULL);
|
|
||||||
now -= st.st_mtime;
|
|
||||||
if (now < 0)
|
|
||||||
warnx("pkg-vulnerabilities is from the future");
|
|
||||||
else if (now > 86400 * 7)
|
|
||||||
warnx("pkg-vulnerabilities is out of date (%ld days old)",
|
|
||||||
(long)(now / 86400));
|
|
||||||
else if (verbose >= 2)
|
|
||||||
warnx("pkg-vulnerabilities is %ld day%s old",
|
|
||||||
(long)(now / 86400), now / 86400 == 1 ? "" : "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
pv = read_pkg_vulnerabilities_file(pkg_vulnerabilities_file, 0, check_signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
audit_pkgdb(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
parse_options(argc, argv, audit_options);
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
check_and_read_pkg_vulnerabilities();
|
|
||||||
|
|
||||||
rv = 0;
|
|
||||||
if (*argv == NULL)
|
|
||||||
rv |= check_installed_pattern("*");
|
|
||||||
else {
|
|
||||||
for (; *argv != NULL; ++argv)
|
|
||||||
rv |= check_installed_pattern(*argv);
|
|
||||||
}
|
|
||||||
free_pkg_vulnerabilities(pv);
|
|
||||||
|
|
||||||
if (rv == 0 && verbose >= 1)
|
|
||||||
fputs("No vulnerabilities found\n", stderr);
|
|
||||||
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
audit_pkg(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
parse_options(argc, argv, audit_options);
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
check_and_read_pkg_vulnerabilities();
|
|
||||||
rv = 0;
|
|
||||||
for (; *argv != NULL; ++argv)
|
|
||||||
rv |= check_exact_pkg(*argv);
|
|
||||||
|
|
||||||
free_pkg_vulnerabilities(pv);
|
|
||||||
|
|
||||||
if (rv == 0 && verbose >= 1)
|
|
||||||
fputs("No vulnerabilities found\n", stderr);
|
|
||||||
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
audit_batch(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
parse_options(argc, argv, audit_options);
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
check_and_read_pkg_vulnerabilities();
|
|
||||||
rv = 0;
|
|
||||||
for (; *argv != NULL; ++argv)
|
|
||||||
rv |= check_batch_exact_pkgs(*argv);
|
|
||||||
free_pkg_vulnerabilities(pv);
|
|
||||||
|
|
||||||
if (rv == 0 && verbose >= 1)
|
|
||||||
fputs("No vulnerabilities found\n", stderr);
|
|
||||||
exit(rv ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_pkg_vulnerabilities(int argc, char **argv)
|
|
||||||
{
|
|
||||||
parse_options(argc, argv, "s");
|
|
||||||
if (argc != optind + 1)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
pv = read_pkg_vulnerabilities_file(argv[optind], 0, check_signature);
|
|
||||||
free_pkg_vulnerabilities(pv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
fetch_pkg_vulnerabilities(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct pkg_vulnerabilities *pv_check;
|
|
||||||
char *buf;
|
|
||||||
size_t buf_len, buf_fetched;
|
|
||||||
ssize_t cur_fetched;
|
|
||||||
struct url *url;
|
|
||||||
struct url_stat st;
|
|
||||||
fetchIO *f;
|
|
||||||
int fd;
|
|
||||||
struct stat sb;
|
|
||||||
char my_flags[20];
|
|
||||||
const char *flags;
|
|
||||||
|
|
||||||
parse_options(argc, argv, "su");
|
|
||||||
if (argc != optind)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
if (verbose >= 2)
|
|
||||||
fprintf(stderr, "Fetching %s\n", pkg_vulnerabilities_url);
|
|
||||||
|
|
||||||
url = fetchParseURL(pkg_vulnerabilities_url);
|
|
||||||
if (url == NULL)
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"Could not parse location of pkg_vulnerabilities: %s",
|
|
||||||
fetchLastErrString);
|
|
||||||
|
|
||||||
flags = fetch_flags;
|
|
||||||
if (update_pkg_vuln) {
|
|
||||||
fd = open(pkg_vulnerabilities_file, O_RDONLY);
|
|
||||||
if (fd != -1 && fstat(fd, &sb) != -1) {
|
|
||||||
url->last_modified = sb.st_mtime;
|
|
||||||
snprintf(my_flags, sizeof(my_flags), "%si",
|
|
||||||
fetch_flags);
|
|
||||||
flags = my_flags;
|
|
||||||
} else
|
|
||||||
update_pkg_vuln = 0;
|
|
||||||
if (fd != -1)
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
f = fetchXGet(url, &st, flags);
|
|
||||||
if (f == NULL && update_pkg_vuln &&
|
|
||||||
fetchLastErrCode == FETCH_UNCHANGED) {
|
|
||||||
if (verbose >= 1)
|
|
||||||
fprintf(stderr, "%s is not newer\n",
|
|
||||||
pkg_vulnerabilities_url);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Could not fetch vulnerability file: %s",
|
|
||||||
fetchLastErrString);
|
|
||||||
/*
|
|
||||||
if (st.size > SSIZE_MAX - 1)
|
|
||||||
errx(EXIT_FAILURE, "pkg-vulnerabilities is too large");
|
|
||||||
*/
|
|
||||||
|
|
||||||
buf_len = st.size;
|
|
||||||
buf = xmalloc(buf_len + 1);
|
|
||||||
buf_fetched = 0;
|
|
||||||
|
|
||||||
while (buf_fetched < buf_len) {
|
|
||||||
cur_fetched = fetchIO_read(f, buf + buf_fetched,
|
|
||||||
buf_len - buf_fetched);
|
|
||||||
if (cur_fetched == 0)
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"Truncated pkg-vulnerabilities received");
|
|
||||||
else if (cur_fetched == -1)
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"IO error while fetching pkg-vulnerabilities: %s",
|
|
||||||
fetchLastErrString);
|
|
||||||
buf_fetched += cur_fetched;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[buf_len] = '\0';
|
|
||||||
|
|
||||||
pv_check = read_pkg_vulnerabilities_memory(buf, buf_len, check_signature);
|
|
||||||
free_pkg_vulnerabilities(pv_check);
|
|
||||||
|
|
||||||
fd = open(pkg_vulnerabilities_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
|
||||||
if (fd == -1)
|
|
||||||
err(EXIT_FAILURE, "Cannot create pkg-vulnerability file %s",
|
|
||||||
pkg_vulnerabilities_file);
|
|
||||||
|
|
||||||
if (write(fd, buf, buf_len) != (ssize_t)buf_len)
|
|
||||||
err(EXIT_FAILURE, "Cannot write pkg-vulnerability file");
|
|
||||||
if (close(fd) == -1)
|
|
||||||
err(EXIT_FAILURE, "Cannot close pkg-vulnerability file after write");
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_pkg_history_pattern(const char *pkg, const char *pattern)
|
|
||||||
{
|
|
||||||
const char *delim, *end_base;
|
|
||||||
|
|
||||||
if ((delim = strchr(pattern, '*')) != NULL) {
|
|
||||||
if ((end_base = strrchr(pattern, '-')) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Missing - in wildcard pattern %s",
|
|
||||||
pattern);
|
|
||||||
if ((delim = strchr(pattern, '>')) != NULL ||
|
|
||||||
(delim = strchr(pattern, '<')) != NULL)
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"Mixed relational and wildcard patterns in %s",
|
|
||||||
pattern);
|
|
||||||
} else if ((delim = strchr(pattern, '>')) != NULL) {
|
|
||||||
end_base = delim;
|
|
||||||
if ((delim = strchr(pattern, '<')) != NULL && delim < end_base)
|
|
||||||
errx(EXIT_FAILURE, "Inverted operators in %s",
|
|
||||||
pattern);
|
|
||||||
} else if ((delim = strchr(pattern, '<')) != NULL) {
|
|
||||||
end_base = delim;
|
|
||||||
} else if ((end_base = strrchr(pattern, '-')) == NULL) {
|
|
||||||
errx(EXIT_FAILURE, "Missing - in absolute pattern %s",
|
|
||||||
pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(pkg, pattern, end_base - pattern) != 0)
|
|
||||||
return 0;
|
|
||||||
if (pkg[end_base - pattern] != '\0')
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_pkg_history1(const char *pkg, const char *pattern)
|
|
||||||
{
|
|
||||||
const char *open_brace, *close_brace, *inner_brace, *suffix, *iter;
|
|
||||||
size_t prefix_len, suffix_len, middle_len;
|
|
||||||
char *expanded_pkg;
|
|
||||||
|
|
||||||
open_brace = strchr(pattern, '{');
|
|
||||||
if (open_brace == NULL) {
|
|
||||||
if ((close_brace = strchr(pattern, '}')) != NULL)
|
|
||||||
errx(EXIT_FAILURE, "Unbalanced {} in pattern %s",
|
|
||||||
pattern);
|
|
||||||
return check_pkg_history_pattern(pkg, pattern);
|
|
||||||
}
|
|
||||||
close_brace = strchr(open_brace, '}');
|
|
||||||
if (strchr(pattern, '}') != close_brace)
|
|
||||||
errx(EXIT_FAILURE, "Unbalanced {} in pattern %s",
|
|
||||||
pattern);
|
|
||||||
|
|
||||||
while ((inner_brace = strchr(open_brace + 1, '{')) != NULL) {
|
|
||||||
if (inner_brace >= close_brace)
|
|
||||||
break;
|
|
||||||
open_brace = inner_brace;
|
|
||||||
}
|
|
||||||
|
|
||||||
expanded_pkg = xmalloc(strlen(pattern)); /* {} are going away... */
|
|
||||||
|
|
||||||
prefix_len = open_brace - pattern;
|
|
||||||
suffix = close_brace + 1;
|
|
||||||
suffix_len = strlen(suffix) + 1;
|
|
||||||
memcpy(expanded_pkg, pattern, prefix_len);
|
|
||||||
|
|
||||||
++open_brace;
|
|
||||||
|
|
||||||
do {
|
|
||||||
iter = strchr(open_brace, ',');
|
|
||||||
if (iter == NULL || iter > close_brace)
|
|
||||||
iter = close_brace;
|
|
||||||
|
|
||||||
middle_len = iter - open_brace;
|
|
||||||
memcpy(expanded_pkg + prefix_len, open_brace, middle_len);
|
|
||||||
memcpy(expanded_pkg + prefix_len + middle_len, suffix,
|
|
||||||
suffix_len);
|
|
||||||
if (check_pkg_history1(pkg, expanded_pkg)) {
|
|
||||||
free(expanded_pkg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
open_brace = iter + 1;
|
|
||||||
} while (iter < close_brace);
|
|
||||||
|
|
||||||
free(expanded_pkg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_pkg_history(const char *pkg)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < pv->entries; ++i) {
|
|
||||||
if (!quick_pkg_match(pv->vulnerability[i], pkg))
|
|
||||||
continue;
|
|
||||||
if (strcmp("eol", pv->classification[i]) == 0)
|
|
||||||
continue;
|
|
||||||
if (check_pkg_history1(pkg, pv->vulnerability[i]) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
printf("%s %s %s\n", pv->vulnerability[i],
|
|
||||||
pv->classification[i], pv->advisory[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
audit_history(int argc, char **argv)
|
|
||||||
{
|
|
||||||
parse_options(argc, argv, "st:");
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
check_and_read_pkg_vulnerabilities();
|
|
||||||
for (; *argv != NULL; ++argv)
|
|
||||||
check_pkg_history(*argv);
|
|
||||||
|
|
||||||
free_pkg_vulnerabilities(pv);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
|
@ -1,263 +0,0 @@
|
||||||
/* $NetBSD: check.c,v 1.10 2010/01/22 13:30:41 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: check.c,v 1.10 2010/01/22 13:30:41 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1999-2008 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Hubert Feyrer <hubert@feyrer.de>.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_DIRENT_H
|
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if !defined(NETBSD) && !defined(__minix)
|
|
||||||
#include <nbcompat/md5.h>
|
|
||||||
#else
|
|
||||||
#include <minix/md5.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_LIMITS_H
|
|
||||||
#include <limits.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "admin.h"
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static int checkpattern_fn(const char *, void *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Assumes CWD is in /var/db/pkg/<pkg>!
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
check1pkg(const char *pkgdir, int *filecnt, int *pkgcnt)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
plist_t *p;
|
|
||||||
package_t Plist;
|
|
||||||
char *PkgName, *dirp = NULL, *md5file;
|
|
||||||
char file[MaxPathSize];
|
|
||||||
char *content;
|
|
||||||
|
|
||||||
content = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME);
|
|
||||||
f = fopen(content, "r");
|
|
||||||
if (f == NULL)
|
|
||||||
err(EXIT_FAILURE, "can't open %s", content);
|
|
||||||
free(content);
|
|
||||||
|
|
||||||
read_plist(&Plist, f);
|
|
||||||
p = find_plist(&Plist, PLIST_NAME);
|
|
||||||
if (p == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Package %s has no @name, aborting.",
|
|
||||||
pkgdir);
|
|
||||||
PkgName = p->name;
|
|
||||||
for (p = Plist.head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_FILE:
|
|
||||||
if (dirp == NULL) {
|
|
||||||
warnx("dirp not initialized, please send-pr!");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name);
|
|
||||||
|
|
||||||
if (isfile(file) || islinktodir(file)) {
|
|
||||||
if (p->next && p->next->type == PLIST_COMMENT) {
|
|
||||||
if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) {
|
|
||||||
if ((md5file = MD5File(file, NULL)) != NULL) {
|
|
||||||
/* Mismatch? */
|
|
||||||
if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0)
|
|
||||||
printf("%s fails MD5 checksum\n", file);
|
|
||||||
|
|
||||||
free(md5file);
|
|
||||||
}
|
|
||||||
} else if (strncmp(p->next->name, SYMLINK_HEADER, SymlinkHeaderLen) == 0) {
|
|
||||||
char buf[MaxPathSize + SymlinkHeaderLen];
|
|
||||||
int cc;
|
|
||||||
|
|
||||||
(void) strlcpy(buf, SYMLINK_HEADER, sizeof(buf));
|
|
||||||
if ((cc = readlink(file, &buf[SymlinkHeaderLen],
|
|
||||||
sizeof(buf) - SymlinkHeaderLen - 1)) < 0) {
|
|
||||||
warnx("can't readlink `%s'", file);
|
|
||||||
} else {
|
|
||||||
buf[SymlinkHeaderLen + cc] = 0x0;
|
|
||||||
if (strcmp(buf, p->next->name) != 0) {
|
|
||||||
printf("symlink (%s) is not same as recorded value, %s: %s\n",
|
|
||||||
file, buf, p->next->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(*filecnt)++;
|
|
||||||
} else if (isbrokenlink(file)) {
|
|
||||||
warnx("%s: Symlink `%s' exists and is in %s but target does not exist!", PkgName, file, CONTENTS_FNAME);
|
|
||||||
} else {
|
|
||||||
warnx("%s: File `%s' is in %s but not on filesystem!", PkgName, file, CONTENTS_FNAME);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PLIST_CWD:
|
|
||||||
if (strcmp(p->name, ".") != 0)
|
|
||||||
dirp = p->name;
|
|
||||||
else
|
|
||||||
dirp = pkgdb_pkg_dir(pkgdir);
|
|
||||||
break;
|
|
||||||
case PLIST_IGNORE:
|
|
||||||
p = p->next;
|
|
||||||
break;
|
|
||||||
case PLIST_SHOW_ALL:
|
|
||||||
case PLIST_SRC:
|
|
||||||
case PLIST_CMD:
|
|
||||||
case PLIST_CHMOD:
|
|
||||||
case PLIST_CHOWN:
|
|
||||||
case PLIST_CHGRP:
|
|
||||||
case PLIST_COMMENT:
|
|
||||||
case PLIST_NAME:
|
|
||||||
case PLIST_UNEXEC:
|
|
||||||
case PLIST_DISPLAY:
|
|
||||||
case PLIST_PKGDEP:
|
|
||||||
case PLIST_DIR_RM:
|
|
||||||
case PLIST_OPTION:
|
|
||||||
case PLIST_PKGCFL:
|
|
||||||
case PLIST_BLDDEP:
|
|
||||||
case PLIST_PKGDIR:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free_plist(&Plist);
|
|
||||||
fclose(f);
|
|
||||||
(*pkgcnt)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct checkpattern_arg {
|
|
||||||
int filecnt;
|
|
||||||
int pkgcnt;
|
|
||||||
int got_match;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
checkpattern_fn(const char *pkg, void *vp)
|
|
||||||
{
|
|
||||||
struct checkpattern_arg *arg = vp;
|
|
||||||
|
|
||||||
check1pkg(pkg, &arg->filecnt, &arg->pkgcnt);
|
|
||||||
if (!quiet)
|
|
||||||
printf(".");
|
|
||||||
|
|
||||||
arg->got_match = 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_pkg(const char *pkg, int *filecnt, int *pkgcnt, int allow_unmatched)
|
|
||||||
{
|
|
||||||
struct checkpattern_arg arg;
|
|
||||||
char *pattern;
|
|
||||||
|
|
||||||
arg.filecnt = *filecnt;
|
|
||||||
arg.pkgcnt = *pkgcnt;
|
|
||||||
arg.got_match = 0;
|
|
||||||
|
|
||||||
if (match_installed_pkgs(pkg, checkpattern_fn, &arg) == -1)
|
|
||||||
errx(EXIT_FAILURE, "Cannot process pkdbdb");
|
|
||||||
if (arg.got_match != 0) {
|
|
||||||
*filecnt = arg.filecnt;
|
|
||||||
*pkgcnt = arg.pkgcnt;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ispkgpattern(pkg)) {
|
|
||||||
if (allow_unmatched)
|
|
||||||
return;
|
|
||||||
errx(EXIT_FAILURE, "No matching pkg for %s.", pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern = xasprintf("%s-[0-9]*", pkg);
|
|
||||||
|
|
||||||
if (match_installed_pkgs(pattern, checkpattern_fn, &arg) == -1)
|
|
||||||
errx(EXIT_FAILURE, "Cannot process pkdbdb");
|
|
||||||
|
|
||||||
if (arg.got_match == 0)
|
|
||||||
errx(EXIT_FAILURE, "cannot find package %s", pkg);
|
|
||||||
free(pattern);
|
|
||||||
|
|
||||||
*filecnt = arg.filecnt;
|
|
||||||
*pkgcnt = arg.pkgcnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check(char **argv)
|
|
||||||
{
|
|
||||||
int filecnt, pkgcnt;
|
|
||||||
|
|
||||||
filecnt = 0;
|
|
||||||
pkgcnt = 0;
|
|
||||||
setbuf(stdout, NULL);
|
|
||||||
|
|
||||||
if (*argv == NULL) {
|
|
||||||
check_pkg("*", &filecnt, &pkgcnt, 1);
|
|
||||||
} else {
|
|
||||||
for (; *argv != NULL; ++argv)
|
|
||||||
check_pkg(*argv, &filecnt, &pkgcnt, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
printf("Checked %d file%s from %d package%s.\n",
|
|
||||||
filecnt, (filecnt == 1) ? "" : "s",
|
|
||||||
pkgcnt, (pkgcnt == 1) ? "" : "s");
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
pkg_admin=/usr/bin/sbin/pkg_admin
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo 'Usage: download-vulnerability-list [-hs] [-c config_file]' >& $2
|
|
||||||
echo "Please use \`\`pkg_admin fetch-pkg-vulnerabilities'' instead." >& $2
|
|
||||||
exit $1
|
|
||||||
}
|
|
||||||
|
|
||||||
do_sign=
|
|
||||||
|
|
||||||
args=`getopt c:hs $*`
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
usage 1 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -- $args
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
-c)
|
|
||||||
echo "The download-vulnerability-list wrapper does not support -c" >&2
|
|
||||||
echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
-h)
|
|
||||||
usage 0 1
|
|
||||||
;;
|
|
||||||
-s)
|
|
||||||
do_sign=-s
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
exec ${pkg_admin} fetch-pkg-vulnerabilities ${do_sign}
|
|
|
@ -1,54 +0,0 @@
|
||||||
.\" $NetBSD: download-vulnerability-list.8,v 1.1 2010/03/19 12:49:53 wiz Exp $
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 2010 The NetBSD Foundation, Inc.
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
.\" by Thomas Klausner.
|
|
||||||
.\"
|
|
||||||
.\" 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.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd March 18, 2010
|
|
||||||
.Dt DOWNLOAD-VULNERABILITY-LIST 8
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm download-vulnerability-list
|
|
||||||
.Nd download vulnerability list used for checking installed packages
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl hs
|
|
||||||
.Op Fl c Ar config_file
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
is deprecated.
|
|
||||||
Please use the
|
|
||||||
.Cm fetch-pkg-vulnerabilities
|
|
||||||
command of
|
|
||||||
.Xr pkg_admin 1
|
|
||||||
instead.
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
script is installed for backwards compatibility only and will
|
|
||||||
eventually be removed.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_admin 1
|
|
|
@ -1,758 +0,0 @@
|
||||||
/* $NetBSD: main.c,v 1.61 2010/04/20 00:39:13 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: main.c,v 1.61 2010/04/20 00:39:13 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1999-2009 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Hubert Feyrer <hubert@feyrer.de> and
|
|
||||||
* by Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_DIRENT_H
|
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if !defined(NETBSD) && !defined(__minix)
|
|
||||||
#include <nbcompat/md5.h>
|
|
||||||
#else
|
|
||||||
#include <minix/md5.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_LIMITS_H
|
|
||||||
#include <limits.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
#include <archive.h>
|
|
||||||
#include <fetch.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "admin.h"
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#define DEFAULT_SFX ".t[bg]z" /* default suffix for ls{all,best} */
|
|
||||||
|
|
||||||
struct pkgdb_count {
|
|
||||||
size_t files;
|
|
||||||
size_t directories;
|
|
||||||
size_t packages;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char Options[] = "C:K:SVbd:qs:v";
|
|
||||||
|
|
||||||
int quiet, verbose;
|
|
||||||
|
|
||||||
static void set_unset_variable(char **, Boolean);
|
|
||||||
|
|
||||||
/* print usage message and exit */
|
|
||||||
void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
(void) fprintf(stderr, "usage: %s [-bqSVv] [-C config] [-d lsdir] [-K pkg_dbdir] [-s sfx] command [args ...]\n"
|
|
||||||
"Where 'commands' and 'args' are:\n"
|
|
||||||
" rebuild - rebuild pkgdb from +CONTENTS files\n"
|
|
||||||
" rebuild-tree - rebuild +REQUIRED_BY files from forward deps\n"
|
|
||||||
" check [pkg ...] - check md5 checksum of installed files\n"
|
|
||||||
" add pkg ... - add pkg files to database\n"
|
|
||||||
" delete pkg ... - delete file entries for pkg in database\n"
|
|
||||||
" set variable=value pkg ... - set installation variable for package\n"
|
|
||||||
" unset variable pkg ... - unset installation variable for package\n"
|
|
||||||
" lsall /path/to/pkgpattern - list all pkgs matching the pattern\n"
|
|
||||||
" lsbest /path/to/pkgpattern - list pkgs matching the pattern best\n"
|
|
||||||
" dump - dump database\n"
|
|
||||||
" pmatch pattern pkg - returns true if pkg matches pattern, otherwise false\n"
|
|
||||||
" fetch-pkg-vulnerabilities [-s] - fetch new vulnerability file\n"
|
|
||||||
" check-pkg-vulnerabilities [-s] <file> - check syntax and checksums of the vulnerability file\n"
|
|
||||||
" audit [-es] [-t type] ... - check installed packages for vulnerabilities\n"
|
|
||||||
" audit-pkg [-es] [-t type] ... - check listed packages for vulnerabilities\n"
|
|
||||||
" audit-batch [-es] [-t type] ... - check packages in listed files for vulnerabilities\n"
|
|
||||||
" audit-history [-t type] ... - print all advisories for package names\n"
|
|
||||||
" check-license <condition> - check if condition is acceptable\n"
|
|
||||||
" check-single-license <license> - check if license is acceptable\n"
|
|
||||||
" config-var name - print current value of the configuration variable\n"
|
|
||||||
" check-signature ... - verify the signature of packages\n"
|
|
||||||
" x509-sign-package pkg spkg key cert - create X509 signature\n"
|
|
||||||
" gpg-sign-package pkg spkg - create GPG signature\n",
|
|
||||||
getprogname());
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* add1pkg(<pkg>)
|
|
||||||
* adds the files listed in the +CONTENTS of <pkg> into the
|
|
||||||
* pkgdb.byfile.db database file in the current package dbdir. It
|
|
||||||
* returns the number of files added to the database file.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
add_pkg(const char *pkgdir, void *vp)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
plist_t *p;
|
|
||||||
package_t Plist;
|
|
||||||
char *contents;
|
|
||||||
char *PkgName, *dirp;
|
|
||||||
char file[MaxPathSize];
|
|
||||||
struct pkgdb_count *count;
|
|
||||||
|
|
||||||
if (!pkgdb_open(ReadWrite))
|
|
||||||
err(EXIT_FAILURE, "cannot open pkgdb");
|
|
||||||
|
|
||||||
count = vp;
|
|
||||||
++count->packages;
|
|
||||||
|
|
||||||
contents = pkgdb_pkg_file(pkgdir, CONTENTS_FNAME);
|
|
||||||
if ((f = fopen(contents, "r")) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "%s: can't open `%s'", pkgdir, CONTENTS_FNAME);
|
|
||||||
free(contents);
|
|
||||||
|
|
||||||
read_plist(&Plist, f);
|
|
||||||
if ((p = find_plist(&Plist, PLIST_NAME)) == NULL) {
|
|
||||||
errx(EXIT_FAILURE, "Package `%s' has no @name, aborting.", pkgdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
PkgName = p->name;
|
|
||||||
dirp = NULL;
|
|
||||||
for (p = Plist.head; p; p = p->next) {
|
|
||||||
switch(p->type) {
|
|
||||||
case PLIST_FILE:
|
|
||||||
if (dirp == NULL) {
|
|
||||||
errx(EXIT_FAILURE, "@cwd not yet found, please send-pr!");
|
|
||||||
}
|
|
||||||
(void) snprintf(file, sizeof(file), "%s/%s", dirp, p->name);
|
|
||||||
if (!(isfile(file) || islinktodir(file))) {
|
|
||||||
if (isbrokenlink(file)) {
|
|
||||||
warnx("%s: Symlink `%s' exists and is in %s but target does not exist!",
|
|
||||||
PkgName, file, CONTENTS_FNAME);
|
|
||||||
} else {
|
|
||||||
warnx("%s: File `%s' is in %s but not on filesystem!",
|
|
||||||
PkgName, file, CONTENTS_FNAME);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pkgdb_store(file, PkgName);
|
|
||||||
++count->files;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PLIST_PKGDIR:
|
|
||||||
add_pkgdir(PkgName, dirp, p->name);
|
|
||||||
++count->directories;
|
|
||||||
break;
|
|
||||||
case PLIST_CWD:
|
|
||||||
if (strcmp(p->name, ".") != 0)
|
|
||||||
dirp = p->name;
|
|
||||||
else
|
|
||||||
dirp = pkgdb_pkg_dir(pkgdir);
|
|
||||||
break;
|
|
||||||
case PLIST_IGNORE:
|
|
||||||
p = p->next;
|
|
||||||
break;
|
|
||||||
case PLIST_SHOW_ALL:
|
|
||||||
case PLIST_SRC:
|
|
||||||
case PLIST_CMD:
|
|
||||||
case PLIST_CHMOD:
|
|
||||||
case PLIST_CHOWN:
|
|
||||||
case PLIST_CHGRP:
|
|
||||||
case PLIST_COMMENT:
|
|
||||||
case PLIST_NAME:
|
|
||||||
case PLIST_UNEXEC:
|
|
||||||
case PLIST_DISPLAY:
|
|
||||||
case PLIST_PKGDEP:
|
|
||||||
case PLIST_DIR_RM:
|
|
||||||
case PLIST_OPTION:
|
|
||||||
case PLIST_PKGCFL:
|
|
||||||
case PLIST_BLDDEP:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free_plist(&Plist);
|
|
||||||
fclose(f);
|
|
||||||
pkgdb_close();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
delete1pkg(const char *pkgdir)
|
|
||||||
{
|
|
||||||
if (!pkgdb_open(ReadWrite))
|
|
||||||
err(EXIT_FAILURE, "cannot open pkgdb");
|
|
||||||
(void) pkgdb_remove_pkg(pkgdir);
|
|
||||||
pkgdb_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rebuild(void)
|
|
||||||
{
|
|
||||||
char *cachename;
|
|
||||||
struct pkgdb_count count;
|
|
||||||
|
|
||||||
count.files = 0;
|
|
||||||
count.directories = 0;
|
|
||||||
count.packages = 0;
|
|
||||||
|
|
||||||
cachename = pkgdb_get_database();
|
|
||||||
if (unlink(cachename) != 0 && errno != ENOENT)
|
|
||||||
err(EXIT_FAILURE, "unlink %s", cachename);
|
|
||||||
|
|
||||||
setbuf(stdout, NULL);
|
|
||||||
|
|
||||||
iterate_pkg_db(add_pkg, &count);
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
printf("Stored %" PRIzu " file%s and %zu explicit director%s"
|
|
||||||
" from %"PRIzu " package%s in %s.\n",
|
|
||||||
count.files, count.files == 1 ? "" : "s",
|
|
||||||
count.directories, count.directories == 1 ? "y" : "ies",
|
|
||||||
count.packages, count.packages == 1 ? "" : "s",
|
|
||||||
cachename);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
lspattern(const char *pkg, void *vp)
|
|
||||||
{
|
|
||||||
const char *dir = vp;
|
|
||||||
printf("%s/%s\n", dir, pkg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
lsbasepattern(const char *pkg, void *vp)
|
|
||||||
{
|
|
||||||
puts(pkg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
remove_required_by(const char *pkgname, void *cookie)
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
path = pkgdb_pkg_file(pkgname, REQUIRED_BY_FNAME);
|
|
||||||
|
|
||||||
if (unlink(path) == -1 && errno != ENOENT)
|
|
||||||
err(EXIT_FAILURE, "Cannot remove %s", path);
|
|
||||||
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
add_required_by(const char *pattern, const char *required_by)
|
|
||||||
{
|
|
||||||
char *best_installed, *path;
|
|
||||||
int fd;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
best_installed = find_best_matching_installed_pkg(pattern);
|
|
||||||
if (best_installed == NULL) {
|
|
||||||
warnx("Dependency %s of %s unresolved", pattern, required_by);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = pkgdb_pkg_file(best_installed, REQUIRED_BY_FNAME);
|
|
||||||
free(best_installed);
|
|
||||||
|
|
||||||
if ((fd = open(path, O_WRONLY | O_APPEND | O_CREAT, 0644)) == -1)
|
|
||||||
errx(EXIT_FAILURE, "Cannot write to %s", path);
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
len = strlen(required_by);
|
|
||||||
if (write(fd, required_by, len) != (ssize_t)len ||
|
|
||||||
write(fd, "\n", 1) != 1 ||
|
|
||||||
close(fd) == -1)
|
|
||||||
errx(EXIT_FAILURE, "Cannot write to %s", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
add_depends_of(const char *pkgname, void *cookie)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
plist_t *p;
|
|
||||||
package_t plist;
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
path = pkgdb_pkg_file(pkgname, CONTENTS_FNAME);
|
|
||||||
if ((fp = fopen(path, "r")) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Cannot read %s of package %s",
|
|
||||||
CONTENTS_FNAME, pkgname);
|
|
||||||
free(path);
|
|
||||||
read_plist(&plist, fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
for (p = plist.head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_PKGDEP)
|
|
||||||
add_required_by(p->name, pkgname);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_plist(&plist);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rebuild_tree(void)
|
|
||||||
{
|
|
||||||
if (iterate_pkg_db(remove_required_by, NULL) == -1)
|
|
||||||
errx(EXIT_FAILURE, "cannot iterate pkgdb");
|
|
||||||
if (iterate_pkg_db(add_depends_of, NULL) == -1)
|
|
||||||
errx(EXIT_FAILURE, "cannot iterate pkgdb");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
Boolean use_default_sfx = TRUE;
|
|
||||||
Boolean show_basename_only = FALSE;
|
|
||||||
char lsdir[MaxPathSize];
|
|
||||||
char sfx[MaxPathSize];
|
|
||||||
char *lsdirp = NULL;
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
setprogname(argv[0]);
|
|
||||||
|
|
||||||
if (argc < 2)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, Options)) != -1)
|
|
||||||
switch (ch) {
|
|
||||||
case 'C':
|
|
||||||
config_file = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'K':
|
|
||||||
pkgdb_set_dir(optarg, 3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
sfx[0] = 0x0;
|
|
||||||
use_default_sfx = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'V':
|
|
||||||
show_version();
|
|
||||||
/* NOTREACHED */
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
show_basename_only = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
(void) strlcpy(lsdir, optarg, sizeof(lsdir));
|
|
||||||
lsdirp = lsdir;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'q':
|
|
||||||
quiet = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
(void) strlcpy(sfx, optarg, sizeof(sfx));
|
|
||||||
use_default_sfx = FALSE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
++verbose;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (argc <= 0) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* config-var is reading the config file implicitly,
|
|
||||||
* so skip it here.
|
|
||||||
*/
|
|
||||||
if (strcasecmp(argv[0], "config-var") != 0)
|
|
||||||
pkg_install_config();
|
|
||||||
|
|
||||||
if (use_default_sfx)
|
|
||||||
(void) strlcpy(sfx, DEFAULT_SFX, sizeof(sfx));
|
|
||||||
|
|
||||||
if (strcasecmp(argv[0], "pmatch") == 0) {
|
|
||||||
|
|
||||||
char *pattern, *pkg;
|
|
||||||
|
|
||||||
argv++; /* "pmatch" */
|
|
||||||
|
|
||||||
if (argv[0] == NULL || argv[1] == NULL) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
pattern = argv[0];
|
|
||||||
pkg = argv[1];
|
|
||||||
|
|
||||||
if (pkg_match(pattern, pkg)){
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "rebuild") == 0) {
|
|
||||||
|
|
||||||
rebuild();
|
|
||||||
printf("Done.\n");
|
|
||||||
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "rebuild-tree") == 0) {
|
|
||||||
|
|
||||||
rebuild_tree();
|
|
||||||
printf("Done.\n");
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "check") == 0) {
|
|
||||||
argv++; /* "check" */
|
|
||||||
|
|
||||||
check(argv);
|
|
||||||
|
|
||||||
if (!quiet) {
|
|
||||||
printf("Done.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "lsall") == 0) {
|
|
||||||
argv++; /* "lsall" */
|
|
||||||
|
|
||||||
while (*argv != NULL) {
|
|
||||||
/* args specified */
|
|
||||||
int rc;
|
|
||||||
const char *basep, *dir;
|
|
||||||
|
|
||||||
dir = lsdirp ? lsdirp : dirname_of(*argv);
|
|
||||||
basep = basename_of(*argv);
|
|
||||||
|
|
||||||
if (show_basename_only)
|
|
||||||
rc = match_local_files(dir, use_default_sfx, 1, basep, lsbasepattern, NULL);
|
|
||||||
else
|
|
||||||
rc = match_local_files(dir, use_default_sfx, 1, basep, lspattern, __UNCONST(dir));
|
|
||||||
if (rc == -1)
|
|
||||||
errx(EXIT_FAILURE, "Error from match_local_files(\"%s\", \"%s\", ...)",
|
|
||||||
dir, basep);
|
|
||||||
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "lsbest") == 0) {
|
|
||||||
argv++; /* "lsbest" */
|
|
||||||
|
|
||||||
while (*argv != NULL) {
|
|
||||||
/* args specified */
|
|
||||||
const char *basep, *dir;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
dir = lsdirp ? lsdirp : dirname_of(*argv);
|
|
||||||
basep = basename_of(*argv);
|
|
||||||
|
|
||||||
p = find_best_matching_file(dir, basep, use_default_sfx, 1);
|
|
||||||
|
|
||||||
if (p) {
|
|
||||||
if (show_basename_only)
|
|
||||||
printf("%s\n", p);
|
|
||||||
else
|
|
||||||
printf("%s/%s\n", dir, p);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
} else if (strcasecmp(argv[0], "list") == 0 ||
|
|
||||||
strcasecmp(argv[0], "dump") == 0) {
|
|
||||||
|
|
||||||
pkgdb_dump();
|
|
||||||
|
|
||||||
} else if (strcasecmp(argv[0], "add") == 0) {
|
|
||||||
struct pkgdb_count count;
|
|
||||||
|
|
||||||
count.files = 0;
|
|
||||||
count.directories = 0;
|
|
||||||
count.packages = 0;
|
|
||||||
|
|
||||||
for (++argv; *argv != NULL; ++argv)
|
|
||||||
add_pkg(*argv, &count);
|
|
||||||
} else if (strcasecmp(argv[0], "delete") == 0) {
|
|
||||||
argv++; /* "delete" */
|
|
||||||
while (*argv != NULL) {
|
|
||||||
delete1pkg(*argv);
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
} else if (strcasecmp(argv[0], "set") == 0) {
|
|
||||||
argv++; /* "set" */
|
|
||||||
set_unset_variable(argv, FALSE);
|
|
||||||
} else if (strcasecmp(argv[0], "unset") == 0) {
|
|
||||||
argv++; /* "unset" */
|
|
||||||
set_unset_variable(argv, TRUE);
|
|
||||||
} else if (strcasecmp(argv[0], "config-var") == 0) {
|
|
||||||
argv++;
|
|
||||||
if (argv == NULL || argv[1] != NULL)
|
|
||||||
errx(EXIT_FAILURE, "config-var takes exactly one argument");
|
|
||||||
pkg_install_show_variable(argv[0]);
|
|
||||||
} else if (strcasecmp(argv[0], "check-license") == 0) {
|
|
||||||
if (argv[1] == NULL)
|
|
||||||
errx(EXIT_FAILURE, "check-license takes exactly one argument");
|
|
||||||
|
|
||||||
load_license_lists();
|
|
||||||
|
|
||||||
switch (acceptable_pkg_license(argv[1])) {
|
|
||||||
case 0:
|
|
||||||
puts("no");
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
puts("yes");
|
|
||||||
return 0;
|
|
||||||
case -1:
|
|
||||||
errx(EXIT_FAILURE, "invalid license condition");
|
|
||||||
}
|
|
||||||
} else if (strcasecmp(argv[0], "check-single-license") == 0) {
|
|
||||||
if (argv[1] == NULL)
|
|
||||||
errx(EXIT_FAILURE, "check-license takes exactly one argument");
|
|
||||||
load_license_lists();
|
|
||||||
|
|
||||||
switch (acceptable_license(argv[1])) {
|
|
||||||
case 0:
|
|
||||||
puts("no");
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
puts("yes");
|
|
||||||
return 0;
|
|
||||||
case -1:
|
|
||||||
errx(EXIT_FAILURE, "invalid license");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
else if (strcasecmp(argv[0], "findbest") == 0) {
|
|
||||||
struct url *url;
|
|
||||||
char *output;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
process_pkg_path();
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
for (++argv; *argv != NULL; ++argv) {
|
|
||||||
url = find_best_package(NULL, *argv, 1);
|
|
||||||
if (url == NULL) {
|
|
||||||
rc = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
output = fetchStringifyURL(url);
|
|
||||||
puts(output);
|
|
||||||
fetchFreeURL(url);
|
|
||||||
free(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
} else if (strcasecmp(argv[0], "fetch-pkg-vulnerabilities") == 0) {
|
|
||||||
fetch_pkg_vulnerabilities(--argc, ++argv);
|
|
||||||
} else if (strcasecmp(argv[0], "check-pkg-vulnerabilities") == 0) {
|
|
||||||
check_pkg_vulnerabilities(--argc, ++argv);
|
|
||||||
} else if (strcasecmp(argv[0], "audit") == 0) {
|
|
||||||
audit_pkgdb(--argc, ++argv);
|
|
||||||
} else if (strcasecmp(argv[0], "audit-pkg") == 0) {
|
|
||||||
audit_pkg(--argc, ++argv);
|
|
||||||
} else if (strcasecmp(argv[0], "audit-batch") == 0) {
|
|
||||||
audit_batch(--argc, ++argv);
|
|
||||||
} else if (strcasecmp(argv[0], "audit-history") == 0) {
|
|
||||||
audit_history(--argc, ++argv);
|
|
||||||
} else if (strcasecmp(argv[0], "check-signature") == 0) {
|
|
||||||
struct archive *pkg;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
for (--argc, ++argv; argc > 0; --argc, ++argv) {
|
|
||||||
char *archive_name;
|
|
||||||
|
|
||||||
pkg = open_archive(*argv, &archive_name);
|
|
||||||
if (pkg == NULL) {
|
|
||||||
warnx("%s could not be opened", *argv);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pkg_full_signature_check(archive_name, &pkg))
|
|
||||||
rc = 1;
|
|
||||||
free(archive_name);
|
|
||||||
if (!pkg)
|
|
||||||
archive_read_finish(pkg);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
} else if (strcasecmp(argv[0], "x509-sign-package") == 0) {
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
--argc;
|
|
||||||
++argv;
|
|
||||||
if (argc != 4)
|
|
||||||
errx(EXIT_FAILURE, "x509-sign-package takes exactly four arguments");
|
|
||||||
pkg_sign_x509(argv[0], argv[1], argv[2], argv[3]);
|
|
||||||
#else
|
|
||||||
errx(EXIT_FAILURE, "OpenSSL support is not included");
|
|
||||||
#endif
|
|
||||||
} else if (strcasecmp(argv[0], "gpg-sign-package") == 0) {
|
|
||||||
--argc;
|
|
||||||
++argv;
|
|
||||||
if (argc != 2)
|
|
||||||
errx(EXIT_FAILURE, "gpg-sign-package takes exactly two arguments");
|
|
||||||
pkg_sign_gpg(argv[0], argv[1]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct set_installed_info_arg {
|
|
||||||
char *variable;
|
|
||||||
char *value;
|
|
||||||
int got_match;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
set_installed_info_var(const char *name, void *cookie)
|
|
||||||
{
|
|
||||||
struct set_installed_info_arg *arg = cookie;
|
|
||||||
char *filename;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
filename = pkgdb_pkg_file(name, INSTALLED_INFO_FNAME);
|
|
||||||
|
|
||||||
retval = var_set(filename, arg->variable, arg->value);
|
|
||||||
|
|
||||||
free(filename);
|
|
||||||
arg->got_match = 1;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_unset_variable(char **argv, Boolean unset)
|
|
||||||
{
|
|
||||||
struct set_installed_info_arg arg;
|
|
||||||
char *eq;
|
|
||||||
char *variable;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (argv[0] == NULL || argv[1] == NULL)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
variable = NULL;
|
|
||||||
|
|
||||||
if (unset) {
|
|
||||||
arg.variable = argv[0];
|
|
||||||
arg.value = NULL;
|
|
||||||
} else {
|
|
||||||
eq = NULL;
|
|
||||||
if ((eq=strchr(argv[0], '=')) == NULL)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
variable = xmalloc(eq-argv[0]+1);
|
|
||||||
strlcpy(variable, argv[0], eq-argv[0]+1);
|
|
||||||
|
|
||||||
arg.variable = variable;
|
|
||||||
arg.value = eq+1;
|
|
||||||
|
|
||||||
if (strcmp(variable, AUTOMATIC_VARNAME) == 0 &&
|
|
||||||
strcasecmp(arg.value, "yes") != 0 &&
|
|
||||||
strcasecmp(arg.value, "no") != 0) {
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"unknown value `%s' for " AUTOMATIC_VARNAME,
|
|
||||||
arg.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strpbrk(arg.variable, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") != NULL) {
|
|
||||||
free(variable);
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"variable name must not contain uppercase letters");
|
|
||||||
}
|
|
||||||
|
|
||||||
argv++;
|
|
||||||
while (*argv != NULL) {
|
|
||||||
arg.got_match = 0;
|
|
||||||
if (match_installed_pkgs(*argv, set_installed_info_var, &arg) == -1)
|
|
||||||
errx(EXIT_FAILURE, "Cannot process pkdbdb");
|
|
||||||
if (arg.got_match == 0) {
|
|
||||||
char *pattern;
|
|
||||||
|
|
||||||
if (ispkgpattern(*argv)) {
|
|
||||||
warnx("no matching pkg for `%s'", *argv);
|
|
||||||
ret++;
|
|
||||||
} else {
|
|
||||||
pattern = xasprintf("%s-[0-9]*", *argv);
|
|
||||||
|
|
||||||
if (match_installed_pkgs(pattern, set_installed_info_var, &arg) == -1)
|
|
||||||
errx(EXIT_FAILURE, "Cannot process pkdbdb");
|
|
||||||
|
|
||||||
if (arg.got_match == 0) {
|
|
||||||
warnx("cannot find package %s", *argv);
|
|
||||||
++ret;
|
|
||||||
}
|
|
||||||
free(pattern);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret > 0)
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
free(variable);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,322 +0,0 @@
|
||||||
.\" $NetBSD: pkg_admin.1,v 1.32 2010/06/16 23:02:48 joerg Exp $
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 1999-2010 The NetBSD Foundation, Inc.
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
.\" by Hubert Feyrer <hubert@feyrer.de>.
|
|
||||||
.\"
|
|
||||||
.\" 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.
|
|
||||||
.\" 3. All advertising materials mentioning features or use of this software
|
|
||||||
.\" must display the following acknowledgement:
|
|
||||||
.\" This product includes software developed by the NetBSD
|
|
||||||
.\" Foundation, Inc. and its contributors.
|
|
||||||
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
||||||
.\" contributors may be used to endorse or promote products derived
|
|
||||||
.\" from this software without specific prior written permission.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd June 16, 2010
|
|
||||||
.Dt PKG_ADMIN 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pkg_admin
|
|
||||||
.Nd perform various administrative tasks to the pkg system
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl bqSVv
|
|
||||||
.Op Fl C Ar config
|
|
||||||
.Op Fl d Ar lsdir
|
|
||||||
.Op Fl K Ar pkg_dbdir
|
|
||||||
.Op Fl s Ar sfx_pattern
|
|
||||||
.Ar command Op args ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
This command performs various administrative tasks around the
|
|
||||||
.Nx
|
|
||||||
Packages System.
|
|
||||||
.Sh OPTIONS
|
|
||||||
The following command-line options are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Fl b
|
|
||||||
Print only the base names when matching package names for
|
|
||||||
.Cm lsall
|
|
||||||
and
|
|
||||||
.Cm lsbest .
|
|
||||||
.It Fl C Ar config
|
|
||||||
Read the configuration file from
|
|
||||||
.Ar config
|
|
||||||
instead of the system default.
|
|
||||||
.It Fl d Ar lsdir
|
|
||||||
Set
|
|
||||||
.Ar lsdir
|
|
||||||
as the path to the directory in which to find matching package names for
|
|
||||||
.Cm lsall
|
|
||||||
and
|
|
||||||
.Cm lsbest .
|
|
||||||
.It Fl K Ar pkg_dbdir
|
|
||||||
Override the value of the
|
|
||||||
.Dv PKG_DBDIR
|
|
||||||
configuration option with the value
|
|
||||||
.Ar pkg_dbdir .
|
|
||||||
.It Fl q
|
|
||||||
Perform checks in a quiet manner.
|
|
||||||
In normal operation,
|
|
||||||
.Nm
|
|
||||||
prints a
|
|
||||||
.Sq \&.
|
|
||||||
to standard output to indicate progress.
|
|
||||||
This option suppresses this progress indicator.
|
|
||||||
.It Fl S
|
|
||||||
Set the shell glob pattern for package suffixes when matching package
|
|
||||||
names for
|
|
||||||
.Cm lsall
|
|
||||||
and
|
|
||||||
.Cm lsbest
|
|
||||||
to be the null suffix.
|
|
||||||
.It Fl s Ar sfx_pattern
|
|
||||||
Set the shell glob pattern for package suffixes when matching package
|
|
||||||
names for
|
|
||||||
.Cm lsall
|
|
||||||
and
|
|
||||||
.Cm lsbest .
|
|
||||||
The default pattern is ".t[bg]z".
|
|
||||||
.It Fl V
|
|
||||||
Print version number and exit.
|
|
||||||
.It Fl v
|
|
||||||
Be more verbose.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
The following commands are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Cm add Ar pkg ...
|
|
||||||
For each listed package, write the absolute pathnames of the files listed in
|
|
||||||
its
|
|
||||||
.Pa +CONTENTS
|
|
||||||
file together with the package they belong to into the package database.
|
|
||||||
This should be used only by
|
|
||||||
.Xr pkg_view 1 .
|
|
||||||
.It Cm audit Oo Fl es Oc Oo Fl t Ar type Oc Oo Ar pkg Oc ...
|
|
||||||
Check the listed installed packages for vulnerabilities.
|
|
||||||
If no package is given, check all installed packages.
|
|
||||||
If
|
|
||||||
.Fl e
|
|
||||||
is given, override the
|
|
||||||
.Dv CHECK_END_OF_LIFE
|
|
||||||
option from
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
with
|
|
||||||
.Qq Li yes .
|
|
||||||
If
|
|
||||||
.Fl s
|
|
||||||
is given, check the signature of the pkg-vulnerabilities file before using it.
|
|
||||||
.Fl t
|
|
||||||
restricts the reported vulnerabilities to type
|
|
||||||
.Ar type .
|
|
||||||
.It Cm audit-pkg Oo Fl es Oc Oo Fl t Ar type Oc Oo Ar pkg Oc ...
|
|
||||||
Like
|
|
||||||
.Cm audit ,
|
|
||||||
but check only the given package names or patterns.
|
|
||||||
.It Cm audit-batch Oo Fl es Oc Oo Fl t Ar type Oc Oo Ar pkg-list Oc ...
|
|
||||||
Like
|
|
||||||
.Cm audit-pkg ,
|
|
||||||
but read the package names or patterns one per line from the given files.
|
|
||||||
.It Cm audit-history Oo Fl s Oc Oo Fl t Ar type Oc Oo Ar pkgbase Oc ...
|
|
||||||
Print all vulnerabilities for the given base package names.
|
|
||||||
.It Cm check Op Ar pkg ...
|
|
||||||
Use this command to check the files belonging to some or all of the
|
|
||||||
packages installed on the local machine against the checksum
|
|
||||||
which was recorded in the
|
|
||||||
.Pa +CONTENTS
|
|
||||||
files at package installation time.
|
|
||||||
Symbolic links also have their integrity checked against the recorded
|
|
||||||
value at package installation time.
|
|
||||||
If no additional argument is given, the files of all installed packages
|
|
||||||
are checked, else only the named packages will be checked (wildcards can
|
|
||||||
be used here, see
|
|
||||||
.Xr pkg_info 1 ) .
|
|
||||||
.Pp
|
|
||||||
The packages'
|
|
||||||
.Pa +CONTENTS
|
|
||||||
files will be parsed and the
|
|
||||||
checksum will be checked for every file found.
|
|
||||||
A warning message is printed if the expected checksum differs from the
|
|
||||||
checksum of the file on disk.
|
|
||||||
Symbolic links are also checked, ensuring that the targets on disk are
|
|
||||||
the same as the contents recorded at package installation time.
|
|
||||||
.It Cm check-license Ar condition
|
|
||||||
Check if
|
|
||||||
.Ar condition
|
|
||||||
can be fulfilled with the currently set of accepted licenses.
|
|
||||||
Prints either yes or no to stdout if the condition can be parsed,
|
|
||||||
otherwise it exits with error.
|
|
||||||
.It Cm check-pkg-vulnerabilities Oo Fl s Oc Ar file
|
|
||||||
Check format and hashes in the pkg-vulnerabilities file
|
|
||||||
.Ar file .
|
|
||||||
If
|
|
||||||
.Fl s
|
|
||||||
is given, also check the embedded signature.
|
|
||||||
.It Cm check-signature Ar file ...
|
|
||||||
Reports if
|
|
||||||
.Ar file
|
|
||||||
is a correctly signed package.
|
|
||||||
.It Cm check-single-license Ar license
|
|
||||||
Check if
|
|
||||||
.Ar license
|
|
||||||
is a valid license name and if it is in the set of acceptable licenses.
|
|
||||||
Prints either yes or no to stdout if the condition can be parsed,
|
|
||||||
otherwise it exits with error.
|
|
||||||
.It Cm config-var Ar variable
|
|
||||||
Print the current value of
|
|
||||||
.Ar variable
|
|
||||||
as used after parsing the configuration file.
|
|
||||||
.It Cm delete Ar pkg ...
|
|
||||||
For each listed package, remove all file entries in the package database that
|
|
||||||
belong to the package.
|
|
||||||
This should be used only by
|
|
||||||
.Xr pkg_view 1 .
|
|
||||||
.It Cm dump
|
|
||||||
Dump the contents of the package database, similar to
|
|
||||||
.Cm pkg_info -F .
|
|
||||||
Columns are printed for the key field used in the pkgdb - the filename -,
|
|
||||||
and the data field - the package the file belongs to.
|
|
||||||
.It Cm fetch-pkg-vulnerabilities Oo Fl su Oc
|
|
||||||
Fetch a new pkg-vulnerabilities file, check the format and if
|
|
||||||
.Fl s
|
|
||||||
is given the signature.
|
|
||||||
If all checks are passed, write it to pkgdb.
|
|
||||||
If
|
|
||||||
.Fl u
|
|
||||||
is given, the fetch is conditional and the file transfer is only done if
|
|
||||||
the remote version is newer than the one in pkgdb.
|
|
||||||
.It Cm findbest Ar pattern ...
|
|
||||||
Search the entries of
|
|
||||||
.Dv PKG_PATH
|
|
||||||
for packages matching
|
|
||||||
.Ar pattern .
|
|
||||||
Print the URL of the best matching package to stdout for each pattern.
|
|
||||||
If a pattern is not matched, it is skipped and the command will return
|
|
||||||
a failure.
|
|
||||||
.It Cm lsall Ar /dir/pkgpattern
|
|
||||||
.It Cm lsbest Ar /dir/pkgpattern
|
|
||||||
List all/best package matching pattern in the given directory
|
|
||||||
.Pa /dir .
|
|
||||||
If the
|
|
||||||
.Fl d
|
|
||||||
flag is given, then that directory path overrides
|
|
||||||
.Pa /dir .
|
|
||||||
Can be used to work around limitations of /bin/sh and other
|
|
||||||
filename globbing mechanisms.
|
|
||||||
This option implements matching of
|
|
||||||
pkg-wildcards against arbitrary files and directories, useful mainly in
|
|
||||||
the build system itself.
|
|
||||||
See
|
|
||||||
.Xr pkg_info 1
|
|
||||||
for a description of the pattern.
|
|
||||||
.Pp
|
|
||||||
Example:
|
|
||||||
.Bd -literal
|
|
||||||
yui# cd /usr/pkgsrc/packages/i386ELF/All/
|
|
||||||
yui# ls unzip*
|
|
||||||
unzip-5.40.tgz unzip-5.41.tgz
|
|
||||||
yui# pkg_admin lsall 'unzip*'
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unzip-5.40.tgz
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz
|
|
||||||
yui# pkg_admin lsall 'unzip\*[Ge]5.40'
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unzip-5.40.tgz
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz
|
|
||||||
yui# pkg_admin lsall 'unzip\*[Ge]5.41'
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz
|
|
||||||
yui# pkg_admin lsbest 'unzip\*[Ge]5.40'
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unzip-5.41.tgz
|
|
||||||
yui# pkg_admin lsall /usr/pkgsrc/packages/i386ELF/All/'{mit,unproven}-pthread*'
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/mit-pthreads-1.60b6.tgz
|
|
||||||
/usr/pkgsrc/packages/i386ELF/All/unproven-pthreads-0.15.tgz
|
|
||||||
.Ed
|
|
||||||
.It Cm pmatch Ar pattern Ar pkg
|
|
||||||
Returns true if
|
|
||||||
.Ar pkg
|
|
||||||
matches
|
|
||||||
.Ar pattern ,
|
|
||||||
otherwise returns false.
|
|
||||||
.It Cm rebuild
|
|
||||||
Rebuild the package database mapping from scratch.
|
|
||||||
This option is only intended for recovery after system crashes
|
|
||||||
during package installation and removal.
|
|
||||||
.It Cm rebuild-tree
|
|
||||||
Rebuild the +REQUIRED_BY files from scratch by reresolving all dependencies.
|
|
||||||
.Pp
|
|
||||||
This option is intended to be used for fixing inconsistencies between
|
|
||||||
the records of depending and depended-on packages, such as can arise
|
|
||||||
by the use of
|
|
||||||
.Cm pkg_delete -f .
|
|
||||||
.It Cm set Ar variable=value pkg ...
|
|
||||||
Set variable with information about the installed package.
|
|
||||||
Use
|
|
||||||
.Cm unset
|
|
||||||
to remove a variable.
|
|
||||||
.Pp
|
|
||||||
Packages that are not installed directly by the user but pulled in as
|
|
||||||
dependencies are marked by setting
|
|
||||||
.Dq automatic=YES .
|
|
||||||
.It Cm gpg-sign-package pkg spkg
|
|
||||||
Sign the binary package
|
|
||||||
.Ar pkg
|
|
||||||
using GPG and write the result to
|
|
||||||
.Ar spkg .
|
|
||||||
.It Cm x509-sign-package pkg spkg key cert
|
|
||||||
Sign the binary package
|
|
||||||
.Ar pkg
|
|
||||||
using the key
|
|
||||||
.Ar key
|
|
||||||
and the certificate
|
|
||||||
.Ar cert ,
|
|
||||||
using
|
|
||||||
.Ar spkg
|
|
||||||
as output file.
|
|
||||||
.It Cm unset Ar variable pkg ...
|
|
||||||
Remove an installation variable.
|
|
||||||
.El
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
See
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
for options, that can also be specified using the environment.
|
|
||||||
.Sh FILES
|
|
||||||
.Bl -tag -width /var/db/pkg/pkgdb.byfile.db -compact
|
|
||||||
.It Pa /var/db/pkg/pkgdb.byfile.db
|
|
||||||
.It Pa /var/db/pkg/\*[Lt]pkg\*[Gt]/+CONTENTS
|
|
||||||
.El
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_add 1 ,
|
|
||||||
.Xr pkg_create 1 ,
|
|
||||||
.Xr pkg_delete 1 ,
|
|
||||||
.Xr pkg_info 1 ,
|
|
||||||
.Xr pkg_view 1 ,
|
|
||||||
.Xr pkg_install.conf 5 ,
|
|
||||||
.Xr pkgsrc 7
|
|
||||||
.Sh HISTORY
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command first appeared in
|
|
||||||
.Nx 1.4 .
|
|
||||||
.Sh AUTHORS
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command was written by Hubert Feyrer.
|
|
|
@ -1,4 +0,0 @@
|
||||||
SCRIPTS= bpm.sh
|
|
||||||
MAN= bpm.1
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,117 +0,0 @@
|
||||||
.\" $NetBSD: bpm.1,v 1.6 2009/02/08 23:12:10 wiz Exp $ */
|
|
||||||
.\"
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 2003 Alistair G. Crooks. All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" 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.
|
|
||||||
.\" 3. All advertising materials mentioning features or use of this software
|
|
||||||
.\" must display the following acknowledgement:
|
|
||||||
.\" This product includes software developed by Alistair G. Crooks.
|
|
||||||
.\" 4. The name of the author may not be used to endorse or promote
|
|
||||||
.\" products derived from this software without specific prior written
|
|
||||||
.\" permission.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
||||||
.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd August 3, 2007
|
|
||||||
.Dt BPM 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm bpm
|
|
||||||
.Nd menu-based binary package manager
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl hnVv
|
|
||||||
.Op Fl b Ar baseURL
|
|
||||||
.Op Fl m Ar machine
|
|
||||||
.Op Fl r Ar release
|
|
||||||
.Op Fl w Ar seconds
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command is used to locate and install binary packages from any
|
|
||||||
reachable URL.
|
|
||||||
.Pp
|
|
||||||
The following command-line options are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Fl b Ar baseURL
|
|
||||||
Specify a base URL from which to download binary packages.
|
|
||||||
The default URL is
|
|
||||||
.Pa ftp://ftp.NetBSD.org/pub/pkgsrc/packages .
|
|
||||||
.It Fl h
|
|
||||||
Print a help message and then exit.
|
|
||||||
.It Fl m Ar machine
|
|
||||||
Use
|
|
||||||
.Ar machine
|
|
||||||
as the machine architecture to be used, instead of that returned by
|
|
||||||
.Xr uname 1 .
|
|
||||||
.It Fl n
|
|
||||||
Don't actually execute the commands to add the package.
|
|
||||||
.It Fl r Ar release
|
|
||||||
Use
|
|
||||||
.Ar release
|
|
||||||
as the operating system release to be used, instead of that returned by
|
|
||||||
.Xr uname 1 .
|
|
||||||
.It Fl V
|
|
||||||
Print version number and exit.
|
|
||||||
.It Fl v
|
|
||||||
Turn on verbose output.
|
|
||||||
.It Fl w Ar seconds
|
|
||||||
The number of
|
|
||||||
.Ar seconds
|
|
||||||
to wait after displaying an error message and returning to
|
|
||||||
normal menu operations.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
.Nm
|
|
||||||
provides a menu-based binary package manager for
|
|
||||||
.Nx .
|
|
||||||
.Nm
|
|
||||||
first connects to the URL using
|
|
||||||
.Xr ftp 1 ,
|
|
||||||
and displays a list of categories for which binary packages exist.
|
|
||||||
If no categories are displayed, it could
|
|
||||||
be that the machine architecture or operating system release string
|
|
||||||
have been wrongly interpreted, and that it will be necessary to override
|
|
||||||
this values by means of the command line options.
|
|
||||||
Within a category, a list of packages will be displayed, and by selecting
|
|
||||||
one using the number assigned to it, the package will be downloaded
|
|
||||||
automatically, and installed, using the
|
|
||||||
.Xr pkg_add 1
|
|
||||||
utility.
|
|
||||||
It is also possible to change the category currently being examined,
|
|
||||||
and to quit from the utility, simply by selecting the appropriate choices
|
|
||||||
on the menu.
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
The environment variables which govern the behavior of
|
|
||||||
.Xr ftp 1
|
|
||||||
and
|
|
||||||
.Xr pkg_add 1
|
|
||||||
are valid for
|
|
||||||
.Nm .
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr ftp 1 ,
|
|
||||||
.Xr pkg_add 1 ,
|
|
||||||
.Xr uname 1
|
|
||||||
.Sh AUTHORS
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
utility was written by
|
|
||||||
.An Alistair Crooks Aq agc@NetBSD.org .
|
|
|
@ -1,241 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
#
|
|
||||||
# $NetBSD: bpm.sh.in,v 1.4 2007/08/02 23:30:20 wiz Exp $
|
|
||||||
#
|
|
||||||
# Copyright (c) 2003 Alistair G. Crooks. All rights reserved.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by Alistair G. Crooks.
|
|
||||||
# 4. The name of the author may not be used to endorse or promote
|
|
||||||
# products derived from this software without specific prior written
|
|
||||||
# permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
||||||
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
#
|
|
||||||
|
|
||||||
die()
|
|
||||||
{
|
|
||||||
echo >&2 "$@"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
check_prog()
|
|
||||||
{
|
|
||||||
_var="$1"; _name="$2"
|
|
||||||
|
|
||||||
eval _tmp=\"\$$_var\"
|
|
||||||
if [ "x$_tmp" != "x" ]; then
|
|
||||||
# Variable is already set (by the user, for example)
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
for _d in `echo $PATH | tr ':' ' '`; do
|
|
||||||
if [ -x "$_d/$_name" ]; then
|
|
||||||
# Program found
|
|
||||||
eval $_var=\""$_d/$_name"\"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
die "$_name not found in path."
|
|
||||||
}
|
|
||||||
|
|
||||||
check_prog awkprog awk
|
|
||||||
check_prog echoprog echo
|
|
||||||
check_prog ftpprog ftp
|
|
||||||
check_prog idprog id
|
|
||||||
check_prog moreprog more
|
|
||||||
check_prog pkg_addprog pkg_add
|
|
||||||
check_prog rmprog rm
|
|
||||||
check_prog sedprog sed
|
|
||||||
check_prog suprog su
|
|
||||||
check_prog unameprog uname
|
|
||||||
|
|
||||||
# print version and exit
|
|
||||||
version() {
|
|
||||||
$pkg_addprog -V
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
# temporary files
|
|
||||||
tmpcategories=/tmp/categories.$$
|
|
||||||
tmppackages=/tmp/packages.$$
|
|
||||||
|
|
||||||
# some base parameters
|
|
||||||
site=ftp.minix3.org
|
|
||||||
base=pub/minix/packages
|
|
||||||
release=`${unameprog} -r | ${sedprog} -e 's/_STABLE//'`
|
|
||||||
machine=`${unameprog} -p`
|
|
||||||
|
|
||||||
read_ftp_dir()
|
|
||||||
{
|
|
||||||
ftp_base=$1
|
|
||||||
ftp_dir=$2
|
|
||||||
|
|
||||||
${ftpprog} <<EOF
|
|
||||||
open $ftp_base
|
|
||||||
user
|
|
||||||
anonymous
|
|
||||||
cd $ftp_dir
|
|
||||||
ls
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
get_dir_entries()
|
|
||||||
{
|
|
||||||
start='150 Here comes the directory listing.'
|
|
||||||
end='226 Directory send OK.'
|
|
||||||
sed -n "/$start/,/$end/{ /$start/! {/$end/!p;}; }"
|
|
||||||
}
|
|
||||||
|
|
||||||
doit=""
|
|
||||||
sleepsecs=0
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case $1 in
|
|
||||||
-V) version ;;
|
|
||||||
-b) base=$2; shift ;;
|
|
||||||
-h) ${echoprog} "$0 [-b BaseURL] [-h] [-m machine] [-n] [-r release] [-v] [-w secs]"; exit 0;;
|
|
||||||
-m) machine=$2; shift ;;
|
|
||||||
-n) doit=":" ;;
|
|
||||||
-r) release=$2; shift ;;
|
|
||||||
-v) set -x ;;
|
|
||||||
-w) sleepsecs=$2; shift ;;
|
|
||||||
*) break ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
category=""
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
# if we don't have a packages file, then we need to choose a category
|
|
||||||
case "$category" in
|
|
||||||
"") # get possible categories
|
|
||||||
if [ ! -f $tmpcategories ]; then
|
|
||||||
${echoprog} "Downloading package categories from ftp://${site}/${base}..."
|
|
||||||
${echoprog} "** QUIT" > $tmpcategories
|
|
||||||
read_ftp_dir $site $base/${release}/${machine} | get_dir_entries >> $tmpcategories
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check for bad release numbering
|
|
||||||
# - it usually shows with 0 categories being displayed
|
|
||||||
${awkprog} 'END { if (NR == 1) { print "\n\n\n*** No categories found - is the OS release set properly? ***\n\n\n" } }' < $tmpcategories
|
|
||||||
|
|
||||||
# display possible categories
|
|
||||||
${awkprog} '{ print NR ". " $0 }' < $tmpcategories | ${moreprog}
|
|
||||||
|
|
||||||
# read a category number from the user
|
|
||||||
${echoprog} -n "Please type the category number: "
|
|
||||||
read choice
|
|
||||||
|
|
||||||
# validate user's choice
|
|
||||||
case "$choice" in
|
|
||||||
0|1) ${rmprog} -f $tmpcategories $tmppackages; exit 0 ;;
|
|
||||||
[2-9]|[0-9]*) category=`${awkprog} 'NR == '$choice' { print }' < $tmpcategories` ;;
|
|
||||||
*) category="" ;;
|
|
||||||
esac
|
|
||||||
case "$category" in
|
|
||||||
"") ${echoprog} "No such category \"$choice\""
|
|
||||||
sleep $sleepsecs
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# get possible packages
|
|
||||||
${echoprog} ""
|
|
||||||
${echoprog} "Downloading package names from ftp://${site}/${base}/${category}..."
|
|
||||||
${echoprog} "** QUIT" > $tmppackages
|
|
||||||
${echoprog} "** Change category" >> $tmppackages
|
|
||||||
read_ftp_dir $site $base/${release}/${machine}/${category} | get_dir_entries >> $tmppackages
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# display possible packages
|
|
||||||
${awkprog} '{ print NR ". " $0 }' < $tmppackages | ${moreprog}
|
|
||||||
|
|
||||||
# read a package number from the user
|
|
||||||
${echoprog} -n "Please type the package number: "
|
|
||||||
read choice
|
|
||||||
|
|
||||||
# validate user's choice
|
|
||||||
case "$choice" in
|
|
||||||
1) ${rmprog} -f $tmppackages $tmpcategories; exit 0 ;;
|
|
||||||
2) category=""; continue ;; # no package to install - choose new category
|
|
||||||
[3-9]|[0-9]*) package=`${awkprog} 'NR == '$choice' { print }' < $tmppackages` ;;
|
|
||||||
*) package="" ;;
|
|
||||||
esac
|
|
||||||
case "$package" in
|
|
||||||
"") ${echoprog} "No such package \"$choice\""
|
|
||||||
sleep $sleepsecs
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# check it's not already installed
|
|
||||||
pkgbase=`${echoprog} ${package} | ${sedprog} -e 's|-[0-9].*||'`
|
|
||||||
installed=`pkg_info -e $pkgbase`
|
|
||||||
case "$installed" in
|
|
||||||
"") ;;
|
|
||||||
*) ${echoprog} "$package selected, but $installed already installed"
|
|
||||||
sleep $sleepsecs
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Tell people what we're doing
|
|
||||||
${echoprog} ""
|
|
||||||
${echoprog} "Adding package ftp://${site}/${base}/${release}/${machine}/${category}/${package}"
|
|
||||||
|
|
||||||
cmd="${pkg_addprog} ftp://${site}/${base}/${release}/${machine}/All/${package}"
|
|
||||||
|
|
||||||
# check if we need to become root for this
|
|
||||||
if [ `${idprog} -u` != 0 ]; then
|
|
||||||
${echoprog} "Becoming root@`/bin/hostname` to add a binary package"
|
|
||||||
${echoprog} -n "`${echoprog} ${suprog} | $awkprog '{ print $1 }'` "
|
|
||||||
$doit ${suprog} root -c "$cmd"
|
|
||||||
success=$?
|
|
||||||
else
|
|
||||||
$doit $cmd
|
|
||||||
success=$?
|
|
||||||
fi
|
|
||||||
|
|
||||||
# give feedback after adding the package
|
|
||||||
case $success in
|
|
||||||
0) ${echoprog} "$package successfully installed" ;;
|
|
||||||
*) ${echoprog} "Problems when installing $package - please try again" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
${echoprog} ""
|
|
||||||
${echoprog} -n "[Q]uit, [C]hange category, [I]nstall another package: "
|
|
||||||
read choice
|
|
||||||
|
|
||||||
case "$choice" in
|
|
||||||
[Qq]) break ;;
|
|
||||||
[Cc]) category="" ;;
|
|
||||||
[Ii]) ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
${rmprog} -f $tmpcategories $tmppackages
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,197 +0,0 @@
|
||||||
/* lib/config.h. Generated from config.h.in by configure. */
|
|
||||||
/* lib/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <assert.h> header file. */
|
|
||||||
#define HAVE_ASSERT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ctype.h> header file. */
|
|
||||||
#define HAVE_CTYPE_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dirent.h> header file. */
|
|
||||||
#define HAVE_DIRENT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <errno.h> header file. */
|
|
||||||
#define HAVE_ERRNO_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <err.h> header file. */
|
|
||||||
#define HAVE_ERR_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnctl.h> header file. */
|
|
||||||
#define HAVE_FCNTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
|
||||||
#define HAVE_FNMATCH_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <glob.h> header file. */
|
|
||||||
#define HAVE_GLOB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <grp.h> header file. */
|
|
||||||
#define HAVE_GRP_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#define HAVE_INTTYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `db' library (-ldb). */
|
|
||||||
/* #undef HAVE_LIBDB */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <limits.h> header file. */
|
|
||||||
#define HAVE_LIMITS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
/* #undef HAVE_MEMORY_H */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <pwd.h> header file. */
|
|
||||||
#define HAVE_PWD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
|
||||||
#define HAVE_SIGNAL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
|
||||||
#define HAVE_STDARG_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#define HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdio.h> header file. */
|
|
||||||
#define HAVE_STDIO_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#define HAVE_STDLIB_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#define HAVE_STRINGS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#define HAVE_STRING_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/cdefs.h> header file. */
|
|
||||||
#define HAVE_SYS_CDEFS_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
|
||||||
#define HAVE_SYS_FILE_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
|
||||||
#define HAVE_SYS_IOCTL_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
|
||||||
#define HAVE_SYS_PARAM_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
|
||||||
#define HAVE_SYS_QUEUE_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#define HAVE_SYS_STAT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#define HAVE_SYS_TIME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
|
||||||
#define HAVE_SYS_UTSNAME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
|
||||||
#define HAVE_SYS_WAIT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <time.h> header file. */
|
|
||||||
#define HAVE_TIME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#define HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vfork' function. */
|
|
||||||
/* #undef HAVE_VFORK */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <vis.h> header file. */
|
|
||||||
/* #undef HAVE_VIS_H */
|
|
||||||
|
|
||||||
/* Define to 1 if the `z' modifider for printf is missing. */
|
|
||||||
/* #undef MISSING_SIZE_T_SUPPORT */
|
|
||||||
|
|
||||||
/* Defined when PRIu64 is missing or broken */
|
|
||||||
#define NEED_PRI_MACRO 1
|
|
||||||
|
|
||||||
/* Defined when to retain only the numeric OS version */
|
|
||||||
/* #undef NUMERIC_VERSION_ONLY */
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#define PACKAGE_BUGREPORT "joerg@NetBSD.org"
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#define PACKAGE_NAME "pkg_install"
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#define PACKAGE_STRING "pkg_install 20090911"
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#define PACKAGE_TARNAME "pkg_install"
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#define PACKAGE_URL ""
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#define PACKAGE_VERSION "20090911"
|
|
||||||
|
|
||||||
/* The size of `int', as computed by sizeof. */
|
|
||||||
#define SIZEOF_INT 4
|
|
||||||
|
|
||||||
/* The size of `long', as computed by sizeof. */
|
|
||||||
#define SIZEOF_LONG 4
|
|
||||||
|
|
||||||
/* The size of `long long', as computed by sizeof. */
|
|
||||||
#define SIZEOF_LONG_LONG 0
|
|
||||||
|
|
||||||
/* The size of `size_t', as computed by sizeof. */
|
|
||||||
#define SIZEOF_SIZE_T 4
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#define STDC_HEADERS 1
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
/* #undef _UINT32_T */
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
/* #undef _UINT64_T */
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
/* #undef _UINT8_T */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint16_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint32_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 64 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint64_t */
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
/* #undef uint8_t */
|
|
||||||
|
|
||||||
#if !HAVE_VFORK
|
|
||||||
# define vfork fork
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MISSING_SIZE_T_SUPPORT
|
|
||||||
# define PRIzu "zu"
|
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_INT
|
|
||||||
# define PRIzu "u"
|
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_LONG
|
|
||||||
# define PRIzu "lu"
|
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
|
|
||||||
# define PRIzu "llu"
|
|
||||||
#else
|
|
||||||
# error "Unknown size_t size"
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
PROG= pkg_create
|
|
||||||
|
|
||||||
SRCS= main.c perform.c pl.c util.c build.c
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,426 +0,0 @@
|
||||||
/* $NetBSD: build.c,v 1.15 2010/04/20 00:39:13 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: build.c,v 1.15 2010/04/20 00:39:13 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code was developed as part of Google's Summer of Code 2007 program.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* This is the main body of the create module.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#include "create.h"
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_GRP_H
|
|
||||||
#include <grp.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_PWD_H
|
|
||||||
#include <pwd.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <archive.h>
|
|
||||||
#include <archive_entry.h>
|
|
||||||
|
|
||||||
static struct memory_file *contents_file;
|
|
||||||
static struct memory_file *comment_file;
|
|
||||||
static struct memory_file *desc_file;
|
|
||||||
static struct memory_file *install_file;
|
|
||||||
static struct memory_file *deinstall_file;
|
|
||||||
static struct memory_file *display_file;
|
|
||||||
static struct memory_file *build_version_file;
|
|
||||||
static struct memory_file *build_info_file;
|
|
||||||
static struct memory_file *size_pkg_file;
|
|
||||||
static struct memory_file *size_all_file;
|
|
||||||
static struct memory_file *preserve_file;
|
|
||||||
static struct memory_file *views_file;
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_meta_file(struct memory_file *file, struct archive *archive)
|
|
||||||
{
|
|
||||||
struct archive_entry *entry;
|
|
||||||
|
|
||||||
entry = archive_entry_new();
|
|
||||||
archive_entry_set_pathname(entry, file->name);
|
|
||||||
archive_entry_copy_stat(entry, &file->st);
|
|
||||||
|
|
||||||
archive_entry_set_uname(entry, file->owner);
|
|
||||||
archive_entry_set_gname(entry, file->group);
|
|
||||||
|
|
||||||
if (archive_write_header(archive, entry))
|
|
||||||
errx(2, "cannot write to archive: %s", archive_error_string(archive));
|
|
||||||
|
|
||||||
archive_write_data(archive, file->data, file->len);
|
|
||||||
|
|
||||||
archive_entry_free(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_entry(struct archive *archive, struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
char buf[16384];
|
|
||||||
const char *name;
|
|
||||||
int fd;
|
|
||||||
off_t len;
|
|
||||||
ssize_t buf_len;
|
|
||||||
|
|
||||||
if (archive_entry_pathname(entry) == NULL) {
|
|
||||||
warnx("entry with NULL path");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (archive_write_header(archive, entry)) {
|
|
||||||
errx(2, "cannot write %s to archive: %s",
|
|
||||||
archive_entry_pathname(entry),
|
|
||||||
archive_error_string(archive));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only regular files can have data. */
|
|
||||||
if (archive_entry_filetype(entry) != AE_IFREG ||
|
|
||||||
archive_entry_size(entry) == 0) {
|
|
||||||
archive_entry_free(entry);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = archive_entry_pathname(entry);
|
|
||||||
|
|
||||||
if ((fd = open(name, O_RDONLY)) == -1)
|
|
||||||
err(2, "cannot open data file %s", name);
|
|
||||||
|
|
||||||
len = archive_entry_size(entry);
|
|
||||||
|
|
||||||
while (len > 0) {
|
|
||||||
buf_len = (len > (off_t)sizeof(buf)) ? (ssize_t)sizeof(buf) : (ssize_t)len;
|
|
||||||
|
|
||||||
if ((buf_len = read(fd, buf, buf_len)) == 0)
|
|
||||||
break;
|
|
||||||
else if (buf_len < 0)
|
|
||||||
err(2, "cannot read from %s", name);
|
|
||||||
|
|
||||||
archive_write_data(archive, buf, (size_t)buf_len);
|
|
||||||
len -= buf_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
archive_entry_free(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_normal_file(const char *name, struct archive *archive,
|
|
||||||
struct archive_entry_linkresolver *resolver,
|
|
||||||
const char *owner, const char *group)
|
|
||||||
{
|
|
||||||
char buf[16384];
|
|
||||||
ssize_t buf_len;
|
|
||||||
struct archive_entry *entry, *sparse_entry;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (lstat(name, &st) == -1)
|
|
||||||
err(2, "lstat failed for file %s", name);
|
|
||||||
|
|
||||||
entry = archive_entry_new();
|
|
||||||
archive_entry_set_pathname(entry, name);
|
|
||||||
archive_entry_copy_stat(entry, &st);
|
|
||||||
|
|
||||||
if (owner != NULL) {
|
|
||||||
uid_t uid;
|
|
||||||
|
|
||||||
archive_entry_set_uname(entry, owner);
|
|
||||||
if (uid_from_user(owner, &uid) == -1)
|
|
||||||
errx(2, "user %s unknown", owner);
|
|
||||||
archive_entry_set_uid(entry, uid);
|
|
||||||
} else {
|
|
||||||
archive_entry_set_uname(entry, user_from_uid(st.st_uid, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (group != NULL) {
|
|
||||||
gid_t gid;
|
|
||||||
|
|
||||||
archive_entry_set_gname(entry, group);
|
|
||||||
if (gid_from_group(group, &gid) == -1)
|
|
||||||
errx(2, "group %s unknown", group);
|
|
||||||
archive_entry_set_gid(entry, gid);
|
|
||||||
} else {
|
|
||||||
archive_entry_set_gname(entry, group_from_gid(st.st_gid, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((st.st_mode & S_IFMT) == S_IFLNK) {
|
|
||||||
buf_len = readlink(name, buf, sizeof buf);
|
|
||||||
if (buf_len < 0)
|
|
||||||
err(2, "cannot read symlink %s", name);
|
|
||||||
buf[buf_len] = '\0';
|
|
||||||
archive_entry_set_symlink(entry, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
archive_entry_linkify(resolver, &entry, &sparse_entry);
|
|
||||||
|
|
||||||
if (entry != NULL)
|
|
||||||
write_entry(archive, entry);
|
|
||||||
if (sparse_entry != NULL)
|
|
||||||
write_entry(archive, sparse_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
make_dist(const char *pkg, const char *suffix, const package_t *plist)
|
|
||||||
{
|
|
||||||
char *archive_name;
|
|
||||||
const char *owner, *group;
|
|
||||||
const plist_t *p;
|
|
||||||
struct archive *archive;
|
|
||||||
struct archive_entry *entry, *sparse_entry;
|
|
||||||
struct archive_entry_linkresolver *resolver;
|
|
||||||
char *initial_cwd;
|
|
||||||
|
|
||||||
archive = archive_write_new();
|
|
||||||
archive_write_set_format_pax_restricted(archive);
|
|
||||||
if ((resolver = archive_entry_linkresolver_new()) == NULL)
|
|
||||||
errx(2, "cannot create link resolver");
|
|
||||||
archive_entry_linkresolver_set_strategy(resolver,
|
|
||||||
archive_format(archive));
|
|
||||||
|
|
||||||
if (CompressionType == NULL) {
|
|
||||||
if (strcmp(suffix, "tbz") == 0 ||
|
|
||||||
strcmp(suffix, "tar.bz2") == 0)
|
|
||||||
CompressionType = "bzip2";
|
|
||||||
else if (strcmp(suffix, "tgz") == 0 ||
|
|
||||||
strcmp(suffix, "tar.gz") == 0)
|
|
||||||
CompressionType = "gzip";
|
|
||||||
else
|
|
||||||
CompressionType = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(CompressionType, "bzip2") == 0)
|
|
||||||
archive_write_set_compression_bzip2(archive);
|
|
||||||
else if (strcmp(CompressionType, "gzip") == 0)
|
|
||||||
archive_write_set_compression_gzip(archive);
|
|
||||||
else if (strcmp(CompressionType, "xz") == 0)
|
|
||||||
archive_write_set_compression_xz(archive);
|
|
||||||
else if (strcmp(CompressionType, "none") == 0)
|
|
||||||
archive_write_set_compression_none(archive);
|
|
||||||
else
|
|
||||||
errx(1, "Unspported compression type for -F: %s",
|
|
||||||
CompressionType);
|
|
||||||
|
|
||||||
archive_name = xasprintf("%s.%s", pkg, suffix);
|
|
||||||
|
|
||||||
if (archive_write_open_file(archive, archive_name))
|
|
||||||
errx(2, "cannot create archive: %s", archive_error_string(archive));
|
|
||||||
|
|
||||||
free(archive_name);
|
|
||||||
|
|
||||||
owner = DefaultOwner;
|
|
||||||
group = DefaultGroup;
|
|
||||||
|
|
||||||
write_meta_file(contents_file, archive);
|
|
||||||
write_meta_file(comment_file, archive);
|
|
||||||
write_meta_file(desc_file, archive);
|
|
||||||
|
|
||||||
if (Install)
|
|
||||||
write_meta_file(install_file, archive);
|
|
||||||
if (DeInstall)
|
|
||||||
write_meta_file(deinstall_file, archive);
|
|
||||||
if (Display)
|
|
||||||
write_meta_file(display_file, archive);
|
|
||||||
if (BuildVersion)
|
|
||||||
write_meta_file(build_version_file, archive);
|
|
||||||
if (BuildInfo)
|
|
||||||
write_meta_file(build_info_file, archive);
|
|
||||||
if (SizePkg)
|
|
||||||
write_meta_file(size_pkg_file, archive);
|
|
||||||
if (SizeAll)
|
|
||||||
write_meta_file(size_all_file, archive);
|
|
||||||
if (Preserve)
|
|
||||||
write_meta_file(preserve_file, archive);
|
|
||||||
if (create_views)
|
|
||||||
write_meta_file(views_file, archive);
|
|
||||||
|
|
||||||
initial_cwd = getcwd(NULL, 0);
|
|
||||||
|
|
||||||
for (p = plist->head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_FILE) {
|
|
||||||
write_normal_file(p->name, archive, resolver, owner, group);
|
|
||||||
} else if (p->type == PLIST_CWD) {
|
|
||||||
chdir(p->name);
|
|
||||||
} else if (p->type == PLIST_IGNORE) {
|
|
||||||
p = p->next;
|
|
||||||
} else if (p->type == PLIST_CHOWN) {
|
|
||||||
if (p->name != NULL)
|
|
||||||
owner = p->name;
|
|
||||||
else
|
|
||||||
owner = DefaultOwner;
|
|
||||||
} else if (p->type == PLIST_CHGRP) {
|
|
||||||
if (p->name != NULL)
|
|
||||||
group = p->name;
|
|
||||||
else
|
|
||||||
group = DefaultGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = NULL;
|
|
||||||
archive_entry_linkify(resolver, &entry, &sparse_entry);
|
|
||||||
while (entry != NULL) {
|
|
||||||
write_entry(archive, entry);
|
|
||||||
entry = NULL;
|
|
||||||
archive_entry_linkify(resolver, &entry, &sparse_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
archive_entry_linkresolver_free(resolver);
|
|
||||||
|
|
||||||
if (archive_write_close(archive))
|
|
||||||
errx(2, "cannot finish archive: %s", archive_error_string(archive));
|
|
||||||
archive_write_finish(archive);
|
|
||||||
|
|
||||||
free(initial_cwd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct memory_file *
|
|
||||||
load_and_add(package_t *plist, const char *input_name,
|
|
||||||
const char *target_name, mode_t perm)
|
|
||||||
{
|
|
||||||
struct memory_file *file;
|
|
||||||
|
|
||||||
file = load_memory_file(input_name, target_name, DefaultOwner,
|
|
||||||
DefaultGroup, perm);
|
|
||||||
add_plist(plist, PLIST_IGNORE, NULL);
|
|
||||||
add_plist(plist, PLIST_FILE, target_name);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct memory_file *
|
|
||||||
make_and_add(package_t *plist, const char *target_name,
|
|
||||||
char *content, mode_t perm)
|
|
||||||
{
|
|
||||||
struct memory_file *file;
|
|
||||||
|
|
||||||
file = make_memory_file(target_name, content, strlen(content),
|
|
||||||
DefaultOwner, DefaultGroup, perm);
|
|
||||||
add_plist(plist, PLIST_IGNORE, NULL);
|
|
||||||
add_plist(plist, PLIST_FILE, target_name);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pkg_build(const char *pkg, const char *full_pkg, const char *suffix,
|
|
||||||
package_t *plist)
|
|
||||||
{
|
|
||||||
char *plist_buf;
|
|
||||||
size_t plist_len;
|
|
||||||
|
|
||||||
/* Now put the release specific items in */
|
|
||||||
add_plist(plist, PLIST_CWD, ".");
|
|
||||||
comment_file = make_and_add(plist, COMMENT_FNAME, Comment, 0444);
|
|
||||||
desc_file = make_and_add(plist, DESC_FNAME, Desc, 0444);
|
|
||||||
|
|
||||||
if (Install) {
|
|
||||||
install_file = load_and_add(plist, Install, INSTALL_FNAME,
|
|
||||||
0555);
|
|
||||||
}
|
|
||||||
if (DeInstall) {
|
|
||||||
deinstall_file = load_and_add(plist, DeInstall,
|
|
||||||
DEINSTALL_FNAME, 0555);
|
|
||||||
}
|
|
||||||
if (Display) {
|
|
||||||
display_file = load_and_add(plist, Display,
|
|
||||||
DISPLAY_FNAME, 0444);
|
|
||||||
add_plist(plist, PLIST_DISPLAY, DISPLAY_FNAME);
|
|
||||||
}
|
|
||||||
if (BuildVersion) {
|
|
||||||
build_version_file = load_and_add(plist, BuildVersion,
|
|
||||||
BUILD_VERSION_FNAME, 0444);
|
|
||||||
}
|
|
||||||
if (BuildInfo) {
|
|
||||||
build_info_file = load_and_add(plist, BuildInfo,
|
|
||||||
BUILD_INFO_FNAME, 0444);
|
|
||||||
}
|
|
||||||
if (SizePkg) {
|
|
||||||
size_pkg_file = load_and_add(plist, SizePkg,
|
|
||||||
SIZE_PKG_FNAME, 0444);
|
|
||||||
}
|
|
||||||
if (SizeAll) {
|
|
||||||
size_all_file = load_and_add(plist, SizeAll,
|
|
||||||
SIZE_ALL_FNAME, 0444);
|
|
||||||
}
|
|
||||||
if (Preserve) {
|
|
||||||
preserve_file = load_and_add(plist, Preserve,
|
|
||||||
PRESERVE_FNAME, 0444);
|
|
||||||
}
|
|
||||||
if (create_views)
|
|
||||||
views_file = make_and_add(plist, VIEWS_FNAME, xstrdup(""), 0444);
|
|
||||||
|
|
||||||
/* Finally, write out the packing list */
|
|
||||||
stringify_plist(plist, &plist_buf, &plist_len, realprefix);
|
|
||||||
contents_file = make_memory_file(CONTENTS_FNAME, plist_buf, plist_len,
|
|
||||||
DefaultOwner, DefaultGroup, 0644);
|
|
||||||
|
|
||||||
/* And stick it into a tar ball */
|
|
||||||
make_dist(pkg, suffix, plist);
|
|
||||||
|
|
||||||
return TRUE; /* Success */
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/* $NetBSD: create.h,v 1.14 2009/11/05 16:22:32 joerg Exp $ */
|
|
||||||
|
|
||||||
/* from FreeBSD Id: create.h,v 1.13 1997/10/08 07:46:19 charnier Exp */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Include and define various things wanted by the create command.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INST_CREATE_H_INCLUDE
|
|
||||||
#define _INST_CREATE_H_INCLUDE
|
|
||||||
|
|
||||||
struct memory_file {
|
|
||||||
struct stat st;
|
|
||||||
const char *name;
|
|
||||||
const char *owner;
|
|
||||||
const char *group;
|
|
||||||
mode_t mode;
|
|
||||||
|
|
||||||
char *data;
|
|
||||||
size_t len;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern char *Prefix;
|
|
||||||
extern char *Comment;
|
|
||||||
extern char *Desc;
|
|
||||||
extern char *Display;
|
|
||||||
extern char *Install;
|
|
||||||
extern char *DeInstall;
|
|
||||||
extern char *Contents;
|
|
||||||
extern char *Pkgdeps;
|
|
||||||
extern char *BuildPkgdeps;
|
|
||||||
extern char *Pkgcfl;
|
|
||||||
extern char *BuildVersion;
|
|
||||||
extern char *BuildInfo;
|
|
||||||
extern char *SizePkg;
|
|
||||||
extern char *SizeAll;
|
|
||||||
extern char *Preserve;
|
|
||||||
extern char *realprefix;
|
|
||||||
extern char *DefaultOwner;
|
|
||||||
extern char *DefaultGroup;
|
|
||||||
extern const char *CompressionType;
|
|
||||||
extern int PlistOnly;
|
|
||||||
extern int RelativeLinks;
|
|
||||||
extern int update_pkgdb;
|
|
||||||
extern int create_views;
|
|
||||||
|
|
||||||
void check_list(package_t *, const char *);
|
|
||||||
void copy_plist(char *, package_t *);
|
|
||||||
|
|
||||||
struct memory_file
|
|
||||||
*load_memory_file(const char *, const char *,
|
|
||||||
const char *, const char *, mode_t);
|
|
||||||
struct memory_file
|
|
||||||
*make_memory_file(const char *, void *, size_t,
|
|
||||||
const char *, const char *, mode_t);
|
|
||||||
void free_memory_file(struct memory_file *);
|
|
||||||
|
|
||||||
int pkg_perform(const char *);
|
|
||||||
int pkg_build(const char *, const char *, const char *, package_t *plist);
|
|
||||||
|
|
||||||
#endif /* _INST_CREATE_H_INCLUDE */
|
|
|
@ -1,221 +0,0 @@
|
||||||
/* $NetBSD: main.c,v 1.19 2010/01/22 13:30:41 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: main.c,v 1.19 2010/01/22 13:30:41 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FreeBSD install - a package for the installation and maintainance
|
|
||||||
* of non-core utilities.
|
|
||||||
*
|
|
||||||
* Jordan K. Hubbard
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* This is the create module.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include "lib.h"
|
|
||||||
#include "create.h"
|
|
||||||
|
|
||||||
static const char Options[] = "B:C:D:EF:I:K:L:OP:S:T:UVb:c:d:f:g:i:k:ln:p:r:s:u:v";
|
|
||||||
|
|
||||||
char *Prefix = NULL;
|
|
||||||
char *Comment = NULL;
|
|
||||||
char *Desc = NULL;
|
|
||||||
char *Display = NULL;
|
|
||||||
char *Install = NULL;
|
|
||||||
char *DeInstall = NULL;
|
|
||||||
char *Contents = NULL;
|
|
||||||
char *Pkgdeps = NULL;
|
|
||||||
char *BuildPkgdeps = NULL;
|
|
||||||
char *Pkgcfl = NULL;
|
|
||||||
char *BuildVersion = NULL;
|
|
||||||
char *BuildInfo = NULL;
|
|
||||||
char *SizePkg = NULL;
|
|
||||||
char *SizeAll = NULL;
|
|
||||||
char *Preserve = NULL;
|
|
||||||
char *DefaultOwner = NULL;
|
|
||||||
char *DefaultGroup = NULL;
|
|
||||||
char *realprefix = NULL;
|
|
||||||
const char *CompressionType = NULL;
|
|
||||||
int update_pkgdb = 1;
|
|
||||||
int create_views = 0;
|
|
||||||
int PlistOnly = 0;
|
|
||||||
int RelativeLinks = 0;
|
|
||||||
Boolean File2Pkg = FALSE;
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"usage: pkg_create [-ElOUVv] [-B build-info-file] [-b build-version-file]\n"
|
|
||||||
" [-C cpkgs] [-D displayfile] [-F compression] \n"
|
|
||||||
" [-I realprefix] [-i iscript]\n"
|
|
||||||
" [-K pkg_dbdir] [-k dscript]\n"
|
|
||||||
" [-n preserve-file] [-P dpkgs] [-p prefix] [-r rscript]\n"
|
|
||||||
" [-S size-all-file] [-s size-pkg-file]\n"
|
|
||||||
" [-T buildpkgs] [-u owner] [-g group]\n"
|
|
||||||
" -c comment -d description -f packlist\n"
|
|
||||||
" pkg-name\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int ch;
|
|
||||||
|
|
||||||
setprogname(argv[0]);
|
|
||||||
while ((ch = getopt(argc, argv, Options)) != -1)
|
|
||||||
switch (ch) {
|
|
||||||
case 'v':
|
|
||||||
Verbose = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'E':
|
|
||||||
create_views = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
CompressionType = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
realprefix = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'O':
|
|
||||||
PlistOnly = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'U':
|
|
||||||
update_pkgdb = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
Prefix = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
SizePkg = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
SizeAll = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
Contents = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
Comment = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
Desc = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'g':
|
|
||||||
DefaultGroup = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'i':
|
|
||||||
Install = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'K':
|
|
||||||
pkgdb_set_dir(optarg, 3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'k':
|
|
||||||
DeInstall = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
RelativeLinks = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'L':
|
|
||||||
warnx("Obsolete -L option ignored");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u':
|
|
||||||
DefaultOwner = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
Display = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
Preserve = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'P':
|
|
||||||
Pkgdeps = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'T':
|
|
||||||
BuildPkgdeps = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
Pkgcfl = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
BuildVersion = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
BuildInfo = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'V':
|
|
||||||
show_version();
|
|
||||||
/* NOTREACHED */
|
|
||||||
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
pkg_install_config();
|
|
||||||
|
|
||||||
if (argc == 0) {
|
|
||||||
warnx("missing package name");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
if (argc != 1) {
|
|
||||||
warnx("only one package name allowed");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pkg_perform(*argv))
|
|
||||||
return 0;
|
|
||||||
if (Verbose) {
|
|
||||||
if (PlistOnly)
|
|
||||||
warnx("package registration failed");
|
|
||||||
else
|
|
||||||
warnx("package creation failed");
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -1,253 +0,0 @@
|
||||||
/* $NetBSD: perform.c,v 1.26 2009/11/05 16:22:32 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: perform.c,v 1.26 2009/11/05 16:22:32 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* This is the main body of the create module.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#include "create.h"
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
sanity_check(void)
|
|
||||||
{
|
|
||||||
if (!Comment)
|
|
||||||
errx(2, "required package comment string is missing (-c comment)");
|
|
||||||
if (!Desc)
|
|
||||||
errx(2, "required package description string is missing (-d desc)");
|
|
||||||
if (!Contents)
|
|
||||||
errx(2, "required package contents list is missing (-f [-]file)");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
register_depends(package_t *plist, char *deps, int build_only)
|
|
||||||
{
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
if (Verbose && !PlistOnly) {
|
|
||||||
if (build_only)
|
|
||||||
printf("Registering build depends:");
|
|
||||||
else
|
|
||||||
printf("Registering depends:");
|
|
||||||
}
|
|
||||||
while (deps) {
|
|
||||||
cp = strsep(&deps, " \t\n");
|
|
||||||
if (*cp) {
|
|
||||||
char *best_installed;
|
|
||||||
best_installed = find_best_matching_installed_pkg(cp);
|
|
||||||
if (best_installed != NULL) {
|
|
||||||
add_plist(plist, PLIST_BLDDEP, best_installed);
|
|
||||||
if (Verbose && !PlistOnly && build_only)
|
|
||||||
printf(" %s", cp);
|
|
||||||
} else
|
|
||||||
warnx("No matching package installed for %s", cp);
|
|
||||||
free(best_installed);
|
|
||||||
if (!build_only) {
|
|
||||||
add_plist(plist, PLIST_PKGDEP, cp);
|
|
||||||
if (Verbose && !PlistOnly)
|
|
||||||
printf(" %s", cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Verbose && !PlistOnly)
|
|
||||||
printf(".\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Expect "fname" to point at a file, and read it into
|
|
||||||
* the buffer returned.
|
|
||||||
*/
|
|
||||||
static char *
|
|
||||||
fileGetContents(char *fname)
|
|
||||||
{
|
|
||||||
char *contents;
|
|
||||||
struct stat sb;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (stat(fname, &sb) == FAIL) {
|
|
||||||
errx(2, "can't stat '%s'", fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
contents = xmalloc((size_t) (sb.st_size) + 1);
|
|
||||||
fd = open(fname, O_RDONLY, 0);
|
|
||||||
if (fd == FAIL) {
|
|
||||||
errx(2, "unable to open '%s' for reading", fname);
|
|
||||||
}
|
|
||||||
if (read(fd, contents, (size_t) sb.st_size) != (ssize_t) sb.st_size) {
|
|
||||||
#ifndef __minix
|
|
||||||
errx(2, "short read on '%s' - did not get %lld bytes",
|
|
||||||
fname, (long long) sb.st_size);
|
|
||||||
#else
|
|
||||||
errx(2, "short read on '%s' - did not get %ld bytes",
|
|
||||||
fname, (long) sb.st_size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
contents[(size_t) sb.st_size] = '\0';
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get a string parameter as a file spec or as a "contents follow -" spec
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
get_dash_string(char **s)
|
|
||||||
{
|
|
||||||
if (**s == '-')
|
|
||||||
*s = xstrdup(*s + 1);
|
|
||||||
else
|
|
||||||
*s = fileGetContents(*s);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pkg_perform(const char *pkg)
|
|
||||||
{
|
|
||||||
char *cp;
|
|
||||||
FILE *pkg_in;
|
|
||||||
package_t plist;
|
|
||||||
const char *full_pkg, *suffix;
|
|
||||||
char *allocated_pkg;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
/* Break the package name into base and desired suffix (if any) */
|
|
||||||
if ((cp = strrchr(pkg, '.')) != NULL) {
|
|
||||||
allocated_pkg = xmalloc(cp - pkg + 1);
|
|
||||||
memcpy(allocated_pkg, pkg, cp - pkg);
|
|
||||||
allocated_pkg[cp - pkg] = '\0';
|
|
||||||
suffix = cp + 1;
|
|
||||||
full_pkg = pkg;
|
|
||||||
pkg = allocated_pkg;
|
|
||||||
} else {
|
|
||||||
allocated_pkg = NULL;
|
|
||||||
full_pkg = pkg;
|
|
||||||
suffix = "tgz";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Preliminary setup */
|
|
||||||
sanity_check();
|
|
||||||
if (Verbose && !PlistOnly)
|
|
||||||
printf("Creating package %s\n", pkg);
|
|
||||||
get_dash_string(&Comment);
|
|
||||||
get_dash_string(&Desc);
|
|
||||||
if (IS_STDIN(Contents))
|
|
||||||
pkg_in = stdin;
|
|
||||||
else {
|
|
||||||
pkg_in = fopen(Contents, "r");
|
|
||||||
if (!pkg_in)
|
|
||||||
errx(2, "unable to open contents file '%s' for input", Contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
plist.head = plist.tail = NULL;
|
|
||||||
|
|
||||||
/* Stick the dependencies, if any, at the top */
|
|
||||||
if (Pkgdeps)
|
|
||||||
register_depends(&plist, Pkgdeps, 0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Put the build dependencies after the dependencies.
|
|
||||||
* This works due to the evaluation order in pkg_add.
|
|
||||||
*/
|
|
||||||
if (BuildPkgdeps)
|
|
||||||
register_depends(&plist, BuildPkgdeps, 1);
|
|
||||||
|
|
||||||
/* Put the conflicts directly after the dependencies, if any */
|
|
||||||
if (Pkgcfl) {
|
|
||||||
if (Verbose && !PlistOnly)
|
|
||||||
printf("Registering conflicts:");
|
|
||||||
while (Pkgcfl) {
|
|
||||||
cp = strsep(&Pkgcfl, " \t\n");
|
|
||||||
if (*cp) {
|
|
||||||
add_plist(&plist, PLIST_PKGCFL, cp);
|
|
||||||
if (Verbose && !PlistOnly)
|
|
||||||
printf(" %s", cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Verbose && !PlistOnly)
|
|
||||||
printf(".\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Slurp in the packing list */
|
|
||||||
append_plist(&plist, pkg_in);
|
|
||||||
|
|
||||||
if (pkg_in != stdin)
|
|
||||||
fclose(pkg_in);
|
|
||||||
|
|
||||||
/* Prefix should override the packing list */
|
|
||||||
if (Prefix) {
|
|
||||||
delete_plist(&plist, FALSE, PLIST_CWD, NULL);
|
|
||||||
add_plist_top(&plist, PLIST_CWD, Prefix);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Run down the list and see if we've named it, if not stick in a name
|
|
||||||
* at the top.
|
|
||||||
*/
|
|
||||||
if (find_plist(&plist, PLIST_NAME) == NULL) {
|
|
||||||
add_plist_top(&plist, PLIST_NAME, basename_of(pkg));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make first "real contents" pass over it */
|
|
||||||
check_list(&plist, basename_of(pkg));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We're just here for to dump out a revised plist for the FreeBSD ports
|
|
||||||
* hack. It's not a real create in progress.
|
|
||||||
*/
|
|
||||||
if (PlistOnly) {
|
|
||||||
write_plist(&plist, stdout, realprefix);
|
|
||||||
retval = TRUE;
|
|
||||||
} else {
|
|
||||||
#ifdef BOOTSTRAP
|
|
||||||
warnx("Package building is not supported in bootstrap mode");
|
|
||||||
retval = FALSE;
|
|
||||||
#else
|
|
||||||
retval = pkg_build(pkg, full_pkg, suffix, &plist);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cleanup */
|
|
||||||
free(Comment);
|
|
||||||
free(Desc);
|
|
||||||
free_plist(&plist);
|
|
||||||
|
|
||||||
free(allocated_pkg);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
|
@ -1,504 +0,0 @@
|
||||||
.\" $NetBSD: pkg_create.1,v 1.25 2010/04/20 00:39:13 joerg Exp $
|
|
||||||
.\"
|
|
||||||
.\" FreeBSD install - a package for the installation and maintenance
|
|
||||||
.\" 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
|
|
||||||
.\"
|
|
||||||
.\"
|
|
||||||
.\" @(#)pkg_create.1
|
|
||||||
.\" from FreeBSD Id: pkg_create.1,v 1.19 1997/05/02 22:00:05 max Exp
|
|
||||||
.\"
|
|
||||||
.\" hacked up by John Kohl for NetBSD--fixed a few bugs, extended keywords,
|
|
||||||
.\" added dependency tracking, etc.
|
|
||||||
.\"
|
|
||||||
.\" [jkh] Took John's changes back and made some additional extensions for
|
|
||||||
.\" better integration with FreeBSD's new ports collection.
|
|
||||||
.\"
|
|
||||||
.Dd January 20, 2010
|
|
||||||
.Dt PKG_CREATE 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pkg_create
|
|
||||||
.Nd a utility for creating software package distributions
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl ElOUVv
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl B Ar build-info-file
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl b Ar build-version-file
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl C Ar cpkgs
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl D Ar displayfile
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl F Ar compression
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl g Ar group
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl I Ar realprefix
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl i Ar iscript
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl K Ar pkg_dbdir
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl k Ar dscript
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl n Ar preserve-file
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl P Ar dpkgs
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl T Ar buildpkgs
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl p Ar prefix
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl S Ar size-all-file
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl s Ar size-pkg-file
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl t Ar template
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Op Fl u Ar owner
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Fl c Ar comment
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Fl d Ar description
|
|
||||||
.Ek
|
|
||||||
.Bk -words
|
|
||||||
.Fl f Ar packlist
|
|
||||||
.Ek
|
|
||||||
.Ar pkg-name
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command is used to create packages that will subsequently be fed to
|
|
||||||
one of the package extraction/info utilities.
|
|
||||||
The input description and command line arguments for the creation of a
|
|
||||||
package are not really meant to be human-generated, though it is easy
|
|
||||||
enough to do so.
|
|
||||||
It is more expected that you will use a front-end tool for
|
|
||||||
the job rather than muddling through it yourself.
|
|
||||||
Nonetheless, a short description of the input syntax is included in this
|
|
||||||
document.
|
|
||||||
.Sh OPTIONS
|
|
||||||
The following command line options are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Fl B Ar build-info-file
|
|
||||||
Install the file
|
|
||||||
.Ar build-info-file
|
|
||||||
so that users of binary packages can see what
|
|
||||||
.Xr make 1
|
|
||||||
definitions
|
|
||||||
were used to control the build when creating the
|
|
||||||
binary package.
|
|
||||||
This allows various build definitions to be retained in a binary package
|
|
||||||
and viewed wherever it is installed, using
|
|
||||||
.Xr pkg_info 1 .
|
|
||||||
.It Fl b Ar build-version-file
|
|
||||||
Install the file
|
|
||||||
.Ar build-version-file
|
|
||||||
so that users of binary packages can see what versions of
|
|
||||||
the files used to control the build were used when creating the
|
|
||||||
binary package.
|
|
||||||
This allows some fine-grained version control information to be retained
|
|
||||||
in a binary package and viewed wherever it is installed, using
|
|
||||||
.Xr pkg_info 1 .
|
|
||||||
.It Fl C Ar cpkgs
|
|
||||||
Set the initial package conflict list to
|
|
||||||
.Ar cpkgs .
|
|
||||||
This is assumed to be a whitespace separated list of package names
|
|
||||||
and is meant as a convenient shorthand for specifying multiple
|
|
||||||
.Cm @pkgcfl
|
|
||||||
directives in the packing list (see PACKING LIST DETAILS section below).
|
|
||||||
.It Fl c Ar [-]desc
|
|
||||||
Fetch package
|
|
||||||
.Pq one line description
|
|
||||||
from file
|
|
||||||
.Ar desc
|
|
||||||
or, if preceded by
|
|
||||||
.Cm - ,
|
|
||||||
the argument itself.
|
|
||||||
This string should also give some idea of which version of the product
|
|
||||||
(if any) the package represents.
|
|
||||||
.It Fl D Ar displayfile
|
|
||||||
Display the file after installing the package.
|
|
||||||
Useful for things like legal notices on almost-free software, etc.
|
|
||||||
.It Fl d Ar [-]desc
|
|
||||||
Fetch long description for package from file
|
|
||||||
.Ar desc
|
|
||||||
or, if preceded by
|
|
||||||
.Cm - ,
|
|
||||||
the argument itself.
|
|
||||||
.It Fl E
|
|
||||||
Add an empty views file to the package.
|
|
||||||
.It Fl F Ar compression
|
|
||||||
Use
|
|
||||||
.Ar compression
|
|
||||||
as compression algorithm.
|
|
||||||
This overrides the heuristic to guess the compression type from the
|
|
||||||
output name.
|
|
||||||
Currently supported values are bzip2, gzip, none and xz.
|
|
||||||
.It Fl f Ar packlist
|
|
||||||
Fetch
|
|
||||||
.Pq packing list
|
|
||||||
for package from the file
|
|
||||||
.Ar packlist
|
|
||||||
or
|
|
||||||
.Cm stdin
|
|
||||||
if
|
|
||||||
.Ar packlist
|
|
||||||
is a
|
|
||||||
.Cm -
|
|
||||||
(dash).
|
|
||||||
.It Fl g Ar group
|
|
||||||
Make
|
|
||||||
.Ar group
|
|
||||||
the default group ownership instead of extracting it from the file system.
|
|
||||||
.It Fl I Ar realprefix
|
|
||||||
Provide the real prefix, as opposed to the staging prefix, for use in
|
|
||||||
staged installations of packages.
|
|
||||||
.It Fl i Ar iscript
|
|
||||||
Set
|
|
||||||
.Ar iscript
|
|
||||||
to be the install procedure for the package.
|
|
||||||
This can be any executable program (or shell script).
|
|
||||||
It will be invoked automatically when the package is later installed.
|
|
||||||
.It Fl K Ar pkg_dbdir
|
|
||||||
Override the value of the
|
|
||||||
.Dv PKG_DBDIR
|
|
||||||
configuration option with the value
|
|
||||||
.Ar pkg_dbdir .
|
|
||||||
.It Fl k Ar dscript
|
|
||||||
Set
|
|
||||||
.Ar dscript
|
|
||||||
to be the de-install procedure for the package.
|
|
||||||
This can be any executable program (or shell script).
|
|
||||||
It will be invoked automatically
|
|
||||||
when the package is later (if ever) de-installed.
|
|
||||||
.It Fl l
|
|
||||||
Check that any symbolic links which are to be placed in the package are
|
|
||||||
relative to the current prefix.
|
|
||||||
This means using
|
|
||||||
.Xr unlink 2
|
|
||||||
and
|
|
||||||
.Xr symlink 2
|
|
||||||
to remove and re-link
|
|
||||||
any symbolic links which are targeted at full path names.
|
|
||||||
.It Fl n Ar preserve-file
|
|
||||||
The file is used to denote that the package should not be deleted.
|
|
||||||
This is intended for use where the deletion of packages may present
|
|
||||||
a bootstrap problem.
|
|
||||||
.It Fl O
|
|
||||||
Go into a
|
|
||||||
.Pq packing list only
|
|
||||||
mode.
|
|
||||||
This is used to do
|
|
||||||
.Pq fake pkg_add
|
|
||||||
operations when a package is installed.
|
|
||||||
In such cases, it is necessary to know what the final, adjusted packing
|
|
||||||
list will look like.
|
|
||||||
.It Fl P Ar dpkgs
|
|
||||||
Set the initial package dependency list to
|
|
||||||
.Ar dpkgs .
|
|
||||||
This is assumed to be a whitespace separated list of package names
|
|
||||||
and is meant as a convenient shorthand for specifying multiple
|
|
||||||
.Cm @pkgdep
|
|
||||||
directives in the packing list (see PACKING LIST DETAILS section below).
|
|
||||||
In addition, the exact versions of the packages referred to in the
|
|
||||||
.Ar dpkgs
|
|
||||||
list will be added to the packing list in the form of
|
|
||||||
.Cm @blddep
|
|
||||||
directives.
|
|
||||||
.It Fl T Ar buildpkgs
|
|
||||||
The exact versions of the packages referred to in the
|
|
||||||
.Ar buildpkgs
|
|
||||||
list will be added to the packing list in the form of
|
|
||||||
.Cm @blddep
|
|
||||||
directives.
|
|
||||||
This directives are stored after those created by the
|
|
||||||
.Fl P
|
|
||||||
option.
|
|
||||||
.Ar buildpkgs
|
|
||||||
is assumed to be a whitespace separated list of package names.
|
|
||||||
.It Fl p Ar prefix
|
|
||||||
Set
|
|
||||||
.Ar prefix
|
|
||||||
as the initial directory
|
|
||||||
.Pq base
|
|
||||||
to start from in selecting files for
|
|
||||||
the package.
|
|
||||||
.It Fl S Ar size-all-file
|
|
||||||
Store the given file for later querying with the
|
|
||||||
.Xr pkg_info 1
|
|
||||||
.Fl S
|
|
||||||
flag.
|
|
||||||
The file is expected to contain the size (in bytes) of all files of
|
|
||||||
this package plus any required packages added up and stored as a
|
|
||||||
ASCII string, terminated by a newline.
|
|
||||||
.It Fl s Ar size-pkg-file
|
|
||||||
Store the given file for later querying with the
|
|
||||||
.Xr pkg_info 1
|
|
||||||
.Fl s
|
|
||||||
flag.
|
|
||||||
The file is expected to contain the size (in bytes) of all files of
|
|
||||||
this package added up and stored as a ASCII string, terminated by a newline.
|
|
||||||
.It Fl t Ar template
|
|
||||||
Use
|
|
||||||
.Ar template
|
|
||||||
as the input to
|
|
||||||
.Xr mktemp 3 .
|
|
||||||
By default, this is the string
|
|
||||||
.Pa /tmp/instmp.XXXXXX ,
|
|
||||||
but it may be necessary to override it in the situation where
|
|
||||||
space in your
|
|
||||||
.Pa /tmp
|
|
||||||
directory is limited.
|
|
||||||
Be sure to leave some number of
|
|
||||||
.Sq X
|
|
||||||
characters for
|
|
||||||
.Xr mktemp 3
|
|
||||||
to fill in with a unique ID.
|
|
||||||
.It Fl U
|
|
||||||
Do not update the package file database with any file information.
|
|
||||||
.It Fl u Ar owner
|
|
||||||
Make
|
|
||||||
.Ar owner
|
|
||||||
the default owner instead of extracting it from the file system.
|
|
||||||
.It Fl V
|
|
||||||
Print version number and exit.
|
|
||||||
.It Fl v
|
|
||||||
Turn on verbose output.
|
|
||||||
.El
|
|
||||||
.Sh PACKING LIST DETAILS
|
|
||||||
The
|
|
||||||
.Pq packing list
|
|
||||||
format (see
|
|
||||||
.Fl f )
|
|
||||||
is fairly simple, being
|
|
||||||
nothing more than a single column of filenames to include in the
|
|
||||||
package.
|
|
||||||
However, since absolute pathnames are generally a bad idea
|
|
||||||
for a package that could be installed potentially anywhere, there is
|
|
||||||
another method of specifying where things are supposed to go
|
|
||||||
and, optionally, what ownership and mode information they should be
|
|
||||||
installed with.
|
|
||||||
This is done by embedding specialized command sequences
|
|
||||||
in the packing list.
|
|
||||||
Briefly described, these sequences are:
|
|
||||||
.Bl -tag -width indent -compact
|
|
||||||
.It Cm @cwd Ar directory
|
|
||||||
Set the internal directory pointer to point to
|
|
||||||
.Ar directory .
|
|
||||||
All subsequent filenames will be assumed relative to this directory.
|
|
||||||
Note:
|
|
||||||
.Cm @cd
|
|
||||||
is also an alias for this command.
|
|
||||||
.It Cm @src Ar directory
|
|
||||||
This command is supported for compatibility only.
|
|
||||||
It was formerly used to override
|
|
||||||
.Cm @cwd
|
|
||||||
during package creation.
|
|
||||||
.It Cm @exec Ar command
|
|
||||||
Execute
|
|
||||||
.Ar command
|
|
||||||
as part of the unpacking process.
|
|
||||||
If
|
|
||||||
.Ar command
|
|
||||||
contains any of the following sequences somewhere in it, they will
|
|
||||||
be expanded inline.
|
|
||||||
For the following examples, assume that
|
|
||||||
.Cm @cwd
|
|
||||||
is set to
|
|
||||||
.Pa /usr/local
|
|
||||||
and the last extracted file was
|
|
||||||
.Pa bin/emacs .
|
|
||||||
.Bl -tag -width indent -compact
|
|
||||||
.It Cm "\&%F"
|
|
||||||
Expands to the last filename extracted (as specified), in the example case
|
|
||||||
.Pa bin/emacs
|
|
||||||
.It Cm "\&%D"
|
|
||||||
Expand to the current directory prefix, as set with
|
|
||||||
.Cm @cwd ,
|
|
||||||
in the example case
|
|
||||||
.Pa /usr/local .
|
|
||||||
.It Cm "\&%B"
|
|
||||||
Expand to the
|
|
||||||
.Pq basename
|
|
||||||
of the fully qualified filename, that
|
|
||||||
is the current directory prefix, plus the last filespec, minus
|
|
||||||
the trailing filename.
|
|
||||||
In the example case, that would be
|
|
||||||
.Pa /usr/local/bin .
|
|
||||||
.It Cm "\&%f"
|
|
||||||
Expand to the
|
|
||||||
.Pq filename
|
|
||||||
part of the fully qualified name, or
|
|
||||||
the converse of
|
|
||||||
.Cm \&%B ,
|
|
||||||
being in the example case,
|
|
||||||
.Pa emacs .
|
|
||||||
.El
|
|
||||||
.It Cm @unexec Ar command
|
|
||||||
Execute
|
|
||||||
.Ar command
|
|
||||||
as part of the deinstallation process.
|
|
||||||
Expansion of special
|
|
||||||
.Cm \&%
|
|
||||||
sequences is the same as for
|
|
||||||
.Cm @exec .
|
|
||||||
This command is not executed during the package add, as
|
|
||||||
.Cm @exec
|
|
||||||
is, but rather when the package is deleted.
|
|
||||||
This is useful for deleting links and other ancillary files that were created
|
|
||||||
as a result of adding the package, but not directly known to the package's
|
|
||||||
table of contents (and hence not automatically removable).
|
|
||||||
The advantage of using
|
|
||||||
.Cm @unexec
|
|
||||||
over a deinstallation script is that you can use the
|
|
||||||
.Pq special sequence expansion
|
|
||||||
to get at files regardless of where they've
|
|
||||||
been potentially redirected (see
|
|
||||||
.Fl p ) .
|
|
||||||
.It Cm @mode Ar mode
|
|
||||||
Set default permission for all subsequently extracted files to
|
|
||||||
.Ar mode .
|
|
||||||
Format is the same as that used by the
|
|
||||||
.Cm chmod
|
|
||||||
command (well, considering that it's later handed off to it, that's
|
|
||||||
no surprise).
|
|
||||||
Use without an arg to set back to default (extraction) permissions.
|
|
||||||
.It Cm @option Ar option
|
|
||||||
Set internal package options, the only currently supported one
|
|
||||||
being
|
|
||||||
.Ar preserve ,
|
|
||||||
which tells pkg_add to move any existing files out of the way,
|
|
||||||
preserving the previous contents (which are also resurrected on
|
|
||||||
pkg_delete, so caveat emptor).
|
|
||||||
.It Cm @owner Ar user
|
|
||||||
Set default ownership for all subsequently extracted files to
|
|
||||||
.Ar user .
|
|
||||||
Use without an arg to set back to default (extraction)
|
|
||||||
ownership.
|
|
||||||
.It Cm @group Ar group
|
|
||||||
Set default group ownership for all subsequently extracted files to
|
|
||||||
.Ar group .
|
|
||||||
Use without an arg to set back to default (extraction)
|
|
||||||
group ownership.
|
|
||||||
.It Cm @comment Ar string
|
|
||||||
Embed a comment in the packing list.
|
|
||||||
Useful in trying to document some particularly hairy sequence that
|
|
||||||
may trip someone up later.
|
|
||||||
.It Cm @ignore
|
|
||||||
Used internally to tell extraction to ignore the next file (don't
|
|
||||||
copy it anywhere), as it's used for some special purpose.
|
|
||||||
.It Cm @name Ar name
|
|
||||||
Set the name of the package.
|
|
||||||
This is mandatory and is usually put at the top.
|
|
||||||
This name is potentially different than the name of the file it came in,
|
|
||||||
and is used when keeping track of the package for later deinstallation.
|
|
||||||
Note that
|
|
||||||
.Nm
|
|
||||||
will derive this field from the
|
|
||||||
.Ar pkg-name
|
|
||||||
and add it automatically if none is given.
|
|
||||||
.It Cm @pkgdir Ar name
|
|
||||||
Declare directory
|
|
||||||
.Pa name
|
|
||||||
as managed.
|
|
||||||
If it does not exist at installation time, it is created.
|
|
||||||
If this directory is no longer referenced by packages and the last
|
|
||||||
file or directory in it is deleted, the directory is removed as well.
|
|
||||||
.It Cm @dirrm Ar name
|
|
||||||
This command is supported for compatibility only.
|
|
||||||
If directory
|
|
||||||
.Pa name
|
|
||||||
exists, it will be deleted at deinstall time.
|
|
||||||
.It Cm @display Ar name
|
|
||||||
Declare
|
|
||||||
.Pa name
|
|
||||||
as the file to be displayed at install time (see
|
|
||||||
.Fl D
|
|
||||||
above).
|
|
||||||
.It Cm @pkgdep Ar pkgname
|
|
||||||
Declare a dependency on the
|
|
||||||
.Ar pkgname
|
|
||||||
package.
|
|
||||||
The
|
|
||||||
.Ar pkgname
|
|
||||||
package must be installed before this package may be
|
|
||||||
installed, and this package must be deinstalled before the
|
|
||||||
.Ar pkgname
|
|
||||||
package is deinstalled.
|
|
||||||
Multiple
|
|
||||||
.Cm @pkgdep
|
|
||||||
directives may be used if the package depends on multiple other packages.
|
|
||||||
.It Cm @blddep Ar pkgname
|
|
||||||
Declare that this package was built with the exact version
|
|
||||||
of
|
|
||||||
.Ar pkgname
|
|
||||||
(since the
|
|
||||||
.Cm @pkgdep
|
|
||||||
directive may contain wildcards or relational
|
|
||||||
package version information).
|
|
||||||
.It Cm @pkgcfl Ar pkgcflname
|
|
||||||
Declare a conflict with the
|
|
||||||
.Ar pkgcflname
|
|
||||||
package, as the two packages contain references to the same files,
|
|
||||||
and so cannot co-exist on the same system.
|
|
||||||
.El
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
See
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
for options, that can also be specified using the environment.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_add 1 ,
|
|
||||||
.Xr pkg_admin 1 ,
|
|
||||||
.Xr pkg_delete 1 ,
|
|
||||||
.Xr pkg_info 1 ,
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
.Xr pkgsrc 7
|
|
||||||
.Sh HISTORY
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command first appeared in
|
|
||||||
.Fx .
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Bl -tag -width indent -compact
|
|
||||||
.It Jordan Hubbard
|
|
||||||
most of the work
|
|
||||||
.It John Kohl
|
|
||||||
refined it for
|
|
||||||
.Nx
|
|
||||||
.It Hubert Feyrer
|
|
||||||
.Nx
|
|
||||||
wildcard dependency processing, pkgdb, pkg size recording etc.
|
|
||||||
.El
|
|
|
@ -1,217 +0,0 @@
|
||||||
/* $NetBSD: pl.c,v 1.14 2009/11/05 16:22:32 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: pl.c,v 1.14 2009/11/05 16:22:32 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Routines for dealing with the packing list.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#include "create.h"
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if defined(NETBSD)
|
|
||||||
#include <md5.h>
|
|
||||||
#elif defined(__minix)
|
|
||||||
#include <minix/md5.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/md5.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that any symbolic link is relative to the prefix
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
CheckSymlink(char *name, char *prefix, size_t prefixcc)
|
|
||||||
{
|
|
||||||
char newtgt[MaxPathSize];
|
|
||||||
char oldtgt[MaxPathSize];
|
|
||||||
char *slash;
|
|
||||||
int slashc;
|
|
||||||
int cc;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) {
|
|
||||||
oldtgt[cc] = 0;
|
|
||||||
if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') {
|
|
||||||
for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) {
|
|
||||||
}
|
|
||||||
for (cc = i = 0; i < slashc; i++) {
|
|
||||||
strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc);
|
|
||||||
cc += 3;
|
|
||||||
}
|
|
||||||
strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc);
|
|
||||||
(void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt);
|
|
||||||
if (unlink(name) != 0) {
|
|
||||||
warn("can't unlink `%s'", name);
|
|
||||||
} else if (symlink(newtgt, name) != 0) {
|
|
||||||
warn("can't symlink `%s' called `%s'", newtgt, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check a list for files that require preconversion
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
check_list(package_t *pkg, const char *PkgName)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
plist_t *tmp;
|
|
||||||
plist_t *p;
|
|
||||||
char buf[ChecksumHeaderLen + LegibleChecksumLen];
|
|
||||||
char target[MaxPathSize + SymlinkHeaderLen];
|
|
||||||
char name[MaxPathSize];
|
|
||||||
char *cwd = NULL;
|
|
||||||
char *pkgname = NULL;
|
|
||||||
int cc;
|
|
||||||
|
|
||||||
/* Open Package Database for writing */
|
|
||||||
if (update_pkgdb && !pkgdb_open(ReadWrite))
|
|
||||||
err(EXIT_FAILURE, "can't open pkgdb");
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_CWD:
|
|
||||||
cwd = p->name;
|
|
||||||
break;
|
|
||||||
case PLIST_NAME:
|
|
||||||
pkgname = p->name;
|
|
||||||
break;
|
|
||||||
case PLIST_IGNORE:
|
|
||||||
p = p->next;
|
|
||||||
break;
|
|
||||||
case PLIST_PKGDIR:
|
|
||||||
if (cwd == NULL)
|
|
||||||
errx(2, "@pkgdir without preceding @cwd found");
|
|
||||||
if (pkgname == NULL)
|
|
||||||
errx(2, "@pkgdir without preceding @name found");
|
|
||||||
if (update_pkgdb) {
|
|
||||||
add_pkgdir(pkgname, cwd, p->name);
|
|
||||||
/* mkdir_p(cwd, p->name); */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PLIST_FILE:
|
|
||||||
/*
|
|
||||||
* pkgdb handling - usually, we enter files
|
|
||||||
* into the pkgdb as soon as they hit the disk,
|
|
||||||
* but as they are present before pkg_create
|
|
||||||
* starts, it's ok to do this somewhere here
|
|
||||||
*/
|
|
||||||
if (cwd == NULL)
|
|
||||||
errx(2, "file without preceding @cwd found");
|
|
||||||
if (update_pkgdb) {
|
|
||||||
char *s, t[MaxPathSize];
|
|
||||||
|
|
||||||
(void) snprintf(t, sizeof(t), "%s%s%s",
|
|
||||||
cwd,
|
|
||||||
(strcmp(cwd, "/") == 0) ? "" : "/",
|
|
||||||
p->name);
|
|
||||||
|
|
||||||
s = pkgdb_retrieve(t);
|
|
||||||
if (s && PlistOnly)
|
|
||||||
warnx("Overwriting %s - "
|
|
||||||
"pkg %s bogus/conflicting?", t, s);
|
|
||||||
else {
|
|
||||||
pkgdb_store(t, PkgName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepend DESTDIR if set? - HF */
|
|
||||||
(void) snprintf(name, sizeof(name), "%s%s%s",
|
|
||||||
cwd,
|
|
||||||
(strcmp(cwd, "/") == 0) ? "" : "/",
|
|
||||||
p->name);
|
|
||||||
if (lstat(name, &st) < 0) {
|
|
||||||
warnx("can't stat `%s'", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (st.st_mode & S_IFMT) {
|
|
||||||
case S_IFDIR:
|
|
||||||
warnx("Warning - directory `%s' in PLIST", name);
|
|
||||||
break;
|
|
||||||
case S_IFLNK:
|
|
||||||
if (RelativeLinks) {
|
|
||||||
CheckSymlink(name, cwd, strlen(cwd));
|
|
||||||
}
|
|
||||||
(void) strlcpy(target, SYMLINK_HEADER,
|
|
||||||
sizeof(target));
|
|
||||||
if ((cc = readlink(name, &target[SymlinkHeaderLen],
|
|
||||||
sizeof(target) - SymlinkHeaderLen - 1)) < 0) {
|
|
||||||
warnx("can't readlink `%s'", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
target[SymlinkHeaderLen + cc] = 0x0;
|
|
||||||
tmp = new_plist_entry();
|
|
||||||
tmp->name = xstrdup(target);
|
|
||||||
tmp->type = PLIST_COMMENT;
|
|
||||||
tmp->next = p->next;
|
|
||||||
tmp->prev = p;
|
|
||||||
if (p == pkg->tail) {
|
|
||||||
pkg->tail = tmp;
|
|
||||||
}
|
|
||||||
p->next = tmp;
|
|
||||||
p = tmp;
|
|
||||||
break;
|
|
||||||
case S_IFCHR:
|
|
||||||
warnx("Warning - char special device `%s' in PLIST", name);
|
|
||||||
break;
|
|
||||||
case S_IFBLK:
|
|
||||||
warnx("Warning - block special device `%s' in PLIST", name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
(void) strlcpy(buf, CHECKSUM_HEADER,
|
|
||||||
sizeof(buf));
|
|
||||||
if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) {
|
|
||||||
tmp = new_plist_entry();
|
|
||||||
tmp->name = xstrdup(buf);
|
|
||||||
tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */
|
|
||||||
tmp->next = p->next;
|
|
||||||
tmp->prev = p;
|
|
||||||
if (p == pkg->tail) {
|
|
||||||
pkg->tail = tmp;
|
|
||||||
}
|
|
||||||
p->next = tmp;
|
|
||||||
p = tmp;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update_pkgdb) {
|
|
||||||
pkgdb_close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
/*-
|
|
||||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_PWD_H
|
|
||||||
#include <grp.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_PWD_H
|
|
||||||
#include <pwd.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_TIME_H
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#include "create.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
update_ids(struct memory_file *file)
|
|
||||||
{
|
|
||||||
if (file->owner != NULL) {
|
|
||||||
uid_t uid;
|
|
||||||
|
|
||||||
if (uid_from_user(file->owner, &uid) == -1)
|
|
||||||
errx(2, "user %s unknown", file->owner);
|
|
||||||
file->st.st_uid = uid;
|
|
||||||
} else {
|
|
||||||
file->owner = user_from_uid(file->st.st_uid, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file->group != NULL) {
|
|
||||||
gid_t gid;
|
|
||||||
|
|
||||||
if (gid_from_group(file->group, &gid) == -1)
|
|
||||||
errx(2, "group %s unknown", file->group);
|
|
||||||
file->group = file->group;
|
|
||||||
file->st.st_gid = gid;
|
|
||||||
} else {
|
|
||||||
file->group = group_from_gid(file->st.st_gid, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct memory_file *
|
|
||||||
make_memory_file(const char *archive_name, void *data, size_t len,
|
|
||||||
const char *owner, const char *group, mode_t mode)
|
|
||||||
{
|
|
||||||
struct memory_file *file;
|
|
||||||
|
|
||||||
file = xmalloc(sizeof(*file));
|
|
||||||
file->name = archive_name;
|
|
||||||
file->owner = owner;
|
|
||||||
file->group = group;
|
|
||||||
file->data = data;
|
|
||||||
file->len = len;
|
|
||||||
|
|
||||||
memset(&file->st, 0, sizeof(file->st));
|
|
||||||
|
|
||||||
file->st.st_atime = file->st.st_ctime = file->st.st_mtime = time(NULL);
|
|
||||||
|
|
||||||
file->st.st_nlink = 1;
|
|
||||||
file->st.st_size = len;
|
|
||||||
file->st.st_mode = mode | S_IFREG;
|
|
||||||
|
|
||||||
update_ids(file);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct memory_file *
|
|
||||||
load_memory_file(const char *disk_name,
|
|
||||||
const char *archive_name, const char *owner, const char *group,
|
|
||||||
mode_t mode)
|
|
||||||
{
|
|
||||||
struct memory_file *file;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
file = xmalloc(sizeof(*file));
|
|
||||||
file->name = archive_name;
|
|
||||||
file->owner = owner;
|
|
||||||
file->group = group;
|
|
||||||
file->mode = mode;
|
|
||||||
|
|
||||||
fd = open(disk_name, O_RDONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
err(2, "cannot open file %s", disk_name);
|
|
||||||
if (fstat(fd, &file->st) == -1)
|
|
||||||
err(2, "cannot stat file %s", disk_name);
|
|
||||||
|
|
||||||
update_ids(file);
|
|
||||||
|
|
||||||
if ((file->st.st_mode & S_IFMT) != S_IFREG)
|
|
||||||
errx(1, "meta data file %s is not regular file", disk_name);
|
|
||||||
/* if (file->st.st_size > SSIZE_MAX)
|
|
||||||
errx(2, "meta data file too large: %s", disk_name);
|
|
||||||
file->data = xmalloc(file->st.st_size);
|
|
||||||
|
|
||||||
if (read(fd, file->data, file->st.st_size) != file->st.st_size)
|
|
||||||
err(2, "cannot read file into memory %s", disk_name);
|
|
||||||
*/
|
|
||||||
file->data = xmalloc(file->st.st_size);
|
|
||||||
if (readfile(fd, file->data, file->st.st_size) < 0)
|
|
||||||
err(2, "cannot read file into memory %s", disk_name);
|
|
||||||
|
|
||||||
|
|
||||||
file->len = file->st.st_size;
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_memory_file(struct memory_file *file)
|
|
||||||
{
|
|
||||||
if (file != NULL) {
|
|
||||||
free(file->data);
|
|
||||||
free(file);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
PROG= pkg_delete
|
|
||||||
|
|
||||||
SRCS= pkg_delete.c
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,300 +0,0 @@
|
||||||
.\" $NetBSD: pkg_delete.1,v 1.30 2010/02/25 06:56:23 wiz Exp $
|
|
||||||
.\"
|
|
||||||
.\" FreeBSD install - a package for the installation and maintenance
|
|
||||||
.\" 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
|
|
||||||
.\"
|
|
||||||
.\"
|
|
||||||
.\" from FreeBSD: @(#)pkg_delete.1
|
|
||||||
.\"
|
|
||||||
.Dd January 20, 2010
|
|
||||||
.Dt PKG_DELETE 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pkg_delete
|
|
||||||
.Nd a utility for deleting previously installed software package distributions
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl ADFfkNnORrVv
|
|
||||||
.Op Fl K Ar pkg_dbdir
|
|
||||||
.Op Fl P Ar destdir
|
|
||||||
.Op Fl p Ar prefix
|
|
||||||
.Ar pkg-name ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command is used to delete packages that have been previously installed
|
|
||||||
with the
|
|
||||||
.Xr pkg_add 1
|
|
||||||
command.
|
|
||||||
The given packages are sorted, so that the dependencies needed by a
|
|
||||||
package are deleted after the package.
|
|
||||||
Before any action is executed,
|
|
||||||
.Nm
|
|
||||||
checks for packages that are marked as
|
|
||||||
.Cm preserved
|
|
||||||
or have depending packages left.
|
|
||||||
If the
|
|
||||||
.Fl k
|
|
||||||
flag is given, preserved packages are skipped and not removed.
|
|
||||||
Unless the
|
|
||||||
.Fl f
|
|
||||||
flag is given,
|
|
||||||
.Nm
|
|
||||||
stops on the first error.
|
|
||||||
.Sh WARNING
|
|
||||||
.Bf -emphasis
|
|
||||||
Since the
|
|
||||||
.Nm
|
|
||||||
command may execute scripts or programs provided by a package file,
|
|
||||||
your system may be susceptible to
|
|
||||||
.Dq Trojan horses
|
|
||||||
or other subtle
|
|
||||||
attacks from miscreants who create dangerous package files.
|
|
||||||
.Pp
|
|
||||||
You are advised to verify the competence and identity of those who
|
|
||||||
provide installable package files.
|
|
||||||
For extra protection, examine all the package control files in the
|
|
||||||
package record directory
|
|
||||||
.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt]/ ) .
|
|
||||||
Pay particular
|
|
||||||
attention to any
|
|
||||||
.Pa +INSTALL
|
|
||||||
or
|
|
||||||
.Pa +DEINSTALL
|
|
||||||
files, and inspect the
|
|
||||||
.Pa +CONTENTS
|
|
||||||
file for
|
|
||||||
.Cm @cwd ,
|
|
||||||
.Cm @mode
|
|
||||||
(check for setuid),
|
|
||||||
.Cm @dirrm ,
|
|
||||||
.Cm @exec ,
|
|
||||||
and
|
|
||||||
.Cm @unexec
|
|
||||||
directives, and/or use the
|
|
||||||
.Xr pkg_info 1
|
|
||||||
command to examine the installed package control files.
|
|
||||||
.Ef
|
|
||||||
.Sh OPTIONS
|
|
||||||
The following command line options are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Ar pkg-name ...
|
|
||||||
The named packages are deinstalled, wildcards can be used, see
|
|
||||||
.Xr pkg_info 1 .
|
|
||||||
If no version is given, the one currently installed
|
|
||||||
will be removed.
|
|
||||||
If the
|
|
||||||
.Fl F
|
|
||||||
flag is given, one or more (absolute) filenames may be specified and
|
|
||||||
the package database will be consulted for the package to which the
|
|
||||||
given file belongs.
|
|
||||||
These packages are then deinstalled.
|
|
||||||
.It Fl A
|
|
||||||
Recursively remove all automatically installed packages that were needed
|
|
||||||
by the given packages and are no longer required.
|
|
||||||
Does not remove manually installed packages; see also the
|
|
||||||
.Fl R
|
|
||||||
flag.
|
|
||||||
.It Fl D
|
|
||||||
If a deinstallation script exists for a given package, do not execute it.
|
|
||||||
.It Fl F
|
|
||||||
Any
|
|
||||||
.Ar pkg-name
|
|
||||||
given will be interpreted as pathname which is
|
|
||||||
subsequently transformed in a (real) package name via the package
|
|
||||||
database.
|
|
||||||
That way, packages can be deleted by giving a filename
|
|
||||||
instead of the package-name.
|
|
||||||
.It Fl f
|
|
||||||
Force removal of the package, even if a dependency is recorded or the
|
|
||||||
deinstall script fails.
|
|
||||||
This might break the package database; see
|
|
||||||
.Xr pkg_admin 1
|
|
||||||
on how to repair it.
|
|
||||||
.It Fl ff
|
|
||||||
Force removal of the package, even if the package is marked as a
|
|
||||||
.Cm preserved
|
|
||||||
package.
|
|
||||||
Note that this is a dangerous operation.
|
|
||||||
See also the
|
|
||||||
.Fl k
|
|
||||||
option.
|
|
||||||
.It Fl K Ar pkg_dbdir
|
|
||||||
Override the value of the
|
|
||||||
.Dv PKG_DBDIR
|
|
||||||
configuration option with the value
|
|
||||||
.Ar pkg_dbdir .
|
|
||||||
.It Fl k
|
|
||||||
Silently skip all packages that are marked as
|
|
||||||
.Cm preserved .
|
|
||||||
.It Fl N
|
|
||||||
Remove the package's registration and its entries from the package database,
|
|
||||||
but leave the files installed.
|
|
||||||
Don't run any deinstall scripts or
|
|
||||||
.Cm @unexec
|
|
||||||
lines either.
|
|
||||||
.It Fl n
|
|
||||||
Don't actually deinstall a package, just report the steps that
|
|
||||||
would be taken.
|
|
||||||
.It Fl O
|
|
||||||
Only delete the package's entries from the package database; do not
|
|
||||||
touch the package or its files itself.
|
|
||||||
.It Fl P Ar destdir
|
|
||||||
Prefix all file and directory names with
|
|
||||||
.Ar destdir .
|
|
||||||
For packages without install scripts this has the same behavior as
|
|
||||||
using
|
|
||||||
.Xr chroot 8 .
|
|
||||||
.It Fl p Ar prefix
|
|
||||||
Set
|
|
||||||
.Ar prefix
|
|
||||||
as the directory in which to delete files from any installed packages
|
|
||||||
which do not explicitly set theirs.
|
|
||||||
For most packages, the prefix will
|
|
||||||
be set automatically to the installed location by
|
|
||||||
.Xr pkg_add 1 .
|
|
||||||
.It Fl R
|
|
||||||
Recursively remove all packages that were needed by the given packages
|
|
||||||
and are no longer required.
|
|
||||||
This option overrides the
|
|
||||||
.Fl A
|
|
||||||
flag.
|
|
||||||
.It Fl r
|
|
||||||
Recursively remove all packages that require one of the packages given.
|
|
||||||
.It Fl V
|
|
||||||
Print version number and exit.
|
|
||||||
.It Fl v
|
|
||||||
Turn on verbose output.
|
|
||||||
.El
|
|
||||||
.Sh TECHNICAL DETAILS
|
|
||||||
.Nm
|
|
||||||
does pretty much what it says.
|
|
||||||
It examines installed package records in
|
|
||||||
.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt] ,
|
|
||||||
deletes the package contents, and finally removes the package records.
|
|
||||||
.Pp
|
|
||||||
If a package is required by other installed packages,
|
|
||||||
.Nm
|
|
||||||
will list those dependent packages and refuse to delete the package
|
|
||||||
(unless the
|
|
||||||
.Fl f
|
|
||||||
option is given).
|
|
||||||
.Pp
|
|
||||||
If a package has been marked as a
|
|
||||||
.Cm preserved
|
|
||||||
package, it will not be able to be deleted
|
|
||||||
(unless more than one occurrence of the
|
|
||||||
.Fl f
|
|
||||||
option is given).
|
|
||||||
.Pp
|
|
||||||
If a filename is given instead of a package name, the package of which
|
|
||||||
the given file belongs to can be deleted if the
|
|
||||||
.Fl F
|
|
||||||
flag is given.
|
|
||||||
The filename needs to be absolute, see the output produced by the
|
|
||||||
.Xr pkg_info 1
|
|
||||||
.Fl aF
|
|
||||||
command.
|
|
||||||
.Pp
|
|
||||||
If a
|
|
||||||
.Cm deinstall
|
|
||||||
script exists for the package, it is executed before and after
|
|
||||||
any files are removed.
|
|
||||||
It is this script's responsibility to clean up any additional messy details
|
|
||||||
around the package's installation, since all
|
|
||||||
.Nm
|
|
||||||
knows how to do is delete the files created in the original distribution.
|
|
||||||
The
|
|
||||||
.Ic deinstall
|
|
||||||
script is called as:
|
|
||||||
.Bd -filled -offset indent -compact
|
|
||||||
.Cm deinstall
|
|
||||||
.Aq Ar pkg-name
|
|
||||||
.Ar VIEW-DEINSTALL
|
|
||||||
.Ed
|
|
||||||
before removing the package from a view, and as:
|
|
||||||
.Bd -filled -offset indent -compact
|
|
||||||
.Cm deinstall
|
|
||||||
.Aq Ar pkg-name
|
|
||||||
.Ar DEINSTALL
|
|
||||||
.Ed
|
|
||||||
before deleting all files and as:
|
|
||||||
.Bd -filled -offset indent -compact
|
|
||||||
.Cm deinstall
|
|
||||||
.Aq Ar pkg-name
|
|
||||||
.Ar POST-DEINSTALL
|
|
||||||
.Ed
|
|
||||||
after deleting them.
|
|
||||||
Passing the keywords
|
|
||||||
.Ar VIEW-DEINSTALL ,
|
|
||||||
.Ar DEINSTALL ,
|
|
||||||
and
|
|
||||||
.Ar POST-DEINSTALL
|
|
||||||
lets you potentially write only one program/script that handles all
|
|
||||||
aspects of installation and deletion.
|
|
||||||
.Pp
|
|
||||||
All scripts are called with the environment variable
|
|
||||||
.Ev PKG_PREFIX
|
|
||||||
set to the installation prefix (see the
|
|
||||||
.Fl p
|
|
||||||
option above).
|
|
||||||
This allows a package author to write a script
|
|
||||||
that reliably performs some action on the directory where the package
|
|
||||||
is installed, even if the user might have changed it by specifying the
|
|
||||||
.Fl p
|
|
||||||
option when running
|
|
||||||
.Nm
|
|
||||||
or
|
|
||||||
.Xr pkg_add 1 .
|
|
||||||
The scripts are also called with the
|
|
||||||
.Ev PKG_METADATA_DIR
|
|
||||||
environment variable set to the location of the
|
|
||||||
.Pa +*
|
|
||||||
meta-data files, and with the
|
|
||||||
.Ev PKG_REFCOUNT_DBDIR
|
|
||||||
environment variable set to the location of the package reference counts
|
|
||||||
database directory.
|
|
||||||
If the
|
|
||||||
.Fl P
|
|
||||||
flag was given to
|
|
||||||
.Nm ,
|
|
||||||
.Ev PKG_DESTDIR
|
|
||||||
will be set to
|
|
||||||
.Ar destdir .
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
See
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
for options, that can also be specified using the environment.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_add 1 ,
|
|
||||||
.Xr pkg_admin 1 ,
|
|
||||||
.Xr pkg_create 1 ,
|
|
||||||
.Xr pkg_info 1 ,
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
.Xr pkgsrc 7
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Bl -tag -width indent -compact
|
|
||||||
.It "Jordan Hubbard"
|
|
||||||
most of the work
|
|
||||||
.It "John Kohl"
|
|
||||||
refined it for
|
|
||||||
.Nx
|
|
||||||
.It "Hubert Feyrer"
|
|
||||||
.Nx
|
|
||||||
wildcard dependency processing, pkgdb, recursive "down"
|
|
||||||
delete, etc.
|
|
||||||
.It Joerg Sonnenberger
|
|
||||||
Rewrote most of the code to compute correct order of deinstallation
|
|
||||||
and to improve error handling.
|
|
||||||
.El
|
|
|
@ -1,932 +0,0 @@
|
||||||
/*-
|
|
||||||
* Copyright (c) 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* Copyright (c) 2003 Johnny Lam <jlam@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: pkg_delete.c,v 1.11 2010/02/03 14:20:14 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static const char *pkgdb;
|
|
||||||
static const char *destdir;
|
|
||||||
static const char *prefix;
|
|
||||||
|
|
||||||
static int keep_preserve;
|
|
||||||
static int no_deinstall;
|
|
||||||
static int find_by_filename;
|
|
||||||
static int unregister_only;
|
|
||||||
static int pkgdb_update_only;
|
|
||||||
static int delete_recursive;
|
|
||||||
static int delete_new_leaves;
|
|
||||||
static int delete_automatic_leaves;
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "usage: pkg_delete [-DFfkNnORrVv] [-K pkg_dbdir]"
|
|
||||||
" [-P destdir] [-p prefix] pkg-name ...\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
add_by_filename(lpkg_head_t *pkgs, const char *filename)
|
|
||||||
{
|
|
||||||
lpkg_t *lpp;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
if ((s = pkgdb_retrieve(filename)) == NULL) {
|
|
||||||
warnx("No matching package for file `%s' in pkgdb", filename);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX Verify that pkgdb is consistent? Trust it for now... */
|
|
||||||
|
|
||||||
lpp = alloc_lpkg(s);
|
|
||||||
TAILQ_INSERT_TAIL(pkgs, lpp, lp_link);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
add_by_pattern(lpkg_head_t *pkgs, const char *pattern)
|
|
||||||
{
|
|
||||||
switch (add_installed_pkgs_by_pattern(pattern, pkgs)) {
|
|
||||||
case 0:
|
|
||||||
warnx("No package matching `%s' found", pattern);
|
|
||||||
return 1;
|
|
||||||
case -1:
|
|
||||||
warnx("Error while iterating package database for `%s'",
|
|
||||||
pattern);
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The argument is either a fixed package name or an absolute path.
|
|
||||||
* The latter is recognized for legacy compatibility and must point
|
|
||||||
* into the package database.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
add_by_pkgname(lpkg_head_t *pkgs, char *pkg)
|
|
||||||
{
|
|
||||||
char *s;
|
|
||||||
lpkg_t *lpp;
|
|
||||||
size_t l;
|
|
||||||
const char *orig_pkg = pkg;
|
|
||||||
|
|
||||||
if (pkg[0] == '/') {
|
|
||||||
l = strlen(pkgdb);
|
|
||||||
if (strncmp(pkg, pkgdb, l) || pkg[l] != '/') {
|
|
||||||
warnx("Absolute path is not relative to "
|
|
||||||
"package database, skipping: %s", pkg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
pkg += l + 1;
|
|
||||||
}
|
|
||||||
l = strcspn(pkg, "/");
|
|
||||||
if (pkg[l + strspn(pkg + l, "/")] != '\0') {
|
|
||||||
warnx("`%s' is not a package name, skipping", orig_pkg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
pkg[l] = '\0';
|
|
||||||
|
|
||||||
s = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
|
|
||||||
if (fexists(s)) {
|
|
||||||
free(s);
|
|
||||||
lpp = alloc_lpkg(pkg);
|
|
||||||
TAILQ_INSERT_TAIL(pkgs, lpp, lp_link);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
free(s);
|
|
||||||
|
|
||||||
switch (add_installed_pkgs_by_basename(pkg, pkgs)) {
|
|
||||||
case 0:
|
|
||||||
warnx("No matching package for basename `%s' of `%s'",
|
|
||||||
pkg, orig_pkg);
|
|
||||||
return 1;
|
|
||||||
case -1:
|
|
||||||
warnx("Error expanding basename `%s' of `%s'",
|
|
||||||
pkg, orig_pkg);
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Evaluate +REQUIRED_BY. This function is used for four different
|
|
||||||
* tasks:
|
|
||||||
* 0: check if no depending packages remain
|
|
||||||
* 1: like 0, but prepend the depending packages to pkgs if they exist
|
|
||||||
* 2: print remaining packages to stderr
|
|
||||||
* 3: check all and at least one depending packages have been removed
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
process_required_by(const char *pkg, lpkg_head_t *pkgs,
|
|
||||||
lpkg_head_t *sorted_pkgs, int action)
|
|
||||||
{
|
|
||||||
char line[MaxPathSize], *eol, *fname;
|
|
||||||
FILE *fp;
|
|
||||||
lpkg_t *lpp;
|
|
||||||
int got_match, got_miss;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, REQUIRED_BY_FNAME);
|
|
||||||
if (!fexists(fname)) {
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fp = fopen(fname, "r")) == NULL) {
|
|
||||||
warn("Failed to open `%s'", fname);
|
|
||||||
free(fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
got_match = 0;
|
|
||||||
got_miss = 0;
|
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), fp)) {
|
|
||||||
if ((eol = strrchr(line, '\n')) != NULL)
|
|
||||||
*eol = '\0';
|
|
||||||
TAILQ_FOREACH(lpp, sorted_pkgs, lp_link) {
|
|
||||||
if (strcmp(lpp->lp_name, line) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (lpp != NULL) {
|
|
||||||
got_match = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
got_miss = 1;
|
|
||||||
if (pkgs) {
|
|
||||||
TAILQ_FOREACH(lpp, pkgs, lp_link) {
|
|
||||||
if (strcmp(lpp->lp_name, line) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (lpp != NULL)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (action) {
|
|
||||||
case 0:
|
|
||||||
fclose(fp);
|
|
||||||
return 1;
|
|
||||||
case 1:
|
|
||||||
lpp = alloc_lpkg(line);
|
|
||||||
TAILQ_INSERT_HEAD(pkgs, lpp, lp_link);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
fprintf(stderr, "\t%s\n", line);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return (action == 3 ? got_match : got_miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Main function to order the patterns from the command line and
|
|
||||||
* add the subtrees for -r processing as needed.
|
|
||||||
*
|
|
||||||
* The first part ensures that all packages are listed at most once
|
|
||||||
* in pkgs. Afterwards the list is scanned for packages without depending
|
|
||||||
* packages. Each such package is moved to sorted_pkgs in order.
|
|
||||||
* If -r is given, all dependencies are inserted at the head of pkgs.
|
|
||||||
* The loop has to continue as long as progress is made. This can happen
|
|
||||||
* either because another package has been added to pkgs due to recursion
|
|
||||||
* (head of pkgs changed) or because a package has no more depending packages
|
|
||||||
* (tail of sorted_pkgs changed).
|
|
||||||
*
|
|
||||||
* If no progress is made, the remaining packages are moved to sorted_pkgs
|
|
||||||
* and an error is returned for the !Force case.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
sort_and_recurse(lpkg_head_t *pkgs, lpkg_head_t *sorted_pkgs)
|
|
||||||
{
|
|
||||||
lpkg_t *lpp, *lpp2, *lpp_next, *lpp_old_tail, *lpp_old_head;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) {
|
|
||||||
TAILQ_FOREACH(lpp2, pkgs, lp_link) {
|
|
||||||
if (lpp != lpp2 &&
|
|
||||||
strcmp(lpp->lp_name, lpp2->lp_name) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (lpp2 == NULL)
|
|
||||||
continue;
|
|
||||||
TAILQ_REMOVE(pkgs, lpp, lp_link);
|
|
||||||
free_lpkg(lpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(pkgs)) {
|
|
||||||
lpp_old_tail = TAILQ_LAST(sorted_pkgs, _lpkg_head_t);
|
|
||||||
lpp_old_head = TAILQ_FIRST(pkgs);
|
|
||||||
|
|
||||||
TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) {
|
|
||||||
rv = process_required_by(lpp->lp_name, pkgs,
|
|
||||||
sorted_pkgs, delete_recursive ? 1 : 0);
|
|
||||||
if (rv)
|
|
||||||
continue;
|
|
||||||
TAILQ_REMOVE(pkgs, lpp, lp_link);
|
|
||||||
TAILQ_INSERT_TAIL(sorted_pkgs, lpp, lp_link);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lpp_old_tail == TAILQ_LAST(sorted_pkgs, _lpkg_head_t) &&
|
|
||||||
lpp_old_head == TAILQ_FIRST(pkgs))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TAILQ_EMPTY(pkgs))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while (!TAILQ_EMPTY(pkgs)) {
|
|
||||||
lpp = TAILQ_FIRST(pkgs);
|
|
||||||
TAILQ_REMOVE(pkgs, lpp, lp_link);
|
|
||||||
fprintf(stderr,
|
|
||||||
"Package `%s' is still required by other packages:\n",
|
|
||||||
lpp->lp_name);
|
|
||||||
process_required_by(lpp->lp_name, NULL, sorted_pkgs, 2);
|
|
||||||
if (Force) {
|
|
||||||
TAILQ_INSERT_TAIL(sorted_pkgs, lpp, lp_link);
|
|
||||||
} else
|
|
||||||
free_lpkg(lpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return !Force;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct find_leaves_data {
|
|
||||||
lpkg_head_t *pkgs;
|
|
||||||
int progress;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterator for finding leaf packages.
|
|
||||||
* Packages that are marked as not for deletion are not considered as
|
|
||||||
* leaves. For all other packages it is checked if at least one package
|
|
||||||
* that depended on them is to be removed AND no depending package remains.
|
|
||||||
* If that is the case, the package is appened to the sorted list.
|
|
||||||
* As this package can't have depending packages left, the topological order
|
|
||||||
* remains consistent.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
find_new_leaves_iter(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
char *fname;
|
|
||||||
struct find_leaves_data *data = cookie;
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, PRESERVE_FNAME);
|
|
||||||
if (fexists(fname)) {
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
if (delete_automatic_leaves && !delete_new_leaves &&
|
|
||||||
!is_automatic_installed(pkg))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Check whether this package is already on the list first. */
|
|
||||||
TAILQ_FOREACH(lpp, data->pkgs, lp_link) {
|
|
||||||
if (strcmp(lpp->lp_name, pkg) == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process_required_by(pkg, NULL, data->pkgs, 3) == 1) {
|
|
||||||
lpp = alloc_lpkg(pkg);
|
|
||||||
TAILQ_INSERT_TAIL(data->pkgs, lpp, lp_link);
|
|
||||||
data->progress = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Iterate over all installed packages and look for new leaf packages.
|
|
||||||
* As long as the loop adds one new leaf package, processing continues.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
find_new_leaves(lpkg_head_t *pkgs)
|
|
||||||
{
|
|
||||||
struct find_leaves_data data;
|
|
||||||
|
|
||||||
data.pkgs = pkgs;
|
|
||||||
do {
|
|
||||||
data.progress = 0;
|
|
||||||
iterate_pkg_db(find_new_leaves_iter, &data);
|
|
||||||
} while (data.progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that no entry on the package list is marked as not for deletion.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
find_preserve_pkgs(lpkg_head_t *pkgs)
|
|
||||||
{
|
|
||||||
lpkg_t *lpp, *lpp_next;
|
|
||||||
char *fname;
|
|
||||||
int found_preserve;
|
|
||||||
|
|
||||||
found_preserve = 0;
|
|
||||||
TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) {
|
|
||||||
fname = pkgdb_pkg_file(lpp->lp_name, PRESERVE_FNAME);
|
|
||||||
if (!fexists(fname)) {
|
|
||||||
free(fname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
if (keep_preserve) {
|
|
||||||
TAILQ_REMOVE(pkgs, lpp, lp_link);
|
|
||||||
free_lpkg(lpp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!found_preserve)
|
|
||||||
warnx("The following packages are marked as not "
|
|
||||||
"for deletion:");
|
|
||||||
found_preserve = 1;
|
|
||||||
fprintf(stderr, "\t%s\n", lpp->lp_name);
|
|
||||||
}
|
|
||||||
if (!found_preserve)
|
|
||||||
return 0;
|
|
||||||
if (Force == 0 || (!unregister_only && Force == 1))
|
|
||||||
return 1;
|
|
||||||
fprintf(stderr, "...but will delete them anyway\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove package from view. This is calling pkg_deinstall again.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
remove_pkg_from_view(const char *pkg)
|
|
||||||
{
|
|
||||||
char line[MaxPathSize], *fname, *eol;
|
|
||||||
FILE *fp;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, VIEWS_FNAME);
|
|
||||||
if (isemptyfile(fname)) {
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((fp = fopen(fname, "r")) == NULL) {
|
|
||||||
warn("Unable to open `%s', aborting", fname);
|
|
||||||
free(fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
|
||||||
if ((eol = strrchr(line, '\n')) != NULL)
|
|
||||||
*eol = '\0';
|
|
||||||
if (Verbose || Fake)
|
|
||||||
printf("Deleting package `%s' instance from `%s' view\n",
|
|
||||||
pkg, line);
|
|
||||||
if (Fake)
|
|
||||||
continue;
|
|
||||||
if (fexec_skipempty(BINDIR "/pkg_delete", "-K", line,
|
|
||||||
Fake ? "-n" : "",
|
|
||||||
(Force > 1) ? "-f" : "",
|
|
||||||
(Force > 0) ? "-f" : "",
|
|
||||||
pkg, NULL) != 0) {
|
|
||||||
warnx("Unable to delete package `%s' from view `%s'",
|
|
||||||
pkg, line);
|
|
||||||
fclose(fp);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Run the +DEINSTALL script. Depending on whether this is
|
|
||||||
* a depoted package and whether this pre- or post-deinstall phase,
|
|
||||||
* different arguments are passed down.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
run_deinstall_script(const char *pkg, int do_postdeinstall)
|
|
||||||
{
|
|
||||||
const char *target, *text;
|
|
||||||
char *fname, *fname2, *pkgdir;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME);
|
|
||||||
if (!fexists(fname)) {
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fname2 = pkgdb_pkg_file(pkg, DEPOT_FNAME);
|
|
||||||
if (fexists(fname2)) {
|
|
||||||
if (do_postdeinstall) {
|
|
||||||
free(fname);
|
|
||||||
free(fname2);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
target = "VIEW-DEINSTALL";
|
|
||||||
text = "view deinstall";
|
|
||||||
} else if (do_postdeinstall) {
|
|
||||||
target = "POST-DEINSTALL";
|
|
||||||
text = "post-deinstall";
|
|
||||||
} else {
|
|
||||||
target = "DEINSTALL";
|
|
||||||
text = "deinstall";
|
|
||||||
}
|
|
||||||
free(fname2);
|
|
||||||
|
|
||||||
if (Fake) {
|
|
||||||
printf("Would execute %s script with argument %s now\n",
|
|
||||||
text, target);
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgdir = pkgdb_pkg_dir(pkg);
|
|
||||||
if (chmod(fname, 0555))
|
|
||||||
warn("chmod of `%s' failed", fname);
|
|
||||||
rv = fcexec(pkgdir, fname, pkg, target, NULL);
|
|
||||||
if (rv)
|
|
||||||
warnx("%s script returned error status", text);
|
|
||||||
free(pkgdir);
|
|
||||||
free(fname);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy lines from fname to fname_tmp, filtering out lines equal to text.
|
|
||||||
* Afterwards rename fname_tmp to fname;
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
remove_line(const char *fname, const char *fname_tmp, const char *text)
|
|
||||||
{
|
|
||||||
FILE *fp, *fp_out;
|
|
||||||
char line[MaxPathSize], *eol;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
if ((fp = fopen(fname, "r")) == NULL) {
|
|
||||||
warn("Unable to open `%s'", fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((fp_out = fopen(fname_tmp, "w")) == NULL) {
|
|
||||||
warn("Unable to open `%s'", fname_tmp);
|
|
||||||
fclose(fp);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
|
||||||
if ((eol = strrchr(line, '\n')) != NULL)
|
|
||||||
*eol = '\0';
|
|
||||||
if (strcmp(line, text) == 0)
|
|
||||||
continue;
|
|
||||||
fprintf(fp_out, "%s\n", line);
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (fclose(fp_out) == EOF) {
|
|
||||||
remove(fname_tmp);
|
|
||||||
warnx("Failure while closing `%s' temp file", fname_tmp);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(fname_tmp, fname) == -1) {
|
|
||||||
warn("Unable to rename `%s' to `%s'", fname_tmp, fname);
|
|
||||||
rv = 1;
|
|
||||||
} else
|
|
||||||
rv = 0;
|
|
||||||
remove(fname_tmp);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unregister the package from the depot it is registered in.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
remove_pkg_from_depot(const char *pkg)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char line[MaxPathSize], *eol;
|
|
||||||
char *fname, *fname2;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, DEPOT_FNAME);
|
|
||||||
if (isemptyfile(fname)) {
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Verbose)
|
|
||||||
printf("Attempting to remove the `%s' registration "
|
|
||||||
"on package `%s'\n", fname, pkg);
|
|
||||||
|
|
||||||
if (Fake) {
|
|
||||||
free(fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fp = fopen(fname, "r")) == NULL) {
|
|
||||||
warn("Unable to open `%s' file", fname);
|
|
||||||
free(fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (fgets(line, sizeof(line), fp) == NULL) {
|
|
||||||
fclose(fp);
|
|
||||||
warnx("Empty depot file `%s'", fname);
|
|
||||||
free(fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((eol = strrchr(line, '\n')) != NULL)
|
|
||||||
*eol = '\0';
|
|
||||||
fclose(fp);
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, VIEWS_FNAME);
|
|
||||||
fname2 = pkgdb_pkg_file(pkg, VIEWS_FNAME_TMP);
|
|
||||||
rv = remove_line(fname, fname2, line);
|
|
||||||
free(fname2);
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* remove_depend is used as iterator function below.
|
|
||||||
* The passed-in package name should be removed from the
|
|
||||||
* +REQUIRED_BY list of the dependency. Such an entry
|
|
||||||
* can miss in a fully correct package database, if the pattern
|
|
||||||
* matches more than one package.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
remove_depend(const char *cur_pkg, void *cookie)
|
|
||||||
{
|
|
||||||
const char *pkg = cookie;
|
|
||||||
char *fname, *fname2;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(cur_pkg, REQUIRED_BY_FNAME);
|
|
||||||
if (isemptyfile(fname)) {
|
|
||||||
free(fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fname2 = pkgdb_pkg_file(cur_pkg, REQUIRED_BY_FNAME_TMP);
|
|
||||||
|
|
||||||
rv = remove_line(fname, fname2, pkg);
|
|
||||||
|
|
||||||
free(fname2);
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
remove_pkg(const char *pkg)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char *fname, *pkgdir;
|
|
||||||
package_t plist;
|
|
||||||
plist_t *p;
|
|
||||||
int is_depoted_pkg, rv, late_error;
|
|
||||||
|
|
||||||
if (pkgdb_update_only)
|
|
||||||
return pkgdb_remove_pkg(pkg) ? 0 : 1;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
|
|
||||||
if (!fexists(fname)) {
|
|
||||||
warnx("package `%s' is not installed, `%s' missing", pkg, fname);
|
|
||||||
free(fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
/* +REQUIRED_BY and +PRESERVE already checked */
|
|
||||||
if (remove_pkg_from_view(pkg))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The views related code has bad error handling, if e.g.
|
|
||||||
* the deinstall script fails, the package remains unregistered.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
|
|
||||||
if ((fp = fopen(fname, "r")) == NULL) {
|
|
||||||
warnx("Failed to open `%s'", fname);
|
|
||||||
free(fname);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
read_plist(&plist, fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If a prefix has been provided, remove the first @cwd and
|
|
||||||
* prepend that prefix. This allows removing packages without
|
|
||||||
* @cwd if really necessary. pkg_admin rebuild is likely needed
|
|
||||||
* afterwards though.
|
|
||||||
*/
|
|
||||||
if (prefix) {
|
|
||||||
delete_plist(&plist, FALSE, PLIST_CWD, NULL);
|
|
||||||
add_plist_top(&plist, PLIST_CWD, prefix);
|
|
||||||
}
|
|
||||||
if ((p = find_plist(&plist, PLIST_CWD)) == NULL) {
|
|
||||||
warnx("Package `%s' doesn't have a prefix", pkg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (find_plist(&plist, PLIST_NAME) == NULL) {
|
|
||||||
/* Cheat a bit to allow removal of such bad packages. */
|
|
||||||
warnx("Package `%s' doesn't have a name", pkg);
|
|
||||||
add_plist_top(&plist, PLIST_NAME, pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1);
|
|
||||||
fname = pkgdb_pkg_dir(pkg);
|
|
||||||
setenv(PKG_METADATA_DIR_VNAME, fname, 1);
|
|
||||||
free(fname);
|
|
||||||
setenv(PKG_PREFIX_VNAME, p->name, 1);
|
|
||||||
|
|
||||||
if (!no_deinstall && !unregister_only) {
|
|
||||||
if (run_deinstall_script(pkg, 0) && !Force)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
late_error = 0;
|
|
||||||
|
|
||||||
if (Fake)
|
|
||||||
printf("Attempting to delete package `%s'\n", pkg);
|
|
||||||
else if (delete_package(FALSE, &plist, unregister_only,
|
|
||||||
destdir) == FAIL) {
|
|
||||||
warnx("couldn't entirely delete package `%s'", pkg);
|
|
||||||
/*
|
|
||||||
* XXX It could be nice to error out here explicitly,
|
|
||||||
* XXX but this is problematic for missing or changed files.
|
|
||||||
* XXX At least the inability to remove files at all should
|
|
||||||
* XXX be handled though.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Past the point of no return. Files are gone, all that is left
|
|
||||||
* is cleaning up registered dependencies and removing the meta data.
|
|
||||||
* Errors in the remaining part are counted, but don't stop the
|
|
||||||
* processing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, DEPOT_FNAME);
|
|
||||||
if (fexists(fname)) {
|
|
||||||
late_error |= remove_pkg_from_depot(pkg);
|
|
||||||
/* XXX error checking */
|
|
||||||
} else {
|
|
||||||
for (p = plist.head; p; p = p->next) {
|
|
||||||
if (p->type != PLIST_PKGDEP)
|
|
||||||
continue;
|
|
||||||
if (Verbose)
|
|
||||||
printf("Attempting to remove dependency "
|
|
||||||
"on package `%s'\n", p->name);
|
|
||||||
if (Fake)
|
|
||||||
continue;
|
|
||||||
match_installed_pkgs(p->name, remove_depend,
|
|
||||||
__UNCONST(pkg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
free_plist(&plist);
|
|
||||||
|
|
||||||
if (!no_deinstall && !unregister_only)
|
|
||||||
late_error |= run_deinstall_script(pkg, 1);
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, VIEWS_FNAME);
|
|
||||||
if (fexists(fname))
|
|
||||||
is_depoted_pkg = TRUE;
|
|
||||||
else
|
|
||||||
is_depoted_pkg = FALSE;
|
|
||||||
free(fname);
|
|
||||||
|
|
||||||
if (Fake)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Kill the pkgdb subdirectory. The files have been removed, so
|
|
||||||
* this is way beyond the point of no return.
|
|
||||||
*/
|
|
||||||
pkgdir = pkgdb_pkg_dir(pkg);
|
|
||||||
(void) remove_files(pkgdir, "+*");
|
|
||||||
rv = 1;
|
|
||||||
if (isemptydir(pkgdir)&& rmdir(pkgdir) == 0)
|
|
||||||
rv = 0;
|
|
||||||
else if (is_depoted_pkg)
|
|
||||||
warnx("Depot directory `%s' is not empty", pkgdir);
|
|
||||||
else if (!Force)
|
|
||||||
warnx("Couldn't remove package directory in `%s'", pkgdir);
|
|
||||||
else if (recursive_remove(pkgdir, 1))
|
|
||||||
warn("Couldn't remove package directory `%s'", pkgdir);
|
|
||||||
else
|
|
||||||
warnx("Package directory `%s' forcefully removed", pkgdir);
|
|
||||||
free(pkgdir);
|
|
||||||
|
|
||||||
return rv | late_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
lpkg_head_t pkgs, sorted_pkgs;
|
|
||||||
int ch, r, has_error;
|
|
||||||
unsigned long bad_count;
|
|
||||||
|
|
||||||
TAILQ_INIT(&pkgs);
|
|
||||||
TAILQ_INIT(&sorted_pkgs);
|
|
||||||
|
|
||||||
setprogname(argv[0]);
|
|
||||||
while ((ch = getopt(argc, argv, "ADFfK:kNnOP:p:RrVv")) != -1) {
|
|
||||||
switch (ch) {
|
|
||||||
case 'A':
|
|
||||||
delete_automatic_leaves = 1;
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
no_deinstall = 1;
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
find_by_filename = 1;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
++Force;
|
|
||||||
break;
|
|
||||||
case 'K':
|
|
||||||
pkgdb_set_dir(optarg, 3);
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
keep_preserve = 1;
|
|
||||||
break;
|
|
||||||
case 'N':
|
|
||||||
unregister_only = 1;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
Fake = 1;
|
|
||||||
break;
|
|
||||||
case 'O':
|
|
||||||
pkgdb_update_only = 1;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
destdir = optarg;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
prefix = optarg;
|
|
||||||
break;
|
|
||||||
case 'R':
|
|
||||||
delete_new_leaves = 1;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
delete_recursive = 1;
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
show_version();
|
|
||||||
/* NOTREACHED */
|
|
||||||
case 'v':
|
|
||||||
++Verbose;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg_install_config();
|
|
||||||
|
|
||||||
pkgdb = xstrdup(pkgdb_get_dir());
|
|
||||||
|
|
||||||
if (destdir != NULL) {
|
|
||||||
char *pkgdbdir;
|
|
||||||
|
|
||||||
pkgdbdir = xasprintf("%s/%s", destdir, pkgdb);
|
|
||||||
pkgdb_set_dir(pkgdbdir, 4);
|
|
||||||
free(pkgdbdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
if (argc == 0) {
|
|
||||||
if (find_by_filename)
|
|
||||||
warnx("Missing filename(s)");
|
|
||||||
else
|
|
||||||
warnx("Missing package name(s)");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Fake)
|
|
||||||
r = pkgdb_open(ReadOnly);
|
|
||||||
else
|
|
||||||
r = pkgdb_open(ReadWrite);
|
|
||||||
|
|
||||||
if (!r)
|
|
||||||
errx(EXIT_FAILURE, "Opening pkgdb failed");
|
|
||||||
|
|
||||||
/* First, process all command line options. */
|
|
||||||
|
|
||||||
has_error = 0;
|
|
||||||
for (; argc != 0; --argc, ++argv) {
|
|
||||||
if (find_by_filename)
|
|
||||||
has_error |= add_by_filename(&pkgs, *argv);
|
|
||||||
else if (ispkgpattern(*argv))
|
|
||||||
has_error |= add_by_pattern(&pkgs, *argv);
|
|
||||||
else
|
|
||||||
has_error |= add_by_pkgname(&pkgs, *argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_error && !Force) {
|
|
||||||
pkgdb_close();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Second, reorder and recursive if necessary. */
|
|
||||||
|
|
||||||
if (sort_and_recurse(&pkgs, &sorted_pkgs)) {
|
|
||||||
pkgdb_close();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Third, add leaves if necessary. */
|
|
||||||
|
|
||||||
if (delete_new_leaves || delete_automatic_leaves)
|
|
||||||
find_new_leaves(&sorted_pkgs);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now that all packages to remove are known, check
|
|
||||||
* if all are removable. After that, start the actual
|
|
||||||
* removal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (find_preserve_pkgs(&sorted_pkgs)) {
|
|
||||||
pkgdb_close();
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1);
|
|
||||||
|
|
||||||
bad_count = 0;
|
|
||||||
while (!TAILQ_EMPTY(&sorted_pkgs)) {
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
lpp = TAILQ_FIRST(&sorted_pkgs);
|
|
||||||
TAILQ_REMOVE(&sorted_pkgs, lpp, lp_link);
|
|
||||||
if (remove_pkg(lpp->lp_name)) {
|
|
||||||
++bad_count;
|
|
||||||
if (!Force)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free_lpkg(lpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgdb_close();
|
|
||||||
|
|
||||||
if (Force && bad_count && Verbose)
|
|
||||||
warnx("Removal of %lu packages failed", bad_count);
|
|
||||||
|
|
||||||
return bad_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
PROG= pkg_info
|
|
||||||
|
|
||||||
SRCS= main.c perform.c show.c
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
.include <bsd.prog.mk>
|
|
|
@ -1,56 +0,0 @@
|
||||||
# $NetBSD: Makefile.in,v 1.21 2010/04/20 00:39:13 joerg Exp $
|
|
||||||
|
|
||||||
srcdir= @srcdir@
|
|
||||||
|
|
||||||
prefix= @prefix@
|
|
||||||
exec_prefix= @exec_prefix@
|
|
||||||
sbindir= @sbindir@
|
|
||||||
mandir= @mandir@
|
|
||||||
datarootdir= @datarootdir@
|
|
||||||
|
|
||||||
man1dir= $(mandir)/man1
|
|
||||||
cat1dir= $(mandir)/cat1
|
|
||||||
|
|
||||||
BOOTSTRAP= @bootstrap@
|
|
||||||
SSL_SUPPORT= @ssl_support@
|
|
||||||
|
|
||||||
CC= @CC@
|
|
||||||
CCLD= $(CC)
|
|
||||||
.if empty(BOOTSTRAP)
|
|
||||||
LIBS= -linstall -lfetch @LIBS@
|
|
||||||
.if !empty(SSL_SUPPORT)
|
|
||||||
LIBS+= -lcrypto
|
|
||||||
.endif
|
|
||||||
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib
|
|
||||||
.else
|
|
||||||
LIBS= -linstall @LIBS@
|
|
||||||
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib -DBOOTSTRAP
|
|
||||||
.endif
|
|
||||||
DEFS= @DEFS@
|
|
||||||
CFLAGS= @CFLAGS@
|
|
||||||
LDFLAGS= @LDFLAGS@ -L../lib
|
|
||||||
|
|
||||||
INSTALL= @INSTALL@
|
|
||||||
|
|
||||||
PROG= pkg_info
|
|
||||||
|
|
||||||
OBJS= main.o perform.o show.o
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
$(PROG): $(OBJS)
|
|
||||||
$(CCLD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS) $(PROG)
|
|
||||||
|
|
||||||
install:
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(sbindir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man1dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat1dir)
|
|
||||||
$(INSTALL) $(PROG) ${DESTDIR}$(sbindir)/$(PROG)
|
|
||||||
$(INSTALL) -m 444 $(PROG).1 ${DESTDIR}$(man1dir)/$(PROG).1
|
|
||||||
$(INSTALL) -m 444 $(PROG).cat ${DESTDIR}$(cat1dir)/$(PROG).0
|
|
|
@ -1,56 +0,0 @@
|
||||||
# $NetBSD: Makefile.in,v 1.21 2010/04/20 00:39:13 joerg Exp $
|
|
||||||
|
|
||||||
srcdir= .
|
|
||||||
|
|
||||||
prefix= /usr/bin
|
|
||||||
exec_prefix= ${prefix}
|
|
||||||
sbindir= ${exec_prefix}/sbin
|
|
||||||
mandir= ${datarootdir}/man
|
|
||||||
datarootdir= ${prefix}/share
|
|
||||||
|
|
||||||
man1dir= $(mandir)/man1
|
|
||||||
cat1dir= $(mandir)/cat1
|
|
||||||
|
|
||||||
BOOTSTRAP=
|
|
||||||
SSL_SUPPORT=
|
|
||||||
|
|
||||||
CC= cc
|
|
||||||
CCLD= $(CC)
|
|
||||||
.if empty(BOOTSTRAP)
|
|
||||||
LIBS= -linstall -lfetch -larchive -lbz2 -lz -lutil
|
|
||||||
.if !empty(SSL_SUPPORT)
|
|
||||||
LIBS+= -lcrypto
|
|
||||||
.endif
|
|
||||||
CPPFLAGS= -I. -I$(srcdir) -I../lib
|
|
||||||
.else
|
|
||||||
LIBS= -linstall
|
|
||||||
CPPFLAGS= -I. -I$(srcdir) -I../lib -DBOOTSTRAP
|
|
||||||
.endif
|
|
||||||
DEFS= -DHAVE_CONFIG_H
|
|
||||||
CFLAGS= -g
|
|
||||||
LDFLAGS= -L../lib
|
|
||||||
|
|
||||||
INSTALL= /usr/bin/install -c
|
|
||||||
|
|
||||||
PROG= pkg_info
|
|
||||||
|
|
||||||
OBJS= main.o perform.o show.o
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
$(PROG): $(OBJS)
|
|
||||||
$(CCLD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS) $(PROG)
|
|
||||||
|
|
||||||
install:
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(sbindir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man1dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat1dir)
|
|
||||||
$(INSTALL) $(PROG) ${DESTDIR}$(sbindir)/$(PROG)
|
|
||||||
$(INSTALL) -m 444 $(PROG).1 ${DESTDIR}$(man1dir)/$(PROG).1
|
|
||||||
$(INSTALL) -m 444 $(PROG).cat ${DESTDIR}$(cat1dir)/$(PROG).0
|
|
|
@ -1,134 +0,0 @@
|
||||||
/* $NetBSD: info.h,v 1.21 2009/09/11 18:00:13 joerg Exp $ */
|
|
||||||
|
|
||||||
/* from FreeBSD Id: info.h,v 1.10 1997/02/22 16:09:40 peter Exp */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 August 1993
|
|
||||||
*
|
|
||||||
* Include and define various things wanted by the info command.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INST_INFO_H_INCLUDE
|
|
||||||
#define _INST_INFO_H_INCLUDE
|
|
||||||
|
|
||||||
struct pkg_meta {
|
|
||||||
char *meta_contents;
|
|
||||||
char *meta_comment;
|
|
||||||
char *meta_desc;
|
|
||||||
char *meta_mtree;
|
|
||||||
char *meta_build_version;
|
|
||||||
char *meta_build_info;
|
|
||||||
char *meta_size_pkg;
|
|
||||||
char *meta_size_all;
|
|
||||||
char *meta_required_by;
|
|
||||||
char *meta_display;
|
|
||||||
char *meta_install;
|
|
||||||
char *meta_deinstall;
|
|
||||||
char *meta_preserve;
|
|
||||||
char *meta_views;
|
|
||||||
char *meta_installed_info;
|
|
||||||
int is_installed;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef MAXINDEXSIZE
|
|
||||||
#define MAXINDEXSIZE 60
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAXNAMESIZE
|
|
||||||
#define MAXNAMESIZE 20
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SHOW_COMMENT 0x00001
|
|
||||||
#define SHOW_DESC 0x00002
|
|
||||||
#define SHOW_PLIST 0x00004
|
|
||||||
#define SHOW_INSTALL 0x00008
|
|
||||||
#define SHOW_DEINSTALL 0x00010
|
|
||||||
#define SHOW_PREFIX 0x00040
|
|
||||||
#define SHOW_INDEX 0x00080
|
|
||||||
#define SHOW_FILES 0x00100
|
|
||||||
#define SHOW_DISPLAY 0x00200
|
|
||||||
#define SHOW_REQBY 0x00400
|
|
||||||
#define SHOW_MTREE 0x00800
|
|
||||||
#define SHOW_BUILD_VERSION 0x01000
|
|
||||||
#define SHOW_BUILD_INFO 0x02000
|
|
||||||
#define SHOW_DEPENDS 0x04000
|
|
||||||
#define SHOW_PKG_SIZE 0x08000
|
|
||||||
#define SHOW_ALL_SIZE 0x10000
|
|
||||||
#define SHOW_BLD_DEPENDS 0x20000
|
|
||||||
#define SHOW_BI_VAR 0x40000
|
|
||||||
#define SHOW_SUMMARY 0x80000
|
|
||||||
#define SHOW_FULL_REQBY 0x100000
|
|
||||||
|
|
||||||
enum which {
|
|
||||||
WHICH_ALL,
|
|
||||||
WHICH_USER,
|
|
||||||
WHICH_LIST
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int Flags;
|
|
||||||
extern enum which Which;
|
|
||||||
extern Boolean File2Pkg;
|
|
||||||
extern Boolean Quiet;
|
|
||||||
extern const char *InfoPrefix;
|
|
||||||
extern const char *BuildInfoVariable;
|
|
||||||
extern lpkg_head_t pkgs;
|
|
||||||
|
|
||||||
int CheckForPkg(const char *);
|
|
||||||
int CheckForBestPkg(const char *);
|
|
||||||
|
|
||||||
void show_file(const char *, const char *, Boolean);
|
|
||||||
void show_var(const char *, const char *);
|
|
||||||
void show_plist(const char *, package_t *, pl_ent_t);
|
|
||||||
void show_files(const char *, package_t *);
|
|
||||||
void show_depends(const char *, package_t *);
|
|
||||||
void show_bld_depends(const char *, package_t *);
|
|
||||||
void show_index(const char *, const char *);
|
|
||||||
void show_summary(struct pkg_meta *, package_t *, const char *);
|
|
||||||
void show_list(lpkg_head_t *, const char *);
|
|
||||||
|
|
||||||
int pkg_perform(lpkg_head_t *);
|
|
||||||
|
|
||||||
#endif /* _INST_INFO_H_INCLUDE */
|
|
|
@ -1,332 +0,0 @@
|
||||||
/* $NetBSD: main.c,v 1.30 2010/01/22 13:30:42 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: main.c,v 1.30 2010/01/22 13:30:42 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* This is the add module.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_SYS_IOCTL_H
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#include "info.h"
|
|
||||||
|
|
||||||
static const char Options[] = ".aBbcDde:E:fFhIiK:kLl:mNnpQ:qrRsSuvVX";
|
|
||||||
|
|
||||||
int Flags = 0;
|
|
||||||
enum which Which = WHICH_LIST;
|
|
||||||
Boolean File2Pkg = FALSE;
|
|
||||||
Boolean Quiet = FALSE;
|
|
||||||
const char *InfoPrefix = "";
|
|
||||||
const char *BuildInfoVariable = "";
|
|
||||||
lpkg_head_t pkgs;
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
|
||||||
"usage: pkg_info [-BbcDdFfhIikLmNnpqrRSsVvX] [-e package] [-E package]",
|
|
||||||
" [-K pkg_dbdir] [-l prefix] pkg-name ...",
|
|
||||||
" pkg_info [-a | -u] [flags]",
|
|
||||||
" pkg_info [-Q variable] pkg-name ...");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *CheckPkg = NULL;
|
|
||||||
char *BestCheckPkg = NULL;
|
|
||||||
lpkg_t *lpp;
|
|
||||||
int ch;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
setprogname(argv[0]);
|
|
||||||
while ((ch = getopt(argc, argv, Options)) != -1)
|
|
||||||
switch (ch) {
|
|
||||||
case '.': /* for backward compatibility */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'a':
|
|
||||||
Which = WHICH_ALL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
Flags |= SHOW_BUILD_INFO;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'b':
|
|
||||||
Flags |= SHOW_BUILD_VERSION;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
Flags |= SHOW_COMMENT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
Flags |= SHOW_DISPLAY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'd':
|
|
||||||
Flags |= SHOW_DESC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'E':
|
|
||||||
BestCheckPkg = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'e':
|
|
||||||
CheckPkg = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
Flags |= SHOW_PLIST;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'F':
|
|
||||||
File2Pkg = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'I':
|
|
||||||
Flags |= SHOW_INDEX;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'i':
|
|
||||||
Flags |= SHOW_INSTALL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'K':
|
|
||||||
pkgdb_set_dir(optarg, 3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'k':
|
|
||||||
Flags |= SHOW_DEINSTALL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'L':
|
|
||||||
Flags |= SHOW_FILES;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
InfoPrefix = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
Flags |= SHOW_MTREE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'N':
|
|
||||||
Flags |= SHOW_BLD_DEPENDS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
Flags |= SHOW_DEPENDS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
Flags |= SHOW_PREFIX;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Q':
|
|
||||||
Flags |= SHOW_BI_VAR;
|
|
||||||
BuildInfoVariable = optarg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'q':
|
|
||||||
Quiet = TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
Flags |= SHOW_FULL_REQBY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R':
|
|
||||||
Flags |= SHOW_REQBY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
Flags |= SHOW_PKG_SIZE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'S':
|
|
||||||
Flags |= SHOW_ALL_SIZE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'u':
|
|
||||||
Which = WHICH_USER;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
Verbose = TRUE;
|
|
||||||
/* Reasonable definition of 'everything' */
|
|
||||||
Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
|
|
||||||
SHOW_DEINSTALL | SHOW_DISPLAY | SHOW_MTREE |
|
|
||||||
SHOW_REQBY | SHOW_BLD_DEPENDS | SHOW_DEPENDS | SHOW_PKG_SIZE | SHOW_ALL_SIZE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'V':
|
|
||||||
show_version();
|
|
||||||
/* NOTREACHED */
|
|
||||||
|
|
||||||
case 'X':
|
|
||||||
Flags |= SHOW_SUMMARY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
case '?':
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
|
|
||||||
argc -= optind;
|
|
||||||
argv += optind;
|
|
||||||
|
|
||||||
pkg_install_config();
|
|
||||||
|
|
||||||
if (argc == 0 && !Flags && !CheckPkg) {
|
|
||||||
/* No argument or relevant flags specified - assume -I */
|
|
||||||
Flags = SHOW_INDEX;
|
|
||||||
/* assume -a if neither -u nor -a is given */
|
|
||||||
if (Which == WHICH_LIST)
|
|
||||||
Which = WHICH_ALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckPkg != NULL && BestCheckPkg != NULL) {
|
|
||||||
warnx("-E and -e are mutally exlusive");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc != 0 && CheckPkg != NULL) {
|
|
||||||
warnx("can't give any additional arguments to -e");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc != 0 && BestCheckPkg != NULL) {
|
|
||||||
warnx("can't give any additional arguments to -E");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc != 0 && Which != WHICH_LIST) {
|
|
||||||
warnx("can't use both -a/-u and package name");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set some reasonable defaults */
|
|
||||||
if (!Flags)
|
|
||||||
Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY
|
|
||||||
| SHOW_DEPENDS | SHOW_DISPLAY;
|
|
||||||
|
|
||||||
/* -Fe /filename -> change CheckPkg to real packagename */
|
|
||||||
if (CheckPkg) {
|
|
||||||
if (File2Pkg) {
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
if (!pkgdb_open(ReadOnly))
|
|
||||||
err(EXIT_FAILURE, "cannot open pkgdb");
|
|
||||||
|
|
||||||
s = pkgdb_retrieve(CheckPkg);
|
|
||||||
|
|
||||||
if (s == NULL)
|
|
||||||
errx(EXIT_FAILURE, "No matching pkg for %s.", CheckPkg);
|
|
||||||
CheckPkg = xstrdup(s);
|
|
||||||
|
|
||||||
pkgdb_close();
|
|
||||||
}
|
|
||||||
return CheckForPkg(CheckPkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BestCheckPkg)
|
|
||||||
return CheckForBestPkg(BestCheckPkg);
|
|
||||||
|
|
||||||
TAILQ_INIT(&pkgs);
|
|
||||||
|
|
||||||
/* Get all the remaining package names, if any */
|
|
||||||
if (File2Pkg && Which == WHICH_LIST)
|
|
||||||
if (!pkgdb_open(ReadOnly)) {
|
|
||||||
err(EXIT_FAILURE, "cannot open pkgdb");
|
|
||||||
}
|
|
||||||
while (*argv) {
|
|
||||||
/* pkgdb: if -F flag given, don't add pkgnames to the "pkgs"
|
|
||||||
* queue but rather resolve the given filenames to pkgnames
|
|
||||||
* using pkgdb_retrieve, then add them. */
|
|
||||||
if (File2Pkg) {
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
s = pkgdb_retrieve(*argv);
|
|
||||||
|
|
||||||
if (s) {
|
|
||||||
lpp = alloc_lpkg(s);
|
|
||||||
TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
|
|
||||||
} else
|
|
||||||
errx(EXIT_FAILURE, "No matching pkg for %s.", *argv);
|
|
||||||
} else {
|
|
||||||
if (ispkgpattern(*argv)) {
|
|
||||||
switch (add_installed_pkgs_by_pattern(*argv, &pkgs)) {
|
|
||||||
case 0:
|
|
||||||
errx(EXIT_FAILURE, "No matching pkg for %s.", *argv);
|
|
||||||
case -1:
|
|
||||||
errx(EXIT_FAILURE, "Error during search in pkgdb for %s", *argv);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const char *dbdir;
|
|
||||||
|
|
||||||
dbdir = pkgdb_get_dir();
|
|
||||||
if (**argv == '/' && strncmp(*argv, dbdir, strlen(dbdir)) == 0) {
|
|
||||||
*argv += strlen(dbdir) + 1;
|
|
||||||
if ((*argv)[strlen(*argv) - 1] == '/') {
|
|
||||||
(*argv)[strlen(*argv) - 1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lpp = alloc_lpkg(*argv);
|
|
||||||
TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
argv++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (File2Pkg)
|
|
||||||
pkgdb_close();
|
|
||||||
|
|
||||||
/* If no packages, yelp */
|
|
||||||
if (TAILQ_FIRST(&pkgs) == NULL && Which == WHICH_LIST && !CheckPkg)
|
|
||||||
warnx("missing package name(s)"), usage();
|
|
||||||
|
|
||||||
rc = pkg_perform(&pkgs);
|
|
||||||
exit(rc);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
|
@ -1,680 +0,0 @@
|
||||||
/* $NetBSD: perform.c,v 1.61 2010/02/20 04:40:03 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_QUEUE_H
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: perform.c,v 1.61 2010/02/20 04:40:03 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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"
|
|
||||||
|
|
||||||
#if HAVE_SYS_TYPES_H
|
|
||||||
#include <sys/types.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
#include <archive.h>
|
|
||||||
#include <archive_entry.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SIGNAL_H
|
|
||||||
#include <signal.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_DIRENT_H
|
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_CTYPE_H
|
|
||||||
#include <ctype.h>
|
|
||||||
#endif
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define LOAD_CONTENTS (1 << 0)
|
|
||||||
#define LOAD_COMMENT (1 << 1)
|
|
||||||
#define LOAD_DESC (1 << 2)
|
|
||||||
#define LOAD_INSTALL (1 << 3)
|
|
||||||
#define LOAD_DEINSTALL (1 << 4)
|
|
||||||
#define LOAD_DISPLAY (1 << 5)
|
|
||||||
#define LOAD_MTREE (1 << 6)
|
|
||||||
#define LOAD_BUILD_VERSION (1 << 7)
|
|
||||||
#define LOAD_BUILD_INFO (1 << 8)
|
|
||||||
#define LOAD_SIZE_PKG (1 << 9)
|
|
||||||
#define LOAD_SIZE_ALL (1 << 10)
|
|
||||||
#define LOAD_PRESERVE (1 << 11)
|
|
||||||
#define LOAD_VIEWS (1 << 12)
|
|
||||||
#define LOAD_REQUIRED_BY (1 << 13)
|
|
||||||
#define LOAD_INSTALLED_INFO (1 << 14)
|
|
||||||
|
|
||||||
static const struct pkg_meta_desc {
|
|
||||||
size_t entry_offset;
|
|
||||||
const char *entry_filename;
|
|
||||||
int entry_mask;
|
|
||||||
int required_file;
|
|
||||||
} pkg_meta_descriptors[] = {
|
|
||||||
{ offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME,
|
|
||||||
LOAD_CONTENTS, 1},
|
|
||||||
{ offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME,
|
|
||||||
LOAD_COMMENT, 1 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_desc), DESC_FNAME,
|
|
||||||
LOAD_DESC, 1 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_install), INSTALL_FNAME,
|
|
||||||
LOAD_INSTALL, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME,
|
|
||||||
LOAD_DEINSTALL, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME,
|
|
||||||
LOAD_DISPLAY, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME,
|
|
||||||
LOAD_MTREE, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME,
|
|
||||||
LOAD_BUILD_VERSION, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME,
|
|
||||||
LOAD_BUILD_INFO, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME,
|
|
||||||
LOAD_SIZE_PKG, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME,
|
|
||||||
LOAD_SIZE_ALL, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME,
|
|
||||||
LOAD_PRESERVE, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_views), VIEWS_FNAME,
|
|
||||||
LOAD_VIEWS, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME,
|
|
||||||
LOAD_REQUIRED_BY, 0 },
|
|
||||||
{ offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME,
|
|
||||||
LOAD_INSTALLED_INFO, 0 },
|
|
||||||
{ 0, NULL, 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
static int desired_meta_data;
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_pkg_meta(struct pkg_meta *meta)
|
|
||||||
{
|
|
||||||
const struct pkg_meta_desc *descr;
|
|
||||||
|
|
||||||
for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr)
|
|
||||||
free(*(char **)((char *)meta + descr->entry_offset));
|
|
||||||
|
|
||||||
free(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
static struct pkg_meta *
|
|
||||||
read_meta_data_from_archive(struct archive *archive,
|
|
||||||
struct archive_entry *entry)
|
|
||||||
{
|
|
||||||
struct pkg_meta *meta;
|
|
||||||
const char *fname;
|
|
||||||
const struct pkg_meta_desc *descr, *last_descr;
|
|
||||||
char **target;
|
|
||||||
#ifndef __minix
|
|
||||||
int64_t size;
|
|
||||||
#else
|
|
||||||
ssize_t size;
|
|
||||||
#endif
|
|
||||||
int r, found_required;
|
|
||||||
|
|
||||||
found_required = 0;
|
|
||||||
|
|
||||||
meta = xcalloc(1, sizeof(*meta));
|
|
||||||
|
|
||||||
last_descr = 0;
|
|
||||||
if (entry != NULL) {
|
|
||||||
r = ARCHIVE_OK;
|
|
||||||
goto has_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((r = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) {
|
|
||||||
has_entry:
|
|
||||||
fname = archive_entry_pathname(entry);
|
|
||||||
|
|
||||||
for (descr = pkg_meta_descriptors; descr->entry_filename;
|
|
||||||
++descr) {
|
|
||||||
if (strcmp(descr->entry_filename, fname) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (descr->entry_filename == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (descr->required_file)
|
|
||||||
++found_required;
|
|
||||||
|
|
||||||
target = (char **)((char *)meta + descr->entry_offset);
|
|
||||||
if (*target)
|
|
||||||
errx(2, "duplicate entry, package corrupt");
|
|
||||||
if (descr < last_descr)
|
|
||||||
warnx("misordered package, continuing");
|
|
||||||
else
|
|
||||||
last_descr = descr;
|
|
||||||
|
|
||||||
if ((descr->entry_mask & desired_meta_data) == 0) {
|
|
||||||
if (archive_read_data_skip(archive))
|
|
||||||
errx(2, "cannot read package meta data");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = archive_entry_size(entry);
|
|
||||||
/* archive_read_data handles this case using multiple reads
|
|
||||||
* if (size > SSIZE_MAX - 1)
|
|
||||||
* errx(2, "package meta data too large to process");
|
|
||||||
*/
|
|
||||||
*target = xmalloc(size + 1);
|
|
||||||
if (archive_read_data(archive, *target, size) != size)
|
|
||||||
errx(2, "cannot read package meta data");
|
|
||||||
(*target)[size] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
|
|
||||||
if (descr->required_file)
|
|
||||||
--found_required;
|
|
||||||
}
|
|
||||||
|
|
||||||
meta->is_installed = 0;
|
|
||||||
if (found_required != 0 || (r != ARCHIVE_OK && r != ARCHIVE_EOF)) {
|
|
||||||
free_pkg_meta(meta);
|
|
||||||
meta = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return meta;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct pkg_meta *
|
|
||||||
read_meta_data_from_pkgdb(const char *pkg)
|
|
||||||
{
|
|
||||||
struct pkg_meta *meta;
|
|
||||||
const struct pkg_meta_desc *descr;
|
|
||||||
char **target;
|
|
||||||
char *fname;
|
|
||||||
int fd;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
meta = xcalloc(1, sizeof(*meta));
|
|
||||||
|
|
||||||
for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) {
|
|
||||||
if ((descr->entry_mask & desired_meta_data) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkg, descr->entry_filename);
|
|
||||||
fd = open(fname, O_RDONLY, 0);
|
|
||||||
free(fname);
|
|
||||||
if (fd == -1) {
|
|
||||||
if (errno == ENOENT && descr->required_file == 0)
|
|
||||||
continue;
|
|
||||||
err(2, "cannot read meta data file %s of package %s",
|
|
||||||
descr->entry_filename, pkg);
|
|
||||||
}
|
|
||||||
target = (char **)((char *)meta + descr->entry_offset);
|
|
||||||
|
|
||||||
if (fstat(fd, &st) == -1)
|
|
||||||
err(2, "cannot stat meta data");
|
|
||||||
if ((st.st_mode & S_IFMT) != S_IFREG)
|
|
||||||
errx(1, "meta data is not regular file");
|
|
||||||
/*
|
|
||||||
if (st.st_size > SSIZE_MAX - 1)
|
|
||||||
err(2, "meta data file too large to process");
|
|
||||||
*target = xmalloc(st.st_size + 1);
|
|
||||||
if (read(fd, *target, st.st_size) != st.st_size)
|
|
||||||
err(2, "cannot read meta data");
|
|
||||||
*/
|
|
||||||
*target = xmalloc(st.st_size + 1);
|
|
||||||
if (readfile(fd, *target, st.st_size) < 0)
|
|
||||||
err(2, "cannot read meta data");
|
|
||||||
(*target)[st.st_size] = '\0';
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta->is_installed = 1;
|
|
||||||
|
|
||||||
return meta;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
build_full_reqby(lpkg_head_t *reqby, struct pkg_meta *meta, int limit)
|
|
||||||
{
|
|
||||||
char *iter, *eol, *next;
|
|
||||||
lpkg_t *lpp;
|
|
||||||
struct pkg_meta *meta_dep;
|
|
||||||
|
|
||||||
if (limit == 65536)
|
|
||||||
errx(1, "Cycle in the dependency tree, bailing out");
|
|
||||||
|
|
||||||
if (meta->is_installed == 0 || meta->meta_required_by == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (iter = meta->meta_required_by; *iter != '\0'; iter = next) {
|
|
||||||
eol = iter + strcspn(iter, "\n");
|
|
||||||
if (*eol == '\n')
|
|
||||||
next = eol + 1;
|
|
||||||
else
|
|
||||||
next = eol;
|
|
||||||
if (iter == eol)
|
|
||||||
continue;
|
|
||||||
TAILQ_FOREACH(lpp, reqby, lp_link) {
|
|
||||||
if (strlen(lpp->lp_name) + iter != eol)
|
|
||||||
continue;
|
|
||||||
if (memcmp(lpp->lp_name, iter, eol - iter) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (lpp != NULL)
|
|
||||||
continue;
|
|
||||||
*eol = '\0';
|
|
||||||
lpp = alloc_lpkg(iter);
|
|
||||||
if (next != eol)
|
|
||||||
*eol = '\n';
|
|
||||||
|
|
||||||
meta_dep = read_meta_data_from_pkgdb(lpp->lp_name);
|
|
||||||
if (meta_dep == NULL)
|
|
||||||
continue;
|
|
||||||
build_full_reqby(reqby, meta_dep, limit + 1);
|
|
||||||
free_pkg_meta(meta_dep);
|
|
||||||
|
|
||||||
TAILQ_INSERT_HEAD(reqby, lpp, lp_link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static lfile_head_t files;
|
|
||||||
|
|
||||||
static int
|
|
||||||
pkg_do(const char *pkg)
|
|
||||||
{
|
|
||||||
struct pkg_meta *meta;
|
|
||||||
int code = 0;
|
|
||||||
const char *binpkgfile = NULL;
|
|
||||||
char *pkgdir;
|
|
||||||
|
|
||||||
if (IS_URL(pkg) || (fexists(pkg) && isfile(pkg))) {
|
|
||||||
#ifdef BOOTSTRAP
|
|
||||||
errx(2, "Binary packages not supported during bootstrap");
|
|
||||||
#else
|
|
||||||
struct archive *archive;
|
|
||||||
struct archive_entry *entry;
|
|
||||||
char *archive_name, *pkgname;
|
|
||||||
|
|
||||||
archive = open_archive(pkg, &archive_name);
|
|
||||||
if (archive == NULL) {
|
|
||||||
warnx("can't find package `%s', skipped", pkg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pkgname = NULL;
|
|
||||||
entry = NULL;
|
|
||||||
pkg_verify_signature(archive_name, &archive, &entry, &pkgname);
|
|
||||||
if (archive == NULL)
|
|
||||||
return -1;
|
|
||||||
free(pkgname);
|
|
||||||
|
|
||||||
meta = read_meta_data_from_archive(archive, entry);
|
|
||||||
archive_read_finish(archive);
|
|
||||||
if (!IS_URL(pkg))
|
|
||||||
binpkgfile = pkg;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* It's not an uninstalled package, try and find it among the
|
|
||||||
* installed
|
|
||||||
*/
|
|
||||||
pkgdir = pkgdb_pkg_dir(pkg);
|
|
||||||
if (!fexists(pkgdir) || !(isdir(pkgdir) || islinktodir(pkgdir))) {
|
|
||||||
switch (add_installed_pkgs_by_basename(pkg, &pkgs)) {
|
|
||||||
case 1:
|
|
||||||
return 0;
|
|
||||||
case 0:
|
|
||||||
/* No match */
|
|
||||||
warnx("can't find package `%s'", pkg);
|
|
||||||
return 1;
|
|
||||||
case -1:
|
|
||||||
errx(EXIT_FAILURE, "Error during search in pkgdb for %s", pkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(pkgdir);
|
|
||||||
meta = read_meta_data_from_pkgdb(pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meta == NULL) {
|
|
||||||
warnx("invalid package `%s' skipped", pkg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Index is special info type that has to override all others to make
|
|
||||||
* any sense.
|
|
||||||
*/
|
|
||||||
if (Flags & SHOW_INDEX) {
|
|
||||||
char tmp[MaxPathSize];
|
|
||||||
|
|
||||||
(void) snprintf(tmp, sizeof(tmp), "%-19s ", pkg);
|
|
||||||
show_index(meta->meta_comment, tmp);
|
|
||||||
} else if (Flags & SHOW_BI_VAR) {
|
|
||||||
if (strcspn(BuildInfoVariable, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
||||||
== strlen(BuildInfoVariable)) {
|
|
||||||
if (meta->meta_installed_info)
|
|
||||||
show_var(meta->meta_installed_info, BuildInfoVariable);
|
|
||||||
} else {
|
|
||||||
if (meta->meta_build_info)
|
|
||||||
show_var(meta->meta_build_info, BuildInfoVariable);
|
|
||||||
else
|
|
||||||
warnx("Build information missing");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
package_t plist;
|
|
||||||
|
|
||||||
/* Read the contents list */
|
|
||||||
parse_plist(&plist, meta->meta_contents);
|
|
||||||
|
|
||||||
/* Start showing the package contents */
|
|
||||||
if (!Quiet && !(Flags & SHOW_SUMMARY)) {
|
|
||||||
printf("%sInformation for %s:\n\n", InfoPrefix, pkg);
|
|
||||||
if (meta->meta_preserve) {
|
|
||||||
printf("*** PACKAGE MAY NOT BE DELETED ***\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_SUMMARY) {
|
|
||||||
show_summary(meta, &plist, binpkgfile);
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_COMMENT) {
|
|
||||||
show_file(meta->meta_comment, "Comment:\n", TRUE);
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_DEPENDS) {
|
|
||||||
show_depends("Requires:\n", &plist);
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_BLD_DEPENDS) {
|
|
||||||
show_bld_depends("Built using:\n", &plist);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_REQBY) && meta->meta_required_by) {
|
|
||||||
show_file(meta->meta_required_by, "Required by:\n", TRUE);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_FULL_REQBY) && meta->is_installed) {
|
|
||||||
lpkg_head_t reqby;
|
|
||||||
TAILQ_INIT(&reqby);
|
|
||||||
build_full_reqby(&reqby, meta, 0);
|
|
||||||
show_list(&reqby, "Full required by list:\n");
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_DESC) {
|
|
||||||
show_file(meta->meta_desc, "Description:\n", TRUE);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_DISPLAY) && meta->meta_display) {
|
|
||||||
show_file(meta->meta_display, "Install notice:\n",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_PLIST) {
|
|
||||||
show_plist("Packing list:\n", &plist, PLIST_SHOW_ALL);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_INSTALL) && meta->meta_install) {
|
|
||||||
show_file(meta->meta_install, "Install script:\n",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_DEINSTALL) && meta->meta_deinstall) {
|
|
||||||
show_file(meta->meta_deinstall, "De-Install script:\n",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_MTREE) && meta->meta_mtree) {
|
|
||||||
show_file(meta->meta_mtree, "mtree file:\n", TRUE);
|
|
||||||
}
|
|
||||||
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) && meta->meta_build_version) {
|
|
||||||
show_file(meta->meta_build_version, "Build version:\n",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if (Flags & SHOW_BUILD_INFO) {
|
|
||||||
if (meta->meta_build_info) {
|
|
||||||
show_file(meta->meta_build_info, "Build information:\n",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if (meta->meta_installed_info) {
|
|
||||||
show_file(meta->meta_installed_info, "Installed information:\n",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_PKG_SIZE) && meta->meta_size_pkg) {
|
|
||||||
show_file(meta->meta_size_pkg, "Size of this package in bytes: ",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if ((Flags & SHOW_ALL_SIZE) && meta->meta_size_all) {
|
|
||||||
show_file(meta->meta_size_all, "Size in bytes including required pkgs: ",
|
|
||||||
TRUE);
|
|
||||||
}
|
|
||||||
if (!Quiet && !(Flags & SHOW_SUMMARY)) {
|
|
||||||
if (meta->meta_preserve) {
|
|
||||||
printf("*** PACKAGE MAY NOT BE DELETED ***\n\n");
|
|
||||||
}
|
|
||||||
puts(InfoPrefix);
|
|
||||||
}
|
|
||||||
free_plist(&plist);
|
|
||||||
}
|
|
||||||
free_pkg_meta(meta);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct print_matching_arg {
|
|
||||||
const char *pattern;
|
|
||||||
int got_match;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
print_matching_pkg(const char *pkgname, void *cookie)
|
|
||||||
{
|
|
||||||
struct print_matching_arg *arg= cookie;
|
|
||||||
|
|
||||||
if (pkg_match(arg->pattern, pkgname)) {
|
|
||||||
if (!Quiet)
|
|
||||||
puts(pkgname);
|
|
||||||
arg->got_match = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns 0 if at least one package matching pkgname.
|
|
||||||
* Returns 1 otherwise.
|
|
||||||
*
|
|
||||||
* If -q was not specified, print all matching packages to stdout.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
CheckForPkg(const char *pkgname)
|
|
||||||
{
|
|
||||||
struct print_matching_arg arg;
|
|
||||||
|
|
||||||
arg.pattern = pkgname;
|
|
||||||
arg.got_match = 0;
|
|
||||||
|
|
||||||
if (iterate_pkg_db(print_matching_pkg, &arg) == -1) {
|
|
||||||
warnx("cannot iterate pkgdb");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.got_match == 0 && !ispkgpattern(pkgname)) {
|
|
||||||
char *pattern;
|
|
||||||
|
|
||||||
pattern = xasprintf("%s-[0-9]*", pkgname);
|
|
||||||
|
|
||||||
arg.pattern = pattern;
|
|
||||||
arg.got_match = 0;
|
|
||||||
|
|
||||||
if (iterate_pkg_db(print_matching_pkg, &arg) == -1) {
|
|
||||||
free(pattern);
|
|
||||||
warnx("cannot iterate pkgdb");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.got_match)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns 0 if at least one package matching pkgname.
|
|
||||||
* Returns 1 otherwise.
|
|
||||||
*
|
|
||||||
* If -q was not specified, print best match to stdout.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
CheckForBestPkg(const char *pkgname)
|
|
||||||
{
|
|
||||||
char *pattern, *best_match;
|
|
||||||
|
|
||||||
best_match = find_best_matching_installed_pkg(pkgname);
|
|
||||||
if (best_match == NULL) {
|
|
||||||
if (ispkgpattern(pkgname))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
pattern = xasprintf("%s-[0-9]*", pkgname);
|
|
||||||
best_match = find_best_matching_installed_pkg(pattern);
|
|
||||||
free(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best_match == NULL)
|
|
||||||
return 1;
|
|
||||||
if (!Quiet)
|
|
||||||
puts(best_match);
|
|
||||||
free(best_match);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
perform_single_pkg(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
int *err_cnt = cookie;
|
|
||||||
|
|
||||||
if (Which == WHICH_ALL || !is_automatic_installed(pkg))
|
|
||||||
*err_cnt += pkg_do(pkg);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pkg_perform(lpkg_head_t *pkghead)
|
|
||||||
{
|
|
||||||
int err_cnt = 0;
|
|
||||||
|
|
||||||
TAILQ_INIT(&files);
|
|
||||||
|
|
||||||
desired_meta_data = 0;
|
|
||||||
if ((Flags & (SHOW_INDEX | SHOW_BI_VAR)) == 0)
|
|
||||||
desired_meta_data |= LOAD_PRESERVE;
|
|
||||||
if ((Flags & (SHOW_INDEX | SHOW_BI_VAR)) == 0)
|
|
||||||
desired_meta_data |= LOAD_CONTENTS;
|
|
||||||
if (Flags & (SHOW_COMMENT | SHOW_INDEX | SHOW_SUMMARY))
|
|
||||||
desired_meta_data |= LOAD_COMMENT;
|
|
||||||
if (Flags & (SHOW_BI_VAR | SHOW_BUILD_INFO | SHOW_SUMMARY))
|
|
||||||
desired_meta_data |= LOAD_BUILD_INFO | LOAD_INSTALLED_INFO;
|
|
||||||
if (Flags & (SHOW_SUMMARY | SHOW_PKG_SIZE))
|
|
||||||
desired_meta_data |= LOAD_SIZE_PKG;
|
|
||||||
if (Flags & SHOW_ALL_SIZE)
|
|
||||||
desired_meta_data |= LOAD_SIZE_ALL;
|
|
||||||
if (Flags & (SHOW_SUMMARY | SHOW_DESC))
|
|
||||||
desired_meta_data |= LOAD_DESC;
|
|
||||||
if (Flags & (SHOW_REQBY | SHOW_FULL_REQBY))
|
|
||||||
desired_meta_data |= LOAD_REQUIRED_BY;
|
|
||||||
if (Flags & SHOW_DISPLAY)
|
|
||||||
desired_meta_data |= LOAD_DISPLAY;
|
|
||||||
if (Flags & SHOW_INSTALL)
|
|
||||||
desired_meta_data |= LOAD_INSTALL;
|
|
||||||
if (Flags & SHOW_DEINSTALL)
|
|
||||||
desired_meta_data |= LOAD_DEINSTALL;
|
|
||||||
if (Flags & SHOW_MTREE)
|
|
||||||
desired_meta_data |= LOAD_MTREE;
|
|
||||||
if (Flags & SHOW_BUILD_VERSION)
|
|
||||||
desired_meta_data |= LOAD_BUILD_VERSION;
|
|
||||||
|
|
||||||
if (Which != WHICH_LIST) {
|
|
||||||
if (File2Pkg) {
|
|
||||||
/* Show all files with the package they belong to */
|
|
||||||
if (pkgdb_dump() == -1)
|
|
||||||
err_cnt = 1;
|
|
||||||
} else {
|
|
||||||
if (iterate_pkg_db(perform_single_pkg, &err_cnt) == -1)
|
|
||||||
err_cnt = 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Show info on individual pkg(s) */
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
while ((lpp = TAILQ_FIRST(pkghead)) != NULL) {
|
|
||||||
TAILQ_REMOVE(pkghead, lpp, lp_link);
|
|
||||||
err_cnt += pkg_do(lpp->lp_name);
|
|
||||||
free_lpkg(lpp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return err_cnt;
|
|
||||||
}
|
|
|
@ -1,317 +0,0 @@
|
||||||
.\" $NetBSD: pkg_info.1,v 1.30 2010/02/27 21:02:01 wiz Exp $
|
|
||||||
.\"
|
|
||||||
.\" FreeBSD install - a package for the installation and maintenance
|
|
||||||
.\" 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
|
|
||||||
.\"
|
|
||||||
.\"
|
|
||||||
.\" @(#)pkg_info.1
|
|
||||||
.\"
|
|
||||||
.Dd February 27, 2010
|
|
||||||
.Dt PKG_INFO 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pkg_info
|
|
||||||
.Nd a utility for displaying information on software packages
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op Fl BbcDdFfhIikLmNnpqRrSsVvX
|
|
||||||
.Op Fl e Ar package
|
|
||||||
.Op Fl E Ar package
|
|
||||||
.Op Fl K Ar pkg_dbdir
|
|
||||||
.Op Fl l Ar prefix
|
|
||||||
.Ar pkg-name ...
|
|
||||||
.Nm
|
|
||||||
.Op Fl a | Fl u
|
|
||||||
.Op flags
|
|
||||||
.Nm
|
|
||||||
.Op Fl Q Ar variable
|
|
||||||
.Ar pkg-name ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The
|
|
||||||
.Nm
|
|
||||||
command is used to dump out information for packages, which may be either
|
|
||||||
packed up in files or already installed on the system with the
|
|
||||||
.Xr pkg_create 1
|
|
||||||
command.
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
.Ar pkg-name
|
|
||||||
may be the name of an installed package (with our without version), a
|
|
||||||
pattern matching several installed packages (see the
|
|
||||||
.Sx PACKAGE WILDCARDS
|
|
||||||
section for a description of possible patterns),
|
|
||||||
the pathname to a
|
|
||||||
binary package, a filename belonging to an installed
|
|
||||||
package (if
|
|
||||||
.Fl F
|
|
||||||
is also given), or a URL to an ftp-available package.
|
|
||||||
.Pp
|
|
||||||
The following command-line options are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Fl a
|
|
||||||
Show information for all currently installed packages.
|
|
||||||
See also
|
|
||||||
.Fl u .
|
|
||||||
.It Fl B
|
|
||||||
Show some of the important definitions used when building
|
|
||||||
the binary package (the
|
|
||||||
.Dq Build information )
|
|
||||||
for each package.
|
|
||||||
Additionally, any installation information variables
|
|
||||||
(lowercase) can be queried, too.
|
|
||||||
In particular,
|
|
||||||
.Ar automatic
|
|
||||||
tells if a package was installed automatically
|
|
||||||
as a dependency of another package.
|
|
||||||
.It Fl b
|
|
||||||
Show the
|
|
||||||
.Nx
|
|
||||||
RCS Id strings from the files used in the construction
|
|
||||||
of the binary package (the "Build version") for each package.
|
|
||||||
These files are the package Makefile, any patch files, any checksum
|
|
||||||
files, and the packing list file.
|
|
||||||
.It Fl c
|
|
||||||
Show the one-line comment field for each package.
|
|
||||||
.It Fl D
|
|
||||||
Show the install-message file (if any) for each package.
|
|
||||||
.It Fl d
|
|
||||||
Show the long-description field for each package.
|
|
||||||
.It Fl E Ar pkg-name
|
|
||||||
This option
|
|
||||||
allows you to test for the existence of a given package.
|
|
||||||
If a package identified by
|
|
||||||
.Ar pkg-name
|
|
||||||
is currently installed, return code is 0, otherwise 1.
|
|
||||||
The name of the best matching package found installed is printed to
|
|
||||||
stdout unless turned off using the
|
|
||||||
.Fl q
|
|
||||||
option.
|
|
||||||
.Ar pkg-name
|
|
||||||
can contain wildcards (see the
|
|
||||||
.Sx PACKAGE WILDCARDS
|
|
||||||
section below).
|
|
||||||
.It Fl e Ar pkg-name
|
|
||||||
This option
|
|
||||||
allows you to test for the existence of a given package.
|
|
||||||
If a package identified by
|
|
||||||
.Ar pkg-name
|
|
||||||
is currently installed, return code is 0, otherwise 1.
|
|
||||||
The names of any package(s) found installed are printed to
|
|
||||||
stdout unless turned off using the
|
|
||||||
.Fl q
|
|
||||||
option.
|
|
||||||
.Ar pkg-name
|
|
||||||
can contain wildcards (see the
|
|
||||||
.Sx PACKAGE WILDCARDS
|
|
||||||
section below).
|
|
||||||
.It Fl F
|
|
||||||
Interpret any pkg-name given as filename, and translate it to a
|
|
||||||
package name using the package database.
|
|
||||||
This can be used to query information on a per-file basis, e.g. in
|
|
||||||
conjunction with the
|
|
||||||
.Fl e
|
|
||||||
flag to find out which package a file belongs to.
|
|
||||||
.It Fl f
|
|
||||||
Show the packing list instructions for each package.
|
|
||||||
.It Fl I
|
|
||||||
Show the index entry for each package.
|
|
||||||
.It Fl i
|
|
||||||
Show the install script (if any) for each package.
|
|
||||||
.It Fl K Ar pkg_dbdir
|
|
||||||
Override the value of the
|
|
||||||
.Dv PKG_DBDIR
|
|
||||||
configuration option with the value
|
|
||||||
.Ar pkg_dbdir .
|
|
||||||
.It Fl k
|
|
||||||
Show the de-install script (if any) for each package.
|
|
||||||
.It Fl L
|
|
||||||
Show the files within each package.
|
|
||||||
This is different from just viewing the packing list, since full pathnames
|
|
||||||
for everything are generated.
|
|
||||||
Files that were created dynamically during installation of the package
|
|
||||||
are not listed.
|
|
||||||
.It Fl l Ar str
|
|
||||||
Prefix each information category header (see
|
|
||||||
.Fl q )
|
|
||||||
shown with
|
|
||||||
.Ar str .
|
|
||||||
This is primarily of use to front-end programs that want to request a
|
|
||||||
lot of different information fields at once for a package, but don't
|
|
||||||
necessary want the output intermingled in such a way that they can't
|
|
||||||
organize it.
|
|
||||||
This lets you add a special token to the start of each field.
|
|
||||||
.It Fl m
|
|
||||||
Show the mtree file (if any) for each package.
|
|
||||||
.It Fl N
|
|
||||||
Show which packages each package was built with (exact dependencies), if any.
|
|
||||||
.It Fl n
|
|
||||||
Show which packages each package needs (depends upon), if any.
|
|
||||||
.It Fl p
|
|
||||||
Show the installation prefix for each package.
|
|
||||||
.It Fl Q
|
|
||||||
Show the definition of
|
|
||||||
.Ar variable
|
|
||||||
from the build information for each package.
|
|
||||||
An empty string is returned if no such variable definition is found for
|
|
||||||
the package(s).
|
|
||||||
.It Fl q
|
|
||||||
Be
|
|
||||||
.Dq quiet
|
|
||||||
in emitting report headers and such, just dump the
|
|
||||||
raw info (basically, assume a non-human reading).
|
|
||||||
.It Fl R
|
|
||||||
For each package, show the packages that require it.
|
|
||||||
.It Fl r
|
|
||||||
For each package, show the packages that require it.
|
|
||||||
Continue recursively to show all dependents.
|
|
||||||
.It Fl S
|
|
||||||
Show the size of this package and all the packages it requires,
|
|
||||||
in bytes.
|
|
||||||
.It Fl s
|
|
||||||
Show the size of this package in bytes.
|
|
||||||
The size is calculated by adding up the size of each file of the package.
|
|
||||||
.It Fl u
|
|
||||||
Show information for all user-installed packages.
|
|
||||||
Automatically installed packages (as dependencies
|
|
||||||
of other packages) are not displayed.
|
|
||||||
See also
|
|
||||||
.Fl a .
|
|
||||||
.It Fl V
|
|
||||||
Print version number and exit.
|
|
||||||
.It Fl v
|
|
||||||
Turn on verbose output.
|
|
||||||
.It Fl X
|
|
||||||
Print summary information for each package.
|
|
||||||
The summary format is
|
|
||||||
described in
|
|
||||||
.Xr pkg_summary 5 .
|
|
||||||
Its primary use is to contain all information about the contents of a
|
|
||||||
(remote) binary package repository needed by package managing software.
|
|
||||||
.El
|
|
||||||
.Sh TECHNICAL DETAILS
|
|
||||||
Package info is either extracted from package files named on the
|
|
||||||
command line, or from already installed package information
|
|
||||||
in
|
|
||||||
.Pa \*[Lt]PKG_DBDIR\*[Gt]/\*[Lt]pkg-name\*[Gt] .
|
|
||||||
.Pp
|
|
||||||
A filename can be given instead of a (installed) package name to query
|
|
||||||
information on the package this file belongs to.
|
|
||||||
This filename is then resolved to a package name using the package database.
|
|
||||||
For this translation to take place, the
|
|
||||||
.Fl F
|
|
||||||
flag must be given.
|
|
||||||
The filename must be absolute, compare the output of pkg_info
|
|
||||||
.Fl aF .
|
|
||||||
.Sh PACKAGE WILDCARDS
|
|
||||||
In the places where a package name/version is expected, e.g. for the
|
|
||||||
.Fl e
|
|
||||||
switch, several forms can be used.
|
|
||||||
Either use a package name with or without version, or specify a
|
|
||||||
package wildcard that gets matched against all installed packages.
|
|
||||||
.Pp
|
|
||||||
Package wildcards use
|
|
||||||
.Xr fnmatch 3 .
|
|
||||||
In addition,
|
|
||||||
.Xr csh 1
|
|
||||||
style {,} alternates have been implemented.
|
|
||||||
Package version numbers can also be matched in a relational manner
|
|
||||||
using the
|
|
||||||
.Pa \*[Ge] , \*[Le] , \*[Gt] ,
|
|
||||||
and
|
|
||||||
.Pa \*[Lt]
|
|
||||||
operators.
|
|
||||||
For example,
|
|
||||||
.Pa pkg_info -e 'name\*[Ge]1.3'
|
|
||||||
will match versions 1.3 and later of the
|
|
||||||
.Pa name
|
|
||||||
package.
|
|
||||||
Additionally, ranges can be defined by giving a lower bound with
|
|
||||||
\*[Gt] or \*[Ge] and an upper bound with \*[Lt] or \*[Le].
|
|
||||||
The lower bound has to come first.
|
|
||||||
For example,
|
|
||||||
.Pa pkg_info -e 'name\*[Ge]1.3\*[Lt]2.0'
|
|
||||||
will match versions 1.3 (inclusive) to 2.0 (exclusive)
|
|
||||||
of package
|
|
||||||
.Pa name .
|
|
||||||
.Pp
|
|
||||||
The collating sequence of the various package version numbers is
|
|
||||||
unusual, but strives to be consistent.
|
|
||||||
The magic string
|
|
||||||
.Dq alpha
|
|
||||||
equates to
|
|
||||||
.Pa alpha version
|
|
||||||
and sorts before a beta version.
|
|
||||||
The magic string
|
|
||||||
.Dq beta
|
|
||||||
equates to
|
|
||||||
.Pa beta version
|
|
||||||
and sorts before a release candidate.
|
|
||||||
The magic string
|
|
||||||
.Dq rc
|
|
||||||
equates to
|
|
||||||
.Pa release candidate
|
|
||||||
and sorts before a release.
|
|
||||||
The magic string
|
|
||||||
.Dq pre ,
|
|
||||||
short for
|
|
||||||
.Dq pre-release ,
|
|
||||||
is a synonym for
|
|
||||||
.Dq rc .
|
|
||||||
For example,
|
|
||||||
.Pa name-1.3rc3
|
|
||||||
will sort before
|
|
||||||
.Pa name-1.3
|
|
||||||
and after
|
|
||||||
.Pa name-1.2.9 .
|
|
||||||
Similarly
|
|
||||||
.Pa name-1.3alpha2
|
|
||||||
will sort before
|
|
||||||
.Pa name-1.3beta1
|
|
||||||
and they both sort before
|
|
||||||
.Pa name-1.3rc1 .
|
|
||||||
In addition, alphabetic characters sort in the same place as
|
|
||||||
their numeric counterparts, so that
|
|
||||||
.Pa name-1.2e
|
|
||||||
has the same sorting value as
|
|
||||||
.Pa name-1.2.5
|
|
||||||
The magic string
|
|
||||||
.Dq pl
|
|
||||||
equates to a
|
|
||||||
.Pa patch level
|
|
||||||
and has the same value as a dot in the dewey-decimal ordering schemes,
|
|
||||||
as does the underscore
|
|
||||||
.Sq _ .
|
|
||||||
.Sh ENVIRONMENT
|
|
||||||
See
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
for options, that can also be specified using the environment.
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_add 1 ,
|
|
||||||
.Xr pkg_admin 1 ,
|
|
||||||
.Xr pkg_create 1 ,
|
|
||||||
.Xr pkg_delete 1 ,
|
|
||||||
.Xr pkg_install.conf 5
|
|
||||||
.Xr pkgsrc 7
|
|
||||||
.Sh AUTHORS
|
|
||||||
.Bl -tag -width indent -compact
|
|
||||||
.It "Jordan Hubbard"
|
|
||||||
most of the work
|
|
||||||
.It "John Kohl"
|
|
||||||
refined it for
|
|
||||||
.Nx
|
|
||||||
.It "Hubert Feyrer"
|
|
||||||
.Nx
|
|
||||||
wildcard dependency processing, pkgdb, depends displaying,
|
|
||||||
pkg size display etc.
|
|
||||||
.El
|
|
|
@ -1,187 +0,0 @@
|
||||||
PKG_INFO(1) NetBSD General Commands Manual PKG_INFO(1)
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
ppkkgg__iinnffoo -- a utility for displaying information on software packages
|
|
||||||
|
|
||||||
SSYYNNOOPPSSIISS
|
|
||||||
ppkkgg__iinnffoo [--BBbbccDDddFFffhhIIiikkLLmmNNnnppqqrrRRSSssVVvvXX] [--ee _p_a_c_k_a_g_e] [--EE _p_a_c_k_a_g_e]
|
|
||||||
[--KK _p_k_g___d_b_d_i_r] [--ll _p_r_e_f_i_x] _p_k_g_-_n_a_m_e _._._.
|
|
||||||
ppkkgg__iinnffoo [--aa | --uu] [flags]
|
|
||||||
ppkkgg__iinnffoo [--QQ _v_a_r_i_a_b_l_e] _p_k_g_-_n_a_m_e _._._.
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
The ppkkgg__iinnffoo command is used to dump out information for packages, which
|
|
||||||
may be either packed up in files or already installed on the system with
|
|
||||||
the pkg_create(1) command.
|
|
||||||
|
|
||||||
The _p_k_g_-_n_a_m_e may be the name of an installed package (with our without
|
|
||||||
version), a pattern matching several installed packages (see the _P_A_C_K_A_G_E
|
|
||||||
_W_I_L_D_C_A_R_D_S section for a description of possible patterns), the pathname
|
|
||||||
to a binary package, a filename belonging to an installed package (if --FF
|
|
||||||
is also given), or a URL to an ftp-available package.
|
|
||||||
|
|
||||||
The following command-line options are supported:
|
|
||||||
|
|
||||||
--aa Show information for all currently installed packages. See also
|
|
||||||
--uu.
|
|
||||||
|
|
||||||
--BB Show some of the important definitions used when building the
|
|
||||||
binary package (the ``Build information'') for each package.
|
|
||||||
Additionally, any installation information variables (lowercase)
|
|
||||||
can be queried, too. In particular, _a_u_t_o_m_a_t_i_c tells if a package
|
|
||||||
was installed automatically as a dependency of another package.
|
|
||||||
|
|
||||||
--bb Show the NetBSD RCS Id strings from the files used in the con-
|
|
||||||
struction of the binary package (the "Build version") for each
|
|
||||||
package. These files are the package Makefile, any patch files,
|
|
||||||
any checksum files, and the packing list file.
|
|
||||||
|
|
||||||
--cc Show the one-line comment field for each package.
|
|
||||||
|
|
||||||
--DD Show the install-message file (if any) for each package.
|
|
||||||
|
|
||||||
--dd Show the long-description field for each package.
|
|
||||||
|
|
||||||
--EE _p_k_g_-_n_a_m_e
|
|
||||||
This option allows you to test for the existence of a given pack-
|
|
||||||
age. If a package identified by _p_k_g_-_n_a_m_e is currently installed,
|
|
||||||
return code is 0, otherwise 1. The name of the best matching
|
|
||||||
package found installed is printed to stdout unless turned off
|
|
||||||
using the --qq option. _p_k_g_-_n_a_m_e can contain wildcards (see the
|
|
||||||
_P_A_C_K_A_G_E _W_I_L_D_C_A_R_D_S section below).
|
|
||||||
|
|
||||||
--ee _p_k_g_-_n_a_m_e
|
|
||||||
This option allows you to test for the existence of a given pack-
|
|
||||||
age. If a package identified by _p_k_g_-_n_a_m_e is currently installed,
|
|
||||||
return code is 0, otherwise 1. The names of any package(s) found
|
|
||||||
installed are printed to stdout unless turned off using the --qq
|
|
||||||
option. _p_k_g_-_n_a_m_e can contain wildcards (see the _P_A_C_K_A_G_E
|
|
||||||
_W_I_L_D_C_A_R_D_S section below).
|
|
||||||
|
|
||||||
--FF Interpret any pkg-name given as filename, and translate it to a
|
|
||||||
package name using the Package Database. This can be used to
|
|
||||||
query information on a per-file basis, e.g. in conjunction with
|
|
||||||
the --ee flag to find out which package a file belongs to.
|
|
||||||
|
|
||||||
--ff Show the packing list instructions for each package.
|
|
||||||
|
|
||||||
--II Show the index entry for each package.
|
|
||||||
|
|
||||||
--ii Show the install script (if any) for each package.
|
|
||||||
|
|
||||||
--KK _p_k_g___d_b_d_i_r
|
|
||||||
Override the value of the PKG_DBDIR configuration option with the
|
|
||||||
value _p_k_g___d_b_d_i_r.
|
|
||||||
|
|
||||||
--kk Show the de-install script (if any) for each package.
|
|
||||||
|
|
||||||
--LL Show the files within each package. This is different from just
|
|
||||||
viewing the packing list, since full pathnames for everything are
|
|
||||||
generated. Files that were created dynamically during installa-
|
|
||||||
tion of the package are not listed.
|
|
||||||
|
|
||||||
--ll _s_t_r Prefix each information category header (see --qq) shown with _s_t_r.
|
|
||||||
This is primarily of use to front-end programs that want to
|
|
||||||
request a lot of different information fields at once for a pack-
|
|
||||||
age, but don't necessary want the output intermingled in such a
|
|
||||||
way that they can't organize it. This lets you add a special
|
|
||||||
token to the start of each field.
|
|
||||||
|
|
||||||
--mm Show the mtree file (if any) for each package.
|
|
||||||
|
|
||||||
--NN Show which packages each package was built with (exact dependen-
|
|
||||||
cies), if any.
|
|
||||||
|
|
||||||
--nn Show which packages each package needs (depends upon), if any.
|
|
||||||
|
|
||||||
--pp Show the installation prefix for each package.
|
|
||||||
|
|
||||||
--QQ Show the definition of _v_a_r_i_a_b_l_e from the build information for
|
|
||||||
each package. An empty string is returned if no such variable
|
|
||||||
definition is found for the package(s).
|
|
||||||
|
|
||||||
--qq Be ``quiet'' in emitting report headers and such, just dump the
|
|
||||||
raw info (basically, assume a non-human reading).
|
|
||||||
|
|
||||||
--RR For each package, show the packages that require it.
|
|
||||||
|
|
||||||
--rr For each package, show the packages that require it. Continue
|
|
||||||
recursively to show all dependents.
|
|
||||||
|
|
||||||
--SS Show the size of this package and all the packages it requires,
|
|
||||||
in bytes.
|
|
||||||
|
|
||||||
--ss Show the size of this package in bytes. The size is calculated
|
|
||||||
by adding up the size of each file of the package.
|
|
||||||
|
|
||||||
--uu Show information for all user-installed packages. Automatically
|
|
||||||
installed packages (as dependencies of other packages) are not
|
|
||||||
displayed. See also --aa.
|
|
||||||
|
|
||||||
--VV Print version number and exit.
|
|
||||||
|
|
||||||
--vv Turn on verbose output.
|
|
||||||
|
|
||||||
--XX Print summary information for each package. The summary format
|
|
||||||
is described in pkg_summary(5). Its primary use is to contain
|
|
||||||
all information about the contents of a (remote) binary package
|
|
||||||
repository needed by package managing software.
|
|
||||||
|
|
||||||
TTEECCHHNNIICCAALL DDEETTAAIILLSS
|
|
||||||
Package info is either extracted from package files named on the command
|
|
||||||
line, or from already installed package information in
|
|
||||||
_<_P_K_G___D_B_D_I_R_>_/_<_p_k_g_-_n_a_m_e_>.
|
|
||||||
|
|
||||||
A filename can be given instead of a (installed) package name to query
|
|
||||||
information on the package this file belongs to. This filename is then
|
|
||||||
resolved to a package name using the Package Database. For this transla-
|
|
||||||
tion to take place, the --FF flag must be given. The filename must be
|
|
||||||
absolute, compare the output of pkg_info --aaFF.
|
|
||||||
|
|
||||||
PPAACCKKAAGGEE WWIILLDDCCAARRDDSS
|
|
||||||
In the places where a package name/version is expected, e.g. for the --ee
|
|
||||||
switch, several forms can be used. Either use a package name with or
|
|
||||||
without version, or specify a package wildcard that gets matched against
|
|
||||||
all installed packages.
|
|
||||||
|
|
||||||
Package wildcards use fnmatch(3). In addition, csh(1) style {,} alter-
|
|
||||||
nates have been implemented. Package version numbers can also be matched
|
|
||||||
in a relational manner using the _>_=, _<_=, _>, and _< operators. For exam-
|
|
||||||
ple, _p_k_g___i_n_f_o _-_e _'_n_a_m_e_>_=_1_._3_' will match versions 1.3 and later of the
|
|
||||||
_n_a_m_e package. Additionally, ranges can be defined by giving a lower
|
|
||||||
bound with > or >= and an upper bound with < or <=. The lower bound has
|
|
||||||
to come first. For example, _p_k_g___i_n_f_o _-_e _'_n_a_m_e_>_=_1_._3_<_2_._0_' will match ver-
|
|
||||||
sions 1.3 (inclusive) to 2.0 (exclusive) of package _n_a_m_e.
|
|
||||||
|
|
||||||
The collating sequence of the various package version numbers is unusual,
|
|
||||||
but strives to be consistent. The magic string ``alpha'' equates to
|
|
||||||
_a_l_p_h_a _v_e_r_s_i_o_n and sorts before a beta version. The magic string ``beta''
|
|
||||||
equates to _b_e_t_a _v_e_r_s_i_o_n and sorts before a release candidate. The magic
|
|
||||||
string ``rc'' equates to _r_e_l_e_a_s_e _c_a_n_d_i_d_a_t_e and sorts before a release.
|
|
||||||
The magic string ``pre'', short for ``pre-release'', is a synonym for
|
|
||||||
``rc''. For example, _n_a_m_e_-_1_._3_r_c_3 will sort before _n_a_m_e_-_1_._3 and after
|
|
||||||
_n_a_m_e_-_1_._2_._9. Similarly _n_a_m_e_-_1_._3_a_l_p_h_a_2 will sort before _n_a_m_e_-_1_._3_b_e_t_a_1 and
|
|
||||||
they both sort before _n_a_m_e_-_1_._3_r_c_1. In addition, alphabetic characters
|
|
||||||
sort in the same place as their numeric counterparts, so that _n_a_m_e_-_1_._2_e
|
|
||||||
has the same sorting value as _n_a_m_e_-_1_._2_._5 The magic string ``pl'' equates
|
|
||||||
to a _p_a_t_c_h _l_e_v_e_l and has the same value as a dot in the dewey-decimal
|
|
||||||
ordering schemes.
|
|
||||||
|
|
||||||
EENNVVIIRROONNMMEENNTT
|
|
||||||
See pkg_install.conf(5) for options, that can also be specified using the
|
|
||||||
environment.
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
pkg_add(1), pkg_admin(1), pkg_create(1), pkg_delete(1),
|
|
||||||
pkg_install.conf(5) pkgsrc(7)
|
|
||||||
|
|
||||||
AAUUTTHHOORRSS
|
|
||||||
Jordan Hubbard
|
|
||||||
most of the work
|
|
||||||
John Kohl
|
|
||||||
refined it for NetBSD
|
|
||||||
Hubert Feyrer
|
|
||||||
NetBSD wildcard dependency processing, pkgdb, depends displaying,
|
|
||||||
pkg size display etc.
|
|
||||||
|
|
||||||
NetBSD 5.0 January 22, 2010 NetBSD 5.0
|
|
|
@ -1,432 +0,0 @@
|
||||||
/* $NetBSD: show.c,v 1.30 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: show.c,v 1.30 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#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
|
|
||||||
*
|
|
||||||
* Various display routines for the info module.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1999-2008 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Hubert Feyrer <hubert@feyrer.de>.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_PARAM_H
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "defs.h"
|
|
||||||
#include "lib.h"
|
|
||||||
#include "info.h"
|
|
||||||
|
|
||||||
/* Structure to define entries for the "show table" */
|
|
||||||
typedef struct show_t {
|
|
||||||
pl_ent_t sh_type; /* type of entry */
|
|
||||||
const char *sh_quiet; /* message when quiet */
|
|
||||||
const char *sh_verbose; /* message when verbose */
|
|
||||||
} show_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The entries in this table must be ordered the same as
|
|
||||||
* pl_ent_t constants
|
|
||||||
*/
|
|
||||||
static const show_t showv[] = {
|
|
||||||
{PLIST_FILE, "%s", "\tFile: %s"},
|
|
||||||
{PLIST_CWD, "@cwd %s", "\tCWD to: %s"},
|
|
||||||
{PLIST_CMD, "@exec %s", "\tEXEC '%s'"},
|
|
||||||
{PLIST_CHMOD, "@chmod %s", "\tCHMOD to %s"},
|
|
||||||
{PLIST_CHOWN, "@chown %s", "\tCHOWN to %s"},
|
|
||||||
{PLIST_CHGRP, "@chgrp %s", "\tCHGRP to %s"},
|
|
||||||
{PLIST_COMMENT, "@comment %s", "\tComment: %s"},
|
|
||||||
{PLIST_IGNORE, "@ignore", "Ignore next file:"},
|
|
||||||
{PLIST_NAME, "@name %s", "\tPackage name: %s"},
|
|
||||||
{PLIST_UNEXEC, "@unexec %s", "\tUNEXEC '%s'"},
|
|
||||||
{PLIST_SRC, "@src: %s", "\tSRC to: %s"},
|
|
||||||
{PLIST_DISPLAY, "@display %s", "\tInstall message file: %s"},
|
|
||||||
{PLIST_PKGDEP, "@pkgdep %s", "\tPackage depends on: %s"},
|
|
||||||
{PLIST_DIR_RM, "@dirrm %s", "\tObsolete deinstall directory removal hint: %s"},
|
|
||||||
{PLIST_OPTION, "@option %s", "\tPackage has option: %s"},
|
|
||||||
{PLIST_PKGCFL, "@pkgcfl %s", "\tPackage conflicts with: %s"},
|
|
||||||
{PLIST_BLDDEP, "@blddep %s", "\tPackage depends exactly on: %s"},
|
|
||||||
{PLIST_PKGDIR, "@pkgdir %s", "\tManaged directory: %s"},
|
|
||||||
{-1, NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int print_string_as_var(const char *, const char *);
|
|
||||||
|
|
||||||
void
|
|
||||||
show_file(const char *buf, const char *title, Boolean separator)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (!Quiet)
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
|
|
||||||
len = strlen(buf);
|
|
||||||
if (len == 0 || buf[len - 1] != '\n')
|
|
||||||
puts(buf);
|
|
||||||
else
|
|
||||||
fputs(buf, stdout);
|
|
||||||
|
|
||||||
if (!Quiet || separator)
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
show_var(const char *buf, const char *variable)
|
|
||||||
{
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
if (buf == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((value = var_get_memory(buf, variable)) != NULL) {
|
|
||||||
(void) printf("%s\n", value);
|
|
||||||
free(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
show_index(const char *buf, const char *title)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (!Quiet)
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
|
|
||||||
len = strlen(buf);
|
|
||||||
if (len == 0 || buf[len - 1] != '\n')
|
|
||||||
puts(buf);
|
|
||||||
else
|
|
||||||
fputs(buf, stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show a packing list item type. If type is PLIST_SHOW_ALL, show all
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
show_plist(const char *title, package_t *plist, pl_ent_t type)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
Boolean ign;
|
|
||||||
|
|
||||||
if (!Quiet) {
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
}
|
|
||||||
for (ign = FALSE, p = plist->head; p; p = p->next) {
|
|
||||||
if (p->type == type || type == PLIST_SHOW_ALL) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_FILE:
|
|
||||||
printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose, p->name);
|
|
||||||
if (ign) {
|
|
||||||
if (!Quiet) {
|
|
||||||
printf(" (ignored)");
|
|
||||||
}
|
|
||||||
ign = FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PLIST_CHMOD:
|
|
||||||
case PLIST_CHOWN:
|
|
||||||
case PLIST_CHGRP:
|
|
||||||
printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose,
|
|
||||||
p->name ? p->name : "(clear default)");
|
|
||||||
break;
|
|
||||||
case PLIST_IGNORE:
|
|
||||||
printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose);
|
|
||||||
ign = TRUE;
|
|
||||||
break;
|
|
||||||
case PLIST_CWD:
|
|
||||||
case PLIST_CMD:
|
|
||||||
case PLIST_SRC:
|
|
||||||
case PLIST_UNEXEC:
|
|
||||||
case PLIST_COMMENT:
|
|
||||||
case PLIST_NAME:
|
|
||||||
case PLIST_DISPLAY:
|
|
||||||
case PLIST_PKGDEP:
|
|
||||||
case PLIST_DIR_RM:
|
|
||||||
case PLIST_OPTION:
|
|
||||||
case PLIST_PKGCFL:
|
|
||||||
case PLIST_BLDDEP:
|
|
||||||
case PLIST_PKGDIR:
|
|
||||||
printf(Quiet ? showv[p->type].sh_quiet : showv[p->type].sh_verbose, p->name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warnx("unknown command type %d (%s)", p->type, p->name);
|
|
||||||
}
|
|
||||||
(void) fputc('\n', stdout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show all files in the packing list (except ignored ones)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
show_files(const char *title, package_t *plist)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
Boolean ign;
|
|
||||||
const char *dir = ".";
|
|
||||||
|
|
||||||
if (!Quiet) {
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
}
|
|
||||||
for (ign = FALSE, p = plist->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_FILE:
|
|
||||||
if (!ign) {
|
|
||||||
printf("%s%s%s\n", dir,
|
|
||||||
(strcmp(dir, "/") == 0) ? "" : "/", p->name);
|
|
||||||
}
|
|
||||||
ign = FALSE;
|
|
||||||
break;
|
|
||||||
case PLIST_CWD:
|
|
||||||
dir = p->name;
|
|
||||||
break;
|
|
||||||
case PLIST_IGNORE:
|
|
||||||
ign = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show dependencies (packages this pkg requires)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
show_depends(const char *title, package_t *plist)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
int nodepends;
|
|
||||||
|
|
||||||
nodepends = 1;
|
|
||||||
for (p = plist->head; p && nodepends; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_PKGDEP:
|
|
||||||
nodepends = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nodepends)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Quiet) {
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
}
|
|
||||||
for (p = plist->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_PKGDEP:
|
|
||||||
printf("%s\n", p->name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show exact dependencies (packages this pkg was built with)
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
show_bld_depends(const char *title, package_t *plist)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
int nodepends;
|
|
||||||
|
|
||||||
nodepends = 1;
|
|
||||||
for (p = plist->head; p && nodepends; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_BLDDEP:
|
|
||||||
nodepends = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nodepends)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!Quiet) {
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
}
|
|
||||||
for (p = plist->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_BLDDEP:
|
|
||||||
printf("%s\n", p->name);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show entry for pkg_summary.txt file.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
show_summary(struct pkg_meta *meta, package_t *plist, const char *binpkgfile)
|
|
||||||
{
|
|
||||||
static const char *bi_vars[] = {
|
|
||||||
"PKGPATH",
|
|
||||||
"CATEGORIES",
|
|
||||||
"PROVIDES",
|
|
||||||
"REQUIRES",
|
|
||||||
"PKG_OPTIONS",
|
|
||||||
"OPSYS",
|
|
||||||
"OS_VERSION",
|
|
||||||
"MACHINE_ARCH",
|
|
||||||
"LICENSE",
|
|
||||||
"HOMEPAGE",
|
|
||||||
"PKGTOOLS_VERSION",
|
|
||||||
"BUILD_DATE",
|
|
||||||
"PREV_PKGPATH",
|
|
||||||
"SUPERSEDES",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
plist_t *p;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
for (p = plist->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_NAME:
|
|
||||||
printf("PKGNAME=%s\n", p->name);
|
|
||||||
break;
|
|
||||||
case PLIST_PKGDEP:
|
|
||||||
printf("DEPENDS=%s\n", p->name);
|
|
||||||
break;
|
|
||||||
case PLIST_PKGCFL:
|
|
||||||
printf("CONFLICTS=%s\n", p->name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print_string_as_var("COMMENT", meta->meta_comment);
|
|
||||||
print_string_as_var("SIZE_PKG", meta->meta_size_pkg);
|
|
||||||
|
|
||||||
if (meta->meta_build_info)
|
|
||||||
var_copy_list(meta->meta_build_info, bi_vars);
|
|
||||||
else
|
|
||||||
warnx("Build information missing");
|
|
||||||
|
|
||||||
if (binpkgfile != NULL && stat(binpkgfile, &st) == 0) {
|
|
||||||
const char *base;
|
|
||||||
|
|
||||||
base = strrchr(binpkgfile, '/');
|
|
||||||
if (base == NULL)
|
|
||||||
base = binpkgfile;
|
|
||||||
else
|
|
||||||
base++;
|
|
||||||
printf("FILE_NAME=%s\n", base);
|
|
||||||
#ifndef __minix
|
|
||||||
printf("FILE_SIZE=%" MY_PRIu64 "\n", (uint64_t)st.st_size);
|
|
||||||
#else
|
|
||||||
printf("FILE_SIZE=%lu\n", st.st_size);
|
|
||||||
#endif
|
|
||||||
/* XXX: DIGETS */
|
|
||||||
}
|
|
||||||
|
|
||||||
print_string_as_var("DESCRIPTION", meta->meta_desc);
|
|
||||||
putc('\n', stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print the contents of file fname as value of variable var to stdout.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
print_string_as_var(const char *var, const char *str)
|
|
||||||
{
|
|
||||||
const char *eol;
|
|
||||||
|
|
||||||
while ((eol = strchr(str, '\n')) != NULL) {
|
|
||||||
printf("%s=%.*s\n", var, (int)(eol - str), str);
|
|
||||||
str = eol + 1;
|
|
||||||
}
|
|
||||||
if (*str)
|
|
||||||
printf("%s=%s\n", var, str);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
show_list(lpkg_head_t *pkghead, const char *title)
|
|
||||||
{
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
if (!Quiet)
|
|
||||||
printf("%s%s", InfoPrefix, title);
|
|
||||||
|
|
||||||
while ((lpp = TAILQ_FIRST(pkghead)) != NULL) {
|
|
||||||
TAILQ_REMOVE(pkghead, lpp, lp_link);
|
|
||||||
puts(lpp->lp_name);
|
|
||||||
free_lpkg(lpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Quiet)
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
LIB= install
|
|
||||||
SRCS= automatic.c conflicts.c dewey.c fexec.c file.c \
|
|
||||||
gpgsig.c global.c iterate.c license.c lpkg.c opattern.c \
|
|
||||||
parse-config.c pkgdb.c plist.c remove.c \
|
|
||||||
str.c var.c version.c vulnerabilities-file.c xwrapper.c \
|
|
||||||
pkg_io.c pkg_signature.c
|
|
||||||
|
|
||||||
.include "../Makefile.inc"
|
|
||||||
|
|
||||||
LIBISPRIVATE= 1
|
|
||||||
.include <bsd.lib.mk>
|
|
|
@ -1,69 +0,0 @@
|
||||||
# $NetBSD: Makefile.in,v 1.29 2010/04/14 18:24:58 joerg Exp $
|
|
||||||
|
|
||||||
srcdir= @srcdir@
|
|
||||||
|
|
||||||
pkgdbdir= @pkgdbdir@
|
|
||||||
mandir= @mandir@
|
|
||||||
datarootdir= @datarootdir@
|
|
||||||
sysconfdir= @sysconfdir@
|
|
||||||
|
|
||||||
cat5dir= $(mandir)/cat5
|
|
||||||
cat7dir= $(mandir)/cat7
|
|
||||||
man5dir= $(mandir)/man5
|
|
||||||
man7dir= $(mandir)/man7
|
|
||||||
|
|
||||||
BOOTSTRAP= @bootstrap@
|
|
||||||
SSL_SUPPORT= @ssl_support@
|
|
||||||
|
|
||||||
RANLIB= @RANLIB@
|
|
||||||
AR= @AR@
|
|
||||||
CC= @CC@
|
|
||||||
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir)
|
|
||||||
DEFS= @DEFS@ -DDEF_LOG_DIR=\"$(pkgdbdir)\"
|
|
||||||
CFLAGS= @CFLAGS@
|
|
||||||
|
|
||||||
INSTALL= @INSTALL@
|
|
||||||
|
|
||||||
LIB= libinstall.a
|
|
||||||
|
|
||||||
OBJS= automatic.o conflicts.o dewey.o fexec.o file.o \
|
|
||||||
gpgsig.o global.o iterate.o license.o lpkg.o opattern.o \
|
|
||||||
parse-config.o pkgdb.o plist.o remove.o \
|
|
||||||
str.o var.o version.o vulnerabilities-file.o xwrapper.o
|
|
||||||
|
|
||||||
CPPFLAGS+= -DSYSCONFDIR=\"$(sysconfdir)\"
|
|
||||||
|
|
||||||
.if !empty(BOOTSTRAP)
|
|
||||||
CPPFLAGS+= -DBOOTSTRAP
|
|
||||||
.else
|
|
||||||
OBJS+= pkg_io.o pkg_signature.o
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.if !empty(SSL_SUPPORT)
|
|
||||||
CPPFLAGS+= -DHAVE_SSL
|
|
||||||
OBJS+= pkcs7.o
|
|
||||||
.endif
|
|
||||||
|
|
||||||
all: $(LIB)
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
$(LIB): $(OBJS)
|
|
||||||
$(AR) crv $@ $(OBJS)
|
|
||||||
$(RANLIB) $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS) $(LIB)
|
|
||||||
|
|
||||||
install:
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man5dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat5dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man7dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat7dir)
|
|
||||||
$(INSTALL) -m 444 pkg_summary.5 ${DESTDIR}$(man5dir)/pkg_summary.5
|
|
||||||
$(INSTALL) -m 444 pkg_summary.cat ${DESTDIR}$(cat5dir)/pkg_summary.0
|
|
||||||
$(INSTALL) -m 444 pkg_install.conf.5 ${DESTDIR}$(man5dir)/pkg_install.conf.5
|
|
||||||
$(INSTALL) -m 444 pkg_install.conf.cat ${DESTDIR}$(cat5dir)/pkg_install.conf.0
|
|
||||||
$(INSTALL) -m 444 pkgsrc.7 ${DESTDIR}$(man7dir)/pkgsrc.7
|
|
||||||
$(INSTALL) -m 444 pkgsrc.cat ${DESTDIR}$(cat7dir)/pkgsrc.0
|
|
|
@ -1,69 +0,0 @@
|
||||||
# $NetBSD: Makefile.in,v 1.29 2010/04/14 18:24:58 joerg Exp $
|
|
||||||
|
|
||||||
srcdir= .
|
|
||||||
|
|
||||||
pkgdbdir= /usr/db/pkg
|
|
||||||
mandir= ${datarootdir}/man
|
|
||||||
datarootdir= ${prefix}/share
|
|
||||||
sysconfdir= /etc
|
|
||||||
|
|
||||||
cat5dir= $(mandir)/cat5
|
|
||||||
cat7dir= $(mandir)/cat7
|
|
||||||
man5dir= $(mandir)/man5
|
|
||||||
man7dir= $(mandir)/man7
|
|
||||||
|
|
||||||
BOOTSTRAP=
|
|
||||||
SSL_SUPPORT=
|
|
||||||
|
|
||||||
RANLIB= :
|
|
||||||
AR= ar
|
|
||||||
CC= cc
|
|
||||||
CPPFLAGS= -I. -I$(srcdir)
|
|
||||||
DEFS= -DHAVE_CONFIG_H -DDEF_LOG_DIR=\"$(pkgdbdir)\"
|
|
||||||
CFLAGS= -g
|
|
||||||
|
|
||||||
INSTALL= /usr/bin/install -c
|
|
||||||
|
|
||||||
LIB= libinstall.a
|
|
||||||
|
|
||||||
OBJS= automatic.o conflicts.o dewey.o fexec.o file.o \
|
|
||||||
gpgsig.o global.o iterate.o license.o lpkg.o opattern.o \
|
|
||||||
parse-config.o pkgdb.o plist.o remove.o \
|
|
||||||
str.o var.o version.o vulnerabilities-file.o xwrapper.o
|
|
||||||
|
|
||||||
CPPFLAGS+= -DSYSCONFDIR=\"$(sysconfdir)\"
|
|
||||||
|
|
||||||
.if !empty(BOOTSTRAP)
|
|
||||||
CPPFLAGS+= -DBOOTSTRAP
|
|
||||||
.else
|
|
||||||
OBJS+= pkg_io.o pkg_signature.o
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.if !empty(SSL_SUPPORT)
|
|
||||||
CPPFLAGS+= -DHAVE_SSL
|
|
||||||
OBJS+= pkcs7.o
|
|
||||||
.endif
|
|
||||||
|
|
||||||
all: $(LIB)
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $<
|
|
||||||
|
|
||||||
$(LIB): $(OBJS)
|
|
||||||
$(AR) crv $@ $(OBJS)
|
|
||||||
$(RANLIB) $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS) $(LIB)
|
|
||||||
|
|
||||||
install:
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man5dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat5dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man7dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat7dir)
|
|
||||||
$(INSTALL) -m 444 pkg_summary.5 ${DESTDIR}$(man5dir)/pkg_summary.5
|
|
||||||
$(INSTALL) -m 444 pkg_summary.cat ${DESTDIR}$(cat5dir)/pkg_summary.0
|
|
||||||
$(INSTALL) -m 444 pkg_install.conf.5 ${DESTDIR}$(man5dir)/pkg_install.conf.5
|
|
||||||
$(INSTALL) -m 444 pkg_install.conf.cat ${DESTDIR}$(cat5dir)/pkg_install.conf.0
|
|
||||||
$(INSTALL) -m 444 pkgsrc.7 ${DESTDIR}$(man7dir)/pkgsrc.7
|
|
||||||
$(INSTALL) -m 444 pkgsrc.cat ${DESTDIR}$(cat7dir)/pkgsrc.0
|
|
|
@ -1,109 +0,0 @@
|
||||||
/* $NetBSD: automatic.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2005 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Dieter Baron and Thomas Klausner.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* 3. Neither the name of The NetBSD Foundation nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: automatic.c,v 1.5 2009/02/02 12:35:01 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ASSERT_H
|
|
||||||
#include <assert.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
Boolean
|
|
||||||
is_automatic_installed(const char *pkg)
|
|
||||||
{
|
|
||||||
char *filename, *value;
|
|
||||||
Boolean ret;
|
|
||||||
|
|
||||||
assert(pkg[0] != '/');
|
|
||||||
|
|
||||||
filename = pkgdb_pkg_file(pkg, INSTALLED_INFO_FNAME);
|
|
||||||
|
|
||||||
value = var_get(filename, AUTOMATIC_VARNAME);
|
|
||||||
|
|
||||||
if (value && strcasecmp(value, "yes") == 0)
|
|
||||||
ret = TRUE;
|
|
||||||
else
|
|
||||||
ret = FALSE;
|
|
||||||
|
|
||||||
free(value);
|
|
||||||
free(filename);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
mark_as_automatic_installed(const char *pkg, int value)
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
assert(pkg[0] != '/');
|
|
||||||
|
|
||||||
filename = pkgdb_pkg_file(pkg, INSTALLED_INFO_FNAME);
|
|
||||||
|
|
||||||
retval = var_set(filename, AUTOMATIC_VARNAME, value ? "yes" : NULL);
|
|
||||||
|
|
||||||
free(filename);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
|
@ -1,196 +0,0 @@
|
||||||
/* lib/config.h.in. Generated from configure.ac by autoheader. */
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <assert.h> header file. */
|
|
||||||
#undef HAVE_ASSERT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ctype.h> header file. */
|
|
||||||
#undef HAVE_CTYPE_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <dirent.h> header file. */
|
|
||||||
#undef HAVE_DIRENT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <errno.h> header file. */
|
|
||||||
#undef HAVE_ERRNO_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <err.h> header file. */
|
|
||||||
#undef HAVE_ERR_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnctl.h> header file. */
|
|
||||||
#undef HAVE_FNCTL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
|
||||||
#undef HAVE_FNMATCH_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <glob.h> header file. */
|
|
||||||
#undef HAVE_GLOB_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <grp.h> header file. */
|
|
||||||
#undef HAVE_GRP_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
|
||||||
#undef HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `db' library (-ldb). */
|
|
||||||
#undef HAVE_LIBDB
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <limits.h> header file. */
|
|
||||||
#undef HAVE_LIMITS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
|
||||||
#undef HAVE_MEMORY_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <pwd.h> header file. */
|
|
||||||
#undef HAVE_PWD_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <signal.h> header file. */
|
|
||||||
#undef HAVE_SIGNAL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
|
||||||
#undef HAVE_STDARG_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#undef HAVE_STDINT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdio.h> header file. */
|
|
||||||
#undef HAVE_STDIO_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
|
||||||
#undef HAVE_STDLIB_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <strings.h> header file. */
|
|
||||||
#undef HAVE_STRINGS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <string.h> header file. */
|
|
||||||
#undef HAVE_STRING_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/cdefs.h> header file. */
|
|
||||||
#undef HAVE_SYS_CDEFS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/file.h> header file. */
|
|
||||||
#undef HAVE_SYS_FILE_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
|
||||||
#undef HAVE_SYS_IOCTL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
|
||||||
#undef HAVE_SYS_PARAM_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
|
||||||
#undef HAVE_SYS_QUEUE_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
|
||||||
#undef HAVE_SYS_STAT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
|
||||||
#undef HAVE_SYS_TIME_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
|
||||||
#undef HAVE_SYS_TYPES_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
|
||||||
#undef HAVE_SYS_UTSNAME_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <sys/wait.h> header file. */
|
|
||||||
#undef HAVE_SYS_WAIT_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <time.h> header file. */
|
|
||||||
#undef HAVE_TIME_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#undef HAVE_UNISTD_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `vfork' function. */
|
|
||||||
#undef HAVE_VFORK
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <vis.h> header file. */
|
|
||||||
#undef HAVE_VIS_H
|
|
||||||
|
|
||||||
/* Define to 1 if the `z' modifider for printf is missing. */
|
|
||||||
#undef MISSING_SIZE_T_SUPPORT
|
|
||||||
|
|
||||||
/* Defined when PRIu64 is missing or broken */
|
|
||||||
#undef NEED_PRI_MACRO
|
|
||||||
|
|
||||||
/* Defined when to retain only the numeric OS version */
|
|
||||||
#undef NUMERIC_VERSION_ONLY
|
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
|
||||||
#undef PACKAGE_BUGREPORT
|
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
|
||||||
#undef PACKAGE_NAME
|
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
|
||||||
#undef PACKAGE_STRING
|
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
|
||||||
#undef PACKAGE_TARNAME
|
|
||||||
|
|
||||||
/* Define to the home page for this package. */
|
|
||||||
#undef PACKAGE_URL
|
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
|
||||||
#undef PACKAGE_VERSION
|
|
||||||
|
|
||||||
/* The size of `int', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_INT
|
|
||||||
|
|
||||||
/* The size of `long', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_LONG
|
|
||||||
|
|
||||||
/* The size of `long long', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_LONG_LONG
|
|
||||||
|
|
||||||
/* The size of `size_t', as computed by sizeof. */
|
|
||||||
#undef SIZEOF_SIZE_T
|
|
||||||
|
|
||||||
/* Define to 1 if you have the ANSI C header files. */
|
|
||||||
#undef STDC_HEADERS
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
#undef _UINT32_T
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
#undef _UINT64_T
|
|
||||||
|
|
||||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
|
||||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
|
||||||
#define below would cause a syntax error. */
|
|
||||||
#undef _UINT8_T
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
#undef uint16_t
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
#undef uint32_t
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 64 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
#undef uint64_t
|
|
||||||
|
|
||||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
|
||||||
such a type exists and the standard includes do not define it. */
|
|
||||||
#undef uint8_t
|
|
||||||
|
|
||||||
#if !HAVE_VFORK
|
|
||||||
# define vfork fork
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MISSING_SIZE_T_SUPPORT
|
|
||||||
# define PRIzu "zu"
|
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_INT
|
|
||||||
# define PRIzu "u"
|
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_LONG
|
|
||||||
# define PRIzu "lu"
|
|
||||||
#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
|
|
||||||
# define PRIzu "llu"
|
|
||||||
#else
|
|
||||||
# errror "Unknown size_t size"
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,170 +0,0 @@
|
||||||
/* $NetBSD: conflicts.c,v 1.10 2010/01/22 13:30:42 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX: Reading the +CONTENTS files of all installed packages is
|
|
||||||
* rather slow. Since this check is necessary to avoid conflicting
|
|
||||||
* packages, it should not be removed.
|
|
||||||
*
|
|
||||||
* TODO: Put all the information that is currently in the +CONTENTS
|
|
||||||
* files into one large file or another database.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: conflicts.c,v 1.10 2010/01/22 13:30:42 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "dewey.h"
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data structure to keep the intermediate result of the conflict
|
|
||||||
* search. ''pkgname'' is the package in question. The first
|
|
||||||
* installed package that conflicts is filled into
|
|
||||||
* ''conflicting_pkgname''. The pattern that leads to the conflict is
|
|
||||||
* also filled in to help the user in deciding what to do with the
|
|
||||||
* conflict.
|
|
||||||
*/
|
|
||||||
struct package_conflict {
|
|
||||||
const char *pkgname;
|
|
||||||
const char *skip_pkgname;
|
|
||||||
char **conflicting_pkgname;
|
|
||||||
char **conflicting_pattern;
|
|
||||||
};
|
|
||||||
|
|
||||||
static FILE *
|
|
||||||
fopen_contents(const char *pkgname, const char *mode)
|
|
||||||
{
|
|
||||||
char *fname;
|
|
||||||
FILE *f;
|
|
||||||
|
|
||||||
fname = pkgdb_pkg_file(pkgname, CONTENTS_FNAME);
|
|
||||||
f = fopen(fname, mode);
|
|
||||||
if (f == NULL) {
|
|
||||||
err(EXIT_FAILURE, "%s", fname);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
free(fname);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_package_conflict(const char *pkgname, void *v)
|
|
||||||
{
|
|
||||||
struct package_conflict *conflict = v;
|
|
||||||
package_t pkg;
|
|
||||||
plist_t *p;
|
|
||||||
FILE *f;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
if (conflict->skip_pkgname != NULL &&
|
|
||||||
strcmp(conflict->skip_pkgname, pkgname) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
rv = 0;
|
|
||||||
|
|
||||||
f = fopen_contents(pkgname, "r");
|
|
||||||
read_plist(&pkg, f);
|
|
||||||
(void)fclose(f);
|
|
||||||
|
|
||||||
for (p = pkg.head; p; p = p->next) {
|
|
||||||
if (p->type != PLIST_PKGCFL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pkg_match(p->name, conflict->pkgname) == 1) {
|
|
||||||
*(conflict->conflicting_pkgname) = xstrdup(pkgname);
|
|
||||||
*(conflict->conflicting_pattern) = xstrdup(p->name);
|
|
||||||
rv = 1 /* nonzero, stop iterating */;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free_plist(&pkg);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if some installed package has a pkgcfl entry that matches
|
|
||||||
* PkgName. If such an entry is found, the package name is returned in
|
|
||||||
* inst_pkgname, the matching pattern in inst_pattern, and the function
|
|
||||||
* returns a non-zero value. Otherwise, zero is returned and the result
|
|
||||||
* variables are set to NULL.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
some_installed_package_conflicts_with(const char *pkgname,
|
|
||||||
const char *skip_pkgname, char **inst_pkgname, char **inst_pattern)
|
|
||||||
{
|
|
||||||
struct package_conflict cfl;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
cfl.pkgname = pkgname;
|
|
||||||
cfl.skip_pkgname = skip_pkgname;
|
|
||||||
*inst_pkgname = NULL;
|
|
||||||
*inst_pattern = NULL;
|
|
||||||
cfl.conflicting_pkgname = inst_pkgname;
|
|
||||||
cfl.conflicting_pattern = inst_pattern;
|
|
||||||
rv = iterate_pkg_db(check_package_conflict, &cfl);
|
|
||||||
if (rv == -1) {
|
|
||||||
errx(EXIT_FAILURE, "Couldn't read list of installed packages.");
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
return *inst_pkgname != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *pkg, *patt;
|
|
||||||
|
|
||||||
if (some_installed_package_conflicts_with(argv[1], &pkg, &patt))
|
|
||||||
printf("yes: package %s conflicts with %s, pattern %s\n", pkg, argv[1], patt);
|
|
||||||
else
|
|
||||||
printf("no\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,80 +0,0 @@
|
||||||
/* $NetBSD: defs.h,v 1.9 2008/04/18 12:01:46 joerg Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1999-2000 Alistair G. Crooks. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by Alistair G. Crooks.
|
|
||||||
* 4. The name of the author may not be used to endorse or promote
|
|
||||||
* products derived from this software without specific prior written
|
|
||||||
* permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
||||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#ifndef DEFS_H_
|
|
||||||
#define DEFS_H_
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MIN
|
|
||||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MAX
|
|
||||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Some systems such as OpenBSD-3.6 do not provide PRIu64.
|
|
||||||
* Others such as AIX-4.3.2 have a broken PRIu64 which includes
|
|
||||||
* a leading "%".
|
|
||||||
*/
|
|
||||||
#ifndef __minix
|
|
||||||
#ifdef NEED_PRI_MACRO
|
|
||||||
# if SIZEOF_INT == 8
|
|
||||||
# define MY_PRIu64 "u"
|
|
||||||
# elif SIZEOF_LONG == 8
|
|
||||||
# define MY_PRIu64 "lu"
|
|
||||||
# elif SIZEOF_LONG_LONG == 8
|
|
||||||
# define MY_PRIu64 "llu"
|
|
||||||
# else
|
|
||||||
# error "unable to find a suitable PRIu64"
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# define MY_PRIu64 PRIu64
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif /* !DEFS_H_ */
|
|
|
@ -1,326 +0,0 @@
|
||||||
/* $NetBSD: dewey.c,v 1.11 2009/03/06 15:18:42 joerg Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright © 2002 Alistair G. Crooks. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote
|
|
||||||
* products derived from this software without specific prior written
|
|
||||||
* permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
||||||
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_CTYPE_H
|
|
||||||
#include <ctype.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "defs.h"
|
|
||||||
#include "dewey.h"
|
|
||||||
|
|
||||||
#define PKG_PATTERN_MAX 1024
|
|
||||||
|
|
||||||
#ifdef __minix
|
|
||||||
#include <stdint.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* do not modify these values, or things will NOT work */
|
|
||||||
enum {
|
|
||||||
Alpha = -3,
|
|
||||||
Beta = -2,
|
|
||||||
RC = -1,
|
|
||||||
Dot = 0,
|
|
||||||
Patch = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/* this struct defines a version number */
|
|
||||||
typedef struct arr_t {
|
|
||||||
unsigned c; /* # of version numbers */
|
|
||||||
unsigned size; /* size of array */
|
|
||||||
int *v; /* array of decimal numbers */
|
|
||||||
int netbsd; /* any "nb" suffix */
|
|
||||||
} arr_t;
|
|
||||||
|
|
||||||
/* this struct describes a test */
|
|
||||||
typedef struct test_t {
|
|
||||||
const char *s; /* string representation */
|
|
||||||
unsigned len; /* length of string */
|
|
||||||
int t; /* enumerated type of test */
|
|
||||||
} test_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* the tests that are recognised. */
|
|
||||||
const test_t tests[] = {
|
|
||||||
{ "<=", 2, DEWEY_LE },
|
|
||||||
{ "<", 1, DEWEY_LT },
|
|
||||||
{ ">=", 2, DEWEY_GE },
|
|
||||||
{ ">", 1, DEWEY_GT },
|
|
||||||
{ "==", 2, DEWEY_EQ },
|
|
||||||
{ "!=", 2, DEWEY_NE },
|
|
||||||
{ NULL, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
const test_t modifiers[] = {
|
|
||||||
{ "alpha", 5, Alpha },
|
|
||||||
{ "beta", 4, Beta },
|
|
||||||
{ "pre", 3, RC },
|
|
||||||
{ "rc", 2, RC },
|
|
||||||
{ "pl", 2, Dot },
|
|
||||||
{ "_", 1, Dot },
|
|
||||||
{ ".", 1, Dot },
|
|
||||||
{ NULL, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* locate the test in the tests array */
|
|
||||||
int
|
|
||||||
dewey_mktest(int *op, const char *test)
|
|
||||||
{
|
|
||||||
const test_t *tp;
|
|
||||||
|
|
||||||
for (tp = tests ; tp->s ; tp++) {
|
|
||||||
if (strncasecmp(test, tp->s, tp->len) == 0) {
|
|
||||||
*op = tp->t;
|
|
||||||
return tp->len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* make a component of a version number.
|
|
||||||
* '.' encodes as Dot which is '0'
|
|
||||||
* '_' encodes as 'patch level', or 'Dot', which is 0.
|
|
||||||
* 'pl' encodes as 'patch level', or 'Dot', which is 0.
|
|
||||||
* 'alpha' encodes as 'alpha version', or Alpha, which is -3.
|
|
||||||
* 'beta' encodes as 'beta version', or Beta, which is -2.
|
|
||||||
* 'rc' encodes as 'release candidate', or RC, which is -1.
|
|
||||||
* 'nb' encodes as 'netbsd version', which is used after all other tests
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
mkcomponent(arr_t *ap, const char *num)
|
|
||||||
{
|
|
||||||
static const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
|
|
||||||
const test_t *modp;
|
|
||||||
int n;
|
|
||||||
const char *cp;
|
|
||||||
|
|
||||||
if (ap->c == ap->size) {
|
|
||||||
if (ap->size == 0) {
|
|
||||||
ap->size = 62;
|
|
||||||
if ((ap->v = malloc(ap->size * sizeof(int))) == NULL)
|
|
||||||
err(EXIT_FAILURE, "mkver malloc failed");
|
|
||||||
} else {
|
|
||||||
ap->size *= 2;
|
|
||||||
if ((ap->v = realloc(ap->v, ap->size * sizeof(int)))
|
|
||||||
== NULL)
|
|
||||||
err(EXIT_FAILURE, "mkver realloc failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isdigit((unsigned char)*num)) {
|
|
||||||
for (cp = num, n = 0 ; isdigit((unsigned char)*num) ; num++) {
|
|
||||||
n = (n * 10) + (*num - '0');
|
|
||||||
}
|
|
||||||
ap->v[ap->c++] = n;
|
|
||||||
return (int)(num - cp);
|
|
||||||
}
|
|
||||||
for (modp = modifiers ; modp->s ; modp++) {
|
|
||||||
if (strncasecmp(num, modp->s, modp->len) == 0) {
|
|
||||||
ap->v[ap->c++] = modp->t;
|
|
||||||
return modp->len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strncasecmp(num, "nb", 2) == 0) {
|
|
||||||
for (cp = num, num += 2, n = 0 ; isdigit((unsigned char)*num) ; num++) {
|
|
||||||
n = (n * 10) + (*num - '0');
|
|
||||||
}
|
|
||||||
ap->netbsd = n;
|
|
||||||
return (int)(num - cp);
|
|
||||||
}
|
|
||||||
if (isalpha((unsigned char)*num)) {
|
|
||||||
ap->v[ap->c++] = Dot;
|
|
||||||
cp = strchr(alphas, tolower((unsigned char)*num));
|
|
||||||
if (ap->c == ap->size) {
|
|
||||||
ap->size *= 2;
|
|
||||||
if ((ap->v = realloc(ap->v, ap->size * sizeof(int))) == NULL)
|
|
||||||
err(EXIT_FAILURE, "mkver realloc failed");
|
|
||||||
}
|
|
||||||
ap->v[ap->c++] = (int)(cp - alphas) + 1;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make a version number string into an array of comparable ints */
|
|
||||||
static int
|
|
||||||
mkversion(arr_t *ap, const char *num)
|
|
||||||
{
|
|
||||||
ap->c = 0;
|
|
||||||
ap->size = 0;
|
|
||||||
ap->v = NULL;
|
|
||||||
ap->netbsd = 0;
|
|
||||||
|
|
||||||
while (*num) {
|
|
||||||
num += mkcomponent(ap, num);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
freeversion(arr_t *ap)
|
|
||||||
{
|
|
||||||
free(ap->v);
|
|
||||||
ap->v = NULL;
|
|
||||||
ap->c = 0;
|
|
||||||
ap->size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define DIGIT(v, c, n) (((n) < (c)) ? v[n] : 0)
|
|
||||||
|
|
||||||
/* compare the result against the test we were expecting */
|
|
||||||
static int
|
|
||||||
result(int cmp, int tst)
|
|
||||||
{
|
|
||||||
switch(tst) {
|
|
||||||
case DEWEY_LT:
|
|
||||||
return cmp < 0;
|
|
||||||
case DEWEY_LE:
|
|
||||||
return cmp <= 0;
|
|
||||||
case DEWEY_GT:
|
|
||||||
return cmp > 0;
|
|
||||||
case DEWEY_GE:
|
|
||||||
return cmp >= 0;
|
|
||||||
case DEWEY_EQ:
|
|
||||||
return cmp == 0;
|
|
||||||
case DEWEY_NE:
|
|
||||||
return cmp != 0;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* do the test on the 2 vectors */
|
|
||||||
static int
|
|
||||||
vtest(arr_t *lhs, int tst, arr_t *rhs)
|
|
||||||
{
|
|
||||||
int cmp;
|
|
||||||
unsigned int c, i;
|
|
||||||
|
|
||||||
for (i = 0, c = MAX(lhs->c, rhs->c) ; i < c ; i++) {
|
|
||||||
if ((cmp = DIGIT(lhs->v, lhs->c, i) - DIGIT(rhs->v, rhs->c, i)) != 0) {
|
|
||||||
return result(cmp, tst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result(lhs->netbsd - rhs->netbsd, tst);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare two dewey decimal numbers
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
dewey_cmp(const char *lhs, int op, const char *rhs)
|
|
||||||
{
|
|
||||||
arr_t right;
|
|
||||||
arr_t left;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
if (!mkversion(&left, lhs))
|
|
||||||
return 0;
|
|
||||||
if (!mkversion(&right, rhs)) {
|
|
||||||
freeversion(&left);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
retval = vtest(&left, op, &right);
|
|
||||||
freeversion(&left);
|
|
||||||
freeversion(&right);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform dewey match on "pkg" against "pattern".
|
|
||||||
* Return 1 on match, 0 on non-match, -1 on error.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
dewey_match(const char *pattern, const char *pkg)
|
|
||||||
{
|
|
||||||
const char *version;
|
|
||||||
const char *sep, *sep2;
|
|
||||||
int op, op2;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
/* compare names */
|
|
||||||
if ((version=strrchr(pkg, '-')) == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if ((sep = strpbrk(pattern, "<>")) == NULL)
|
|
||||||
return -1;
|
|
||||||
/* compare name lengths */
|
|
||||||
if ((sep-pattern != version-pkg) ||
|
|
||||||
strncmp(pkg, pattern, (size_t)(version-pkg)) != 0)
|
|
||||||
return 0;
|
|
||||||
version++;
|
|
||||||
|
|
||||||
/* extract comparison operator */
|
|
||||||
if ((n = dewey_mktest(&op, sep)) < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* skip operator */
|
|
||||||
sep += n;
|
|
||||||
|
|
||||||
/* if greater than, look for less than */
|
|
||||||
sep2 = NULL;
|
|
||||||
if (op == DEWEY_GT || op == DEWEY_GE) {
|
|
||||||
if ((sep2 = strchr(sep, '<')) != NULL) {
|
|
||||||
if ((n = dewey_mktest(&op2, sep2)) < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* compare upper limit */
|
|
||||||
if (!dewey_cmp(version, op2, sep2+n))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compare only pattern / lower limit */
|
|
||||||
if (sep2) {
|
|
||||||
char ver[PKG_PATTERN_MAX];
|
|
||||||
|
|
||||||
strlcpy(ver, sep, MIN((ssize_t)sizeof(ver), sep2-sep+1));
|
|
||||||
if (dewey_cmp(version, op, ver))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (dewey_cmp(version, op, sep))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
/* $NetBSD: dewey.h,v 1.2 2007/04/16 12:55:35 joerg Exp $ */
|
|
||||||
|
|
||||||
#ifndef _INST_LIB_DEWEY_H_
|
|
||||||
#define _INST_LIB_DEWEY_H_
|
|
||||||
|
|
||||||
int dewey_cmp(const char *, int, const char *);
|
|
||||||
int dewey_match(const char *, const char *);
|
|
||||||
int dewey_mktest(int *, const char *);
|
|
||||||
|
|
||||||
enum {
|
|
||||||
DEWEY_LT,
|
|
||||||
DEWEY_LE,
|
|
||||||
DEWEY_EQ,
|
|
||||||
DEWEY_GE,
|
|
||||||
DEWEY_GT,
|
|
||||||
DEWEY_NE
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _INST_LIB_DEWEY_H_ */
|
|
|
@ -1,171 +0,0 @@
|
||||||
/* $NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Matthias Scheler.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDARG_H
|
|
||||||
#include <stdarg.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: fexec.c,v 1.12 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int vfcexec(const char *, int, const char *, va_list);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* fork, then change current working directory to path and
|
|
||||||
* execute the command and arguments in the argv array.
|
|
||||||
* wait for the command to finish, then return the exit status.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pfcexec(const char *path, const char *file, const char **argv)
|
|
||||||
{
|
|
||||||
pid_t child;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
child = vfork();
|
|
||||||
switch (child) {
|
|
||||||
case 0:
|
|
||||||
if ((path != NULL) && (chdir(path) < 0))
|
|
||||||
_exit(127);
|
|
||||||
|
|
||||||
(void)execvp(file, __UNCONST(argv));
|
|
||||||
_exit(127);
|
|
||||||
/* NOTREACHED */
|
|
||||||
case -1:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (waitpid(child, &status, 0) < 0) {
|
|
||||||
if (errno != EINTR)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WIFEXITED(status))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return WEXITSTATUS(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
vfcexec(const char *path, int skipempty, const char *arg, va_list ap)
|
|
||||||
{
|
|
||||||
const char **argv;
|
|
||||||
size_t argv_size, argc;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
argv_size = 16;
|
|
||||||
argv = xcalloc(argv_size, sizeof(*argv));
|
|
||||||
|
|
||||||
argv[0] = arg;
|
|
||||||
argc = 1;
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (argc == argv_size) {
|
|
||||||
argv_size *= 2;
|
|
||||||
argv = xrealloc(argv, argv_size * sizeof(*argv));
|
|
||||||
}
|
|
||||||
arg = va_arg(ap, const char *);
|
|
||||||
if (skipempty && arg && strlen(arg) == 0)
|
|
||||||
continue;
|
|
||||||
argv[argc++] = arg;
|
|
||||||
} while (arg != NULL);
|
|
||||||
|
|
||||||
retval = pfcexec(path, argv[0], argv);
|
|
||||||
free(argv);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fexec(const char *arg, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
va_start(ap, arg);
|
|
||||||
result = vfcexec(NULL, 0, arg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fexec_skipempty(const char *arg, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
va_start(ap, arg);
|
|
||||||
result = vfcexec(NULL, 1, arg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
fcexec(const char *path, const char *arg, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
va_start(ap, arg);
|
|
||||||
result = vfcexec(path, 0, arg, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,394 +0,0 @@
|
||||||
/* $NetBSD: file.c,v 1.29 2009/09/11 18:00:13 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_PARAM_H
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_QUEUE_H
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: file.c,v 1.29 2009/09/11 18:00:13 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Miscellaneous file access utilities.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#if HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ASSERT_H
|
|
||||||
#include <assert.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_GLOB_H
|
|
||||||
#include <glob.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_PWD_H
|
|
||||||
#include <pwd.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_TIME_H
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Quick check to see if a file (or dir ...) exists
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
fexists(const char *fname)
|
|
||||||
{
|
|
||||||
struct stat dummy;
|
|
||||||
if (!lstat(fname, &dummy))
|
|
||||||
return TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Quick check to see if something is a directory
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
isdir(const char *fname)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
if (lstat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode))
|
|
||||||
return TRUE;
|
|
||||||
else
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if something is a link to a directory
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
islinktodir(const char *fname)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode)) {
|
|
||||||
if (stat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode))
|
|
||||||
return TRUE; /* link to dir! */
|
|
||||||
else
|
|
||||||
return FALSE; /* link to non-dir */
|
|
||||||
} else
|
|
||||||
return FALSE; /* non-link */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if something is a link that points to nonexistant target.
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
isbrokenlink(const char *fname)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode)) {
|
|
||||||
if (stat(fname, &sb) != FAIL)
|
|
||||||
return FALSE; /* link target exists! */
|
|
||||||
else
|
|
||||||
return TRUE; /* link target missing*/
|
|
||||||
} else
|
|
||||||
return FALSE; /* non-link */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check to see if file is a dir, and is empty
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
isemptydir(const char *fname)
|
|
||||||
{
|
|
||||||
if (isdir(fname) || islinktodir(fname)) {
|
|
||||||
DIR *dirp;
|
|
||||||
struct dirent *dp;
|
|
||||||
|
|
||||||
dirp = opendir(fname);
|
|
||||||
if (!dirp)
|
|
||||||
return FALSE; /* no perms, leave it alone */
|
|
||||||
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
|
|
||||||
if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
|
|
||||||
closedir(dirp);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) closedir(dirp);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if something is a regular file
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
isfile(const char *fname)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode))
|
|
||||||
return TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check to see if file is a file and is empty. If nonexistent or not
|
|
||||||
* a file, say "it's empty", otherwise return TRUE if zero sized.
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
isemptyfile(const char *fname)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) {
|
|
||||||
if (sb.st_size != 0)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This struct defines the leading part of a valid URL name */
|
|
||||||
typedef struct url_t {
|
|
||||||
const char *u_s; /* the leading part of the URL */
|
|
||||||
int u_len; /* its length */
|
|
||||||
} url_t;
|
|
||||||
|
|
||||||
/* A table of valid leading strings for URLs */
|
|
||||||
static const url_t urls[] = {
|
|
||||||
{"file://", 7},
|
|
||||||
{"ftp://", 6},
|
|
||||||
{"http://", 7},
|
|
||||||
{NULL, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns length of leading part of any URL from urls table, or -1
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
URLlength(const char *fname)
|
|
||||||
{
|
|
||||||
const url_t *up;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (fname != (char *) NULL) {
|
|
||||||
for (i = 0; isspace((unsigned char) *fname); i++) {
|
|
||||||
fname++;
|
|
||||||
}
|
|
||||||
for (up = urls; up->u_s; up++) {
|
|
||||||
if (strncmp(fname, up->u_s, up->u_len) == 0) {
|
|
||||||
return i + up->u_len; /* ... + sizeof(up->u_s); - HF */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Takes a filename and package name, returning (in "try") the canonical
|
|
||||||
* "preserve" name for it.
|
|
||||||
*/
|
|
||||||
Boolean
|
|
||||||
make_preserve_name(char *try, size_t max, const char *name, const char *file)
|
|
||||||
{
|
|
||||||
size_t len, i;
|
|
||||||
|
|
||||||
if ((len = strlen(file)) == 0)
|
|
||||||
return FALSE;
|
|
||||||
i = len - 1;
|
|
||||||
strncpy(try, file, max);
|
|
||||||
if (try[i] == '/') /* Catch trailing slash early and save checking in the loop */
|
|
||||||
--i;
|
|
||||||
for (; i; i--) {
|
|
||||||
if (try[i] == '/') {
|
|
||||||
try[i + 1] = '.';
|
|
||||||
strncpy(&try[i + 2], &file[i + 1], max - i - 2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!i) {
|
|
||||||
try[0] = '.';
|
|
||||||
strncpy(try + 1, file, max - 1);
|
|
||||||
}
|
|
||||||
/* I should probably be called rude names for these inline assignments */
|
|
||||||
strncat(try, ".", max -= strlen(try));
|
|
||||||
strncat(try, name, max -= strlen(name));
|
|
||||||
strncat(try, ".", max--);
|
|
||||||
strncat(try, "backup", max -= 6);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
remove_files(const char *path, const char *pattern)
|
|
||||||
{
|
|
||||||
char fpath[MaxPathSize];
|
|
||||||
glob_t globbed;
|
|
||||||
int i;
|
|
||||||
size_t j;
|
|
||||||
|
|
||||||
(void) snprintf(fpath, sizeof(fpath), "%s/%s", path, pattern);
|
|
||||||
if ((i=glob(fpath, GLOB_NOSORT, NULL, &globbed)) != 0) {
|
|
||||||
switch(i) {
|
|
||||||
case GLOB_NOMATCH:
|
|
||||||
warn("no files matching ``%s'' found", fpath);
|
|
||||||
break;
|
|
||||||
case GLOB_ABORTED:
|
|
||||||
warn("globbing aborted");
|
|
||||||
break;
|
|
||||||
case GLOB_NOSPACE:
|
|
||||||
warn("out-of-memory during globbing");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warn("unknown error during globbing");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* deleting globbed files */
|
|
||||||
for (j = 0; j < globbed.gl_pathc; j++)
|
|
||||||
if (unlink(globbed.gl_pathv[j]) < 0)
|
|
||||||
warn("can't delete ``%s''", globbed.gl_pathv[j]);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using fmt, replace all instances of:
|
|
||||||
*
|
|
||||||
* %F With the parameter "name"
|
|
||||||
* %D With the parameter "dir"
|
|
||||||
* %B Return the directory part ("base") of %D/%F
|
|
||||||
* %f Return the filename part of %D/%F
|
|
||||||
*
|
|
||||||
* Check that no overflows can occur.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
format_cmd(char *buf, size_t size, const char *fmt, const char *dir, const char *name)
|
|
||||||
{
|
|
||||||
size_t remaining, quoted;
|
|
||||||
char *bufp, *tmp;
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
for (bufp = buf, remaining = size; remaining > 1 && *fmt;) {
|
|
||||||
if (*fmt != '%') {
|
|
||||||
*bufp++ = *fmt++;
|
|
||||||
--remaining;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*++fmt != 'D' && name == NULL) {
|
|
||||||
warnx("no last file available for '%s' command", buf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
switch (*fmt) {
|
|
||||||
case 'F':
|
|
||||||
quoted = shquote(name, bufp, remaining);
|
|
||||||
if (quoted >= remaining) {
|
|
||||||
warnx("overflow during quoting");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bufp += quoted;
|
|
||||||
remaining -= quoted;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
quoted = shquote(dir, bufp, remaining);
|
|
||||||
if (quoted >= remaining) {
|
|
||||||
warnx("overflow during quoting");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bufp += quoted;
|
|
||||||
remaining -= quoted;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
tmp = xasprintf("%s/%s", dir, name);
|
|
||||||
cp = strrchr(tmp, '/');
|
|
||||||
*cp = '\0';
|
|
||||||
quoted = shquote(tmp, bufp, remaining);
|
|
||||||
free(tmp);
|
|
||||||
if (quoted >= remaining) {
|
|
||||||
warnx("overflow during quoting");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bufp += quoted;
|
|
||||||
remaining -= quoted;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'f':
|
|
||||||
tmp = xasprintf("%s/%s", dir, name);
|
|
||||||
cp = strrchr(tmp, '/') + 1;
|
|
||||||
quoted = shquote(cp, bufp, remaining);
|
|
||||||
free(tmp);
|
|
||||||
if (quoted >= remaining) {
|
|
||||||
warnx("overflow during quoting");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
bufp += quoted;
|
|
||||||
remaining -= quoted;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (remaining == 1) {
|
|
||||||
warnx("overflow during quoting");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*bufp++ = '%';
|
|
||||||
*bufp++ = *fmt;
|
|
||||||
remaining -= 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++fmt;
|
|
||||||
}
|
|
||||||
*bufp = '\0';
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
readfile(int fd, char *buf, size_t s)
|
|
||||||
{
|
|
||||||
int ntoread, nread;
|
|
||||||
|
|
||||||
ntoread = s;
|
|
||||||
nread = 0;
|
|
||||||
|
|
||||||
while(ntoread > 0) {
|
|
||||||
if((nread = read(fd, buf, ntoread)) < 0) {
|
|
||||||
return nread;
|
|
||||||
}
|
|
||||||
buf += nread;
|
|
||||||
ntoread -= nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* $NetBSD: global.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: global.c,v 1.5 2009/02/02 12:35:01 joerg Exp $");
|
|
||||||
#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
|
|
||||||
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Semi-convenient place to stick some needed globals.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
/* These are global for all utils */
|
|
||||||
Boolean Verbose = FALSE;
|
|
||||||
Boolean Fake = FALSE;
|
|
||||||
Boolean Force = FALSE;
|
|
|
@ -1,252 +0,0 @@
|
||||||
/* $NetBSD: gpgsig.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: gpgsig.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#if !defined(NETBSD) && !defined(__minix)
|
|
||||||
#include <nbcompat/err.h>
|
|
||||||
#else
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if !defined(NETBSD) && !defined(__minix)
|
|
||||||
#include <nbcompat/stdlib.h>
|
|
||||||
#else
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
verify_signature(const char *input, size_t input_len, const char *keyring,
|
|
||||||
const char *detached_signature)
|
|
||||||
{
|
|
||||||
const char *argv[8], **argvp;
|
|
||||||
pid_t child;
|
|
||||||
int fd[2], status;
|
|
||||||
|
|
||||||
if (pipe(fd) == -1)
|
|
||||||
err(EXIT_FAILURE, "cannot create input pipes");
|
|
||||||
|
|
||||||
child = vfork();
|
|
||||||
if (child == -1)
|
|
||||||
err(EXIT_FAILURE, "cannot fork GPG process");
|
|
||||||
if (child == 0) {
|
|
||||||
close(fd[1]);
|
|
||||||
close(STDIN_FILENO);
|
|
||||||
if (dup2(fd[0], STDIN_FILENO) == -1) {
|
|
||||||
static const char err_msg[] =
|
|
||||||
"cannot redirect stdin of GPG process\n";
|
|
||||||
write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1);
|
|
||||||
_exit(255);
|
|
||||||
}
|
|
||||||
close(fd[0]);
|
|
||||||
argvp = argv;
|
|
||||||
*argvp++ = gpg_cmd;
|
|
||||||
*argvp++ = "--verify";
|
|
||||||
if (keyring != NULL) {
|
|
||||||
*argvp++ = "--no-default-keyring";
|
|
||||||
*argvp++ = "--keyring";
|
|
||||||
*argvp++ = keyring;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (detached_signature != NULL)
|
|
||||||
*argvp++ = detached_signature;
|
|
||||||
*argvp++ = "-";
|
|
||||||
|
|
||||||
*argvp = NULL;
|
|
||||||
|
|
||||||
execvp(gpg_cmd, __UNCONST(argv));
|
|
||||||
_exit(255);
|
|
||||||
}
|
|
||||||
close(fd[0]);
|
|
||||||
if (write(fd[1], input, input_len) != (ssize_t)input_len)
|
|
||||||
errx(EXIT_FAILURE, "Short read from GPG");
|
|
||||||
close(fd[1]);
|
|
||||||
waitpid(child, &status, 0);
|
|
||||||
if (status)
|
|
||||||
errx(EXIT_FAILURE, "GPG could not verify the signature");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
inline_gpg_verify(const char *content, size_t len, const char *keyring)
|
|
||||||
{
|
|
||||||
verify_signature(content, len, keyring, NULL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
detached_gpg_verify(const char *content, size_t len,
|
|
||||||
const char *signature, size_t signature_len, const char *keyring)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
const char *tmpdir;
|
|
||||||
char *tempsig;
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
if (gpg_cmd == NULL) {
|
|
||||||
warnx("GPG variable not set, failing signature check");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmpdir = getenv("TMPDIR")) == NULL)
|
|
||||||
tmpdir = "/tmp";
|
|
||||||
tempsig = xasprintf("%s/pkg_install.XXXXXX", tmpdir);
|
|
||||||
|
|
||||||
fd = mkstemp(tempsig);
|
|
||||||
if (fd == -1) {
|
|
||||||
warnx("Creating temporary file for GPG signature failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (signature_len) {
|
|
||||||
ret = write(fd, signature, signature_len);
|
|
||||||
if (ret == -1)
|
|
||||||
err(EXIT_FAILURE, "Write to GPG failed");
|
|
||||||
if (ret == 0)
|
|
||||||
errx(EXIT_FAILURE, "Short write to GPG");
|
|
||||||
signature_len -= ret;
|
|
||||||
signature += ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
verify_signature(content, len, keyring, tempsig);
|
|
||||||
|
|
||||||
unlink(tempsig);
|
|
||||||
close(fd);
|
|
||||||
free(tempsig);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
detached_gpg_sign(const char *content, size_t len, char **sig, size_t *sig_len,
|
|
||||||
const char *keyring, const char *user)
|
|
||||||
{
|
|
||||||
const char *argv[12], **argvp;
|
|
||||||
pid_t child;
|
|
||||||
int fd_in[2], fd_out[2], status;
|
|
||||||
size_t allocated;
|
|
||||||
ssize_t ret;
|
|
||||||
|
|
||||||
if (gpg_cmd == NULL)
|
|
||||||
errx(EXIT_FAILURE, "GPG variable not set");
|
|
||||||
|
|
||||||
if (pipe(fd_in) == -1)
|
|
||||||
err(EXIT_FAILURE, "cannot create input pipes");
|
|
||||||
if (pipe(fd_out) == -1)
|
|
||||||
err(EXIT_FAILURE, "cannot create output pipes");
|
|
||||||
|
|
||||||
child = fork();
|
|
||||||
if (child == -1)
|
|
||||||
err(EXIT_FAILURE, "cannot fork GPG process");
|
|
||||||
if (child == 0) {
|
|
||||||
close(fd_in[1]);
|
|
||||||
close(STDIN_FILENO);
|
|
||||||
if (dup2(fd_in[0], STDIN_FILENO) == -1) {
|
|
||||||
static const char err_msg[] =
|
|
||||||
"cannot redirect stdin of GPG process\n";
|
|
||||||
write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1);
|
|
||||||
_exit(255);
|
|
||||||
}
|
|
||||||
close(fd_in[0]);
|
|
||||||
|
|
||||||
close(fd_out[0]);
|
|
||||||
close(STDOUT_FILENO);
|
|
||||||
if (dup2(fd_out[1], STDOUT_FILENO) == -1) {
|
|
||||||
static const char err_msg[] =
|
|
||||||
"cannot redirect stdout of GPG process\n";
|
|
||||||
write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1);
|
|
||||||
_exit(255);
|
|
||||||
}
|
|
||||||
close(fd_out[1]);
|
|
||||||
|
|
||||||
argvp = argv;
|
|
||||||
*argvp++ = gpg_cmd;
|
|
||||||
*argvp++ = "--detach-sign";
|
|
||||||
*argvp++ = "--armor";
|
|
||||||
*argvp++ = "--output";
|
|
||||||
*argvp++ = "-";
|
|
||||||
if (user != NULL) {
|
|
||||||
*argvp++ = "--local-user";
|
|
||||||
*argvp++ = user;
|
|
||||||
}
|
|
||||||
if (keyring != NULL) {
|
|
||||||
*argvp++ = "--no-default-keyring";
|
|
||||||
*argvp++ = "--secret-keyring";
|
|
||||||
*argvp++ = keyring;
|
|
||||||
}
|
|
||||||
|
|
||||||
*argvp++ = "-";
|
|
||||||
*argvp = NULL;
|
|
||||||
|
|
||||||
execvp(gpg_cmd, __UNCONST(argv));
|
|
||||||
_exit(255);
|
|
||||||
}
|
|
||||||
close(fd_in[0]);
|
|
||||||
if (write(fd_in[1], content, len) != (ssize_t)len)
|
|
||||||
errx(EXIT_FAILURE, "Short read from GPG");
|
|
||||||
close(fd_in[1]);
|
|
||||||
|
|
||||||
allocated = 1024;
|
|
||||||
*sig = xmalloc(allocated);
|
|
||||||
*sig_len = 0;
|
|
||||||
|
|
||||||
close(fd_out[1]);
|
|
||||||
|
|
||||||
while ((ret = read(fd_out[0], *sig + *sig_len,
|
|
||||||
allocated - *sig_len)) > 0) {
|
|
||||||
*sig_len += ret;
|
|
||||||
if (*sig_len == allocated) {
|
|
||||||
allocated *= 2;
|
|
||||||
*sig = xrealloc(*sig, allocated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd_out[0]);
|
|
||||||
|
|
||||||
waitpid(child, &status, 0);
|
|
||||||
if (status)
|
|
||||||
errx(EXIT_FAILURE, "GPG could not create signature");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,487 +0,0 @@
|
||||||
/* $NetBSD: iterate.c,v 1.8 2010/01/22 13:30:42 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic iteration function:
|
|
||||||
* - get new entries from srciter, stop on NULL
|
|
||||||
* - call matchiter for those entries, stop on non-null return value.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
iterate_pkg_generic_src(int (*matchiter)(const char *, void *),
|
|
||||||
void *match_cookie, const char *(*srciter)(void *), void *src_cookie)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
const char *entry;
|
|
||||||
|
|
||||||
retval = 0;
|
|
||||||
|
|
||||||
while ((entry = (*srciter)(src_cookie)) != NULL) {
|
|
||||||
if ((retval = (*matchiter)(entry, match_cookie)) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pkg_dir_iter_arg {
|
|
||||||
DIR *dirp;
|
|
||||||
int filter_suffix;
|
|
||||||
int allow_nonfiles;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
pkg_dir_iter(void *cookie)
|
|
||||||
{
|
|
||||||
struct pkg_dir_iter_arg *arg = cookie;
|
|
||||||
struct dirent *dp;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
while ((dp = readdir(arg->dirp)) != NULL) {
|
|
||||||
#if defined(DT_UNKNOWN) && defined(DT_DIR)
|
|
||||||
if (arg->allow_nonfiles == 0 &&
|
|
||||||
dp->d_type != DT_UNKNOWN && dp->d_type != DT_REG)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
len = strlen(dp->d_name);
|
|
||||||
/* .tbz or .tgz suffix length + some prefix*/
|
|
||||||
if (len < 5)
|
|
||||||
continue;
|
|
||||||
if (arg->filter_suffix == 0 ||
|
|
||||||
memcmp(dp->d_name + len - 4, ".tgz", 4) == 0 ||
|
|
||||||
memcmp(dp->d_name + len - 4, ".tbz", 4) == 0)
|
|
||||||
return dp->d_name;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call matchiter for every package in the directory.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
iterate_local_pkg_dir(const char *dir, int filter_suffix, int allow_nonfiles,
|
|
||||||
int (*matchiter)(const char *, void *), void *cookie)
|
|
||||||
{
|
|
||||||
struct pkg_dir_iter_arg arg;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
if ((arg.dirp = opendir(dir)) == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
arg.filter_suffix = filter_suffix;
|
|
||||||
arg.allow_nonfiles = allow_nonfiles;
|
|
||||||
retval = iterate_pkg_generic_src(matchiter, cookie, pkg_dir_iter, &arg);
|
|
||||||
|
|
||||||
if (closedir(arg.dirp) == -1)
|
|
||||||
return -1;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
pkg_db_iter(void *cookie)
|
|
||||||
{
|
|
||||||
DIR *dirp = cookie;
|
|
||||||
struct dirent *dp;
|
|
||||||
|
|
||||||
while ((dp = readdir(dirp)) != NULL) {
|
|
||||||
if (strcmp(dp->d_name, ".") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(dp->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(dp->d_name, "pkgdb.byfile.db") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(dp->d_name, ".cookie") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(dp->d_name, "pkg-vulnerabilities") == 0)
|
|
||||||
continue;
|
|
||||||
#if defined(DT_UNKNOWN) && defined(DT_DIR)
|
|
||||||
if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_DIR)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
return dp->d_name;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call matchiter for every installed package.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
iterate_pkg_db(int (*matchiter)(const char *, void *), void *cookie)
|
|
||||||
{
|
|
||||||
DIR *dirp;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
if ((dirp = opendir(pkgdb_get_dir())) == NULL) {
|
|
||||||
if (errno == ENOENT)
|
|
||||||
return 0; /* No pkgdb directory == empty pkgdb */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = iterate_pkg_generic_src(matchiter, cookie, pkg_db_iter, dirp);
|
|
||||||
|
|
||||||
if (closedir(dirp) == -1)
|
|
||||||
return -1;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_by_basename(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
const char *target = cookie;
|
|
||||||
const char *pkg_version;
|
|
||||||
|
|
||||||
if ((pkg_version = strrchr(pkg, '-')) == NULL) {
|
|
||||||
warnx("Entry %s in pkgdb is not a valid package name", pkg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (strncmp(pkg, target, pkg_version - pkg) == 0 &&
|
|
||||||
pkg + strlen(target) == pkg_version)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_by_pattern(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
const char *pattern = cookie;
|
|
||||||
|
|
||||||
return pkg_match(pattern, pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct add_matching_arg {
|
|
||||||
lpkg_head_t *pkghead;
|
|
||||||
int got_match;
|
|
||||||
int (*match_fn)(const char *pkg, void *cookie);
|
|
||||||
void *cookie;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_and_add(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
struct add_matching_arg *arg = cookie;
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
if ((*arg->match_fn)(pkg, arg->cookie) == 1) {
|
|
||||||
arg->got_match = 1;
|
|
||||||
|
|
||||||
lpp = alloc_lpkg(pkg);
|
|
||||||
TAILQ_INSERT_TAIL(arg->pkghead, lpp, lp_link);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find all installed packages with the given basename and add them
|
|
||||||
* to pkghead.
|
|
||||||
* Returns -1 on error, 0 if no match was found and 1 otherwise.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
add_installed_pkgs_by_basename(const char *pkgbase, lpkg_head_t *pkghead)
|
|
||||||
{
|
|
||||||
struct add_matching_arg arg;
|
|
||||||
|
|
||||||
arg.pkghead = pkghead;
|
|
||||||
arg.got_match = 0;
|
|
||||||
arg.match_fn = match_by_basename;
|
|
||||||
arg.cookie = __UNCONST(pkgbase);
|
|
||||||
|
|
||||||
if (iterate_pkg_db(match_and_add, &arg) == -1) {
|
|
||||||
warnx("could not process pkgdb");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return arg.got_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Match all installed packages against pattern, add the matches to pkghead.
|
|
||||||
* Returns -1 on error, 0 if no match was found and 1 otherwise.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
add_installed_pkgs_by_pattern(const char *pattern, lpkg_head_t *pkghead)
|
|
||||||
{
|
|
||||||
struct add_matching_arg arg;
|
|
||||||
|
|
||||||
arg.pkghead = pkghead;
|
|
||||||
arg.got_match = 0;
|
|
||||||
arg.match_fn = match_by_pattern;
|
|
||||||
arg.cookie = __UNCONST(pattern);
|
|
||||||
|
|
||||||
if (iterate_pkg_db(match_and_add, &arg) == -1) {
|
|
||||||
warnx("could not process pkgdb");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return arg.got_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct best_installed_match_arg {
|
|
||||||
const char *pattern;
|
|
||||||
char *best_current_match;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_best_installed(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
struct best_installed_match_arg *arg = cookie;
|
|
||||||
|
|
||||||
switch (pkg_order(arg->pattern, pkg, arg->best_current_match)) {
|
|
||||||
case 0:
|
|
||||||
case 2:
|
|
||||||
/*
|
|
||||||
* Either current package doesn't match or
|
|
||||||
* the older match is better. Nothing to do.
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
/* Current package is better, remember it. */
|
|
||||||
free(arg->best_current_match);
|
|
||||||
arg->best_current_match = xstrdup(pkg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a copy of the name of best matching package.
|
|
||||||
* If no package matched the pattern or an error occured, return NULL.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
find_best_matching_installed_pkg(const char *pattern)
|
|
||||||
{
|
|
||||||
struct best_installed_match_arg arg;
|
|
||||||
|
|
||||||
arg.pattern = pattern;
|
|
||||||
arg.best_current_match = NULL;
|
|
||||||
|
|
||||||
if (iterate_pkg_db(match_best_installed, &arg) == -1) {
|
|
||||||
warnx("could not process pkgdb");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return arg.best_current_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct call_matching_arg {
|
|
||||||
const char *pattern;
|
|
||||||
int (*call_fn)(const char *pkg, void *cookie);
|
|
||||||
void *cookie;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_and_call(const char *pkg, void *cookie)
|
|
||||||
{
|
|
||||||
struct call_matching_arg *arg = cookie;
|
|
||||||
|
|
||||||
if (pkg_match(arg->pattern, pkg) == 1) {
|
|
||||||
return (*arg->call_fn)(pkg, arg->cookie);
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find all packages that match the given pattern and call the function
|
|
||||||
* for each of them. Iteration stops if the callback return non-0.
|
|
||||||
* Returns -1 on error, 0 if the iteration finished or whatever the
|
|
||||||
* callback returned otherwise.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
match_installed_pkgs(const char *pattern, int (*cb)(const char *, void *),
|
|
||||||
void *cookie)
|
|
||||||
{
|
|
||||||
struct call_matching_arg arg;
|
|
||||||
|
|
||||||
arg.pattern = pattern;
|
|
||||||
arg.call_fn = cb;
|
|
||||||
arg.cookie = cookie;
|
|
||||||
|
|
||||||
return iterate_pkg_db(match_and_call, &arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct best_file_match_arg {
|
|
||||||
const char *pattern;
|
|
||||||
char *best_current_match_filtered;
|
|
||||||
char *best_current_match;
|
|
||||||
int filter_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_best_file(const char *filename, void *cookie)
|
|
||||||
{
|
|
||||||
struct best_file_match_arg *arg = cookie;
|
|
||||||
const char *active_filename;
|
|
||||||
char *filtered_filename;
|
|
||||||
|
|
||||||
if (arg->filter_suffix) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(filename);
|
|
||||||
if (len < 5 ||
|
|
||||||
(memcmp(filename + len - 4, ".tgz", 4) != 0 &&
|
|
||||||
memcmp(filename + len - 4, ".tbz", 4) != 0)) {
|
|
||||||
warnx("filename %s does not contain a recognized suffix", filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
filtered_filename = xmalloc(len - 4 + 1);
|
|
||||||
memcpy(filtered_filename, filename, len - 4);
|
|
||||||
filtered_filename[len - 4] = '\0';
|
|
||||||
active_filename = filtered_filename;
|
|
||||||
} else {
|
|
||||||
filtered_filename = NULL;
|
|
||||||
active_filename = filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pkg_order(arg->pattern, active_filename, arg->best_current_match_filtered)) {
|
|
||||||
case 0:
|
|
||||||
case 2:
|
|
||||||
/*
|
|
||||||
* Either current package doesn't match or
|
|
||||||
* the older match is better. Nothing to do.
|
|
||||||
*/
|
|
||||||
free(filtered_filename);
|
|
||||||
return 0;
|
|
||||||
case 1:
|
|
||||||
/* Current package is better, remember it. */
|
|
||||||
free(arg->best_current_match);
|
|
||||||
free(arg->best_current_match_filtered);
|
|
||||||
arg->best_current_match = xstrdup(filename);
|
|
||||||
if (filtered_filename != NULL)
|
|
||||||
arg->best_current_match_filtered = filtered_filename;
|
|
||||||
else
|
|
||||||
arg->best_current_match_filtered = xstrdup(active_filename);
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
errx(EXIT_FAILURE, "Invalid error from pkg_order");
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns a copy of the name of best matching file.
|
|
||||||
* If no package matched the pattern or an error occured, return NULL.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
find_best_matching_file(const char *dir, const char *pattern, int filter_suffix, int allow_nonfiles)
|
|
||||||
{
|
|
||||||
struct best_file_match_arg arg;
|
|
||||||
|
|
||||||
arg.filter_suffix = filter_suffix;
|
|
||||||
arg.pattern = pattern;
|
|
||||||
arg.best_current_match = NULL;
|
|
||||||
arg.best_current_match_filtered = NULL;
|
|
||||||
|
|
||||||
if (iterate_local_pkg_dir(dir, filter_suffix, allow_nonfiles, match_best_file, &arg) == -1) {
|
|
||||||
warnx("could not process directory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
free(arg.best_current_match_filtered);
|
|
||||||
|
|
||||||
return arg.best_current_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct call_matching_file_arg {
|
|
||||||
const char *pattern;
|
|
||||||
int (*call_fn)(const char *pkg, void *cookie);
|
|
||||||
void *cookie;
|
|
||||||
int filter_suffix;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
match_file_and_call(const char *filename, void *cookie)
|
|
||||||
{
|
|
||||||
struct call_matching_file_arg *arg = cookie;
|
|
||||||
const char *active_filename;
|
|
||||||
char *filtered_filename;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (arg->filter_suffix) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(filename);
|
|
||||||
if (len < 5 ||
|
|
||||||
(memcmp(filename + len - 4, ".tgz", 4) != 0 &&
|
|
||||||
memcmp(filename + len - 4, ".tbz", 4) != 0)) {
|
|
||||||
warnx("filename %s does not contain a recognized suffix", filename);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
filtered_filename = xmalloc(len - 4 + 1);
|
|
||||||
memcpy(filtered_filename, filename, len - 4);
|
|
||||||
filtered_filename[len - 4] = '\0';
|
|
||||||
active_filename = filtered_filename;
|
|
||||||
} else {
|
|
||||||
filtered_filename = NULL;
|
|
||||||
active_filename = filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pkg_match(arg->pattern, active_filename);
|
|
||||||
free(filtered_filename);
|
|
||||||
|
|
||||||
if (ret == 1)
|
|
||||||
return (*arg->call_fn)(filename, arg->cookie);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find all packages that match the given pattern and call the function
|
|
||||||
* for each of them. Iteration stops if the callback return non-0.
|
|
||||||
* Returns -1 on error, 0 if the iteration finished or whatever the
|
|
||||||
* callback returned otherwise.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
match_local_files(const char *dir, int filter_suffix, int allow_nonfiles, const char *pattern,
|
|
||||||
int (*cb)(const char *, void *), void *cookie)
|
|
||||||
{
|
|
||||||
struct call_matching_file_arg arg;
|
|
||||||
|
|
||||||
arg.pattern = pattern;
|
|
||||||
arg.call_fn = cb;
|
|
||||||
arg.cookie = cookie;
|
|
||||||
arg.filter_suffix = filter_suffix;
|
|
||||||
|
|
||||||
return iterate_local_pkg_dir(dir, filter_suffix, allow_nonfiles, match_file_and_call, &arg);
|
|
||||||
}
|
|
|
@ -1,460 +0,0 @@
|
||||||
/* $NetBSD: lib.h,v 1.64 2010/06/16 23:02:49 joerg Exp $ */
|
|
||||||
|
|
||||||
/* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Include and define various things wanted by the library routines.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INST_LIB_LIB_H_
|
|
||||||
#define _INST_LIB_LIB_H_
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_PARAM_H
|
|
||||||
#include <sys/param.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_FILE_H
|
|
||||||
#include <sys/file.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_QUEUE_H
|
|
||||||
#include <sys/queue.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_CTYPE_H
|
|
||||||
#include <ctype.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_DIRENT_H
|
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDLIB_H
|
|
||||||
#include <stdlib.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDARG_H
|
|
||||||
#include <stdarg.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Macros */
|
|
||||||
#ifndef __UNCONST
|
|
||||||
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SUCCESS (0)
|
|
||||||
#define FAIL (-1)
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE (1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPSYS_NAME
|
|
||||||
#define OPSYS_NAME "NetBSD"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef DEF_UMASK
|
|
||||||
#define DEF_UMASK 022
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
|
||||||
# ifdef MAXPATHLEN
|
|
||||||
# define PATH_MAX MAXPATHLEN
|
|
||||||
# else
|
|
||||||
# define PATH_MAX 1024
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum {
|
|
||||||
MaxPathSize = PATH_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The names of our "special" files */
|
|
||||||
#define CONTENTS_FNAME "+CONTENTS"
|
|
||||||
#define COMMENT_FNAME "+COMMENT"
|
|
||||||
#define DESC_FNAME "+DESC"
|
|
||||||
#define INSTALL_FNAME "+INSTALL"
|
|
||||||
#define DEINSTALL_FNAME "+DEINSTALL"
|
|
||||||
#define REQUIRED_BY_FNAME "+REQUIRED_BY"
|
|
||||||
#define REQUIRED_BY_FNAME_TMP "+REQUIRED_BY.tmp"
|
|
||||||
#define DISPLAY_FNAME "+DISPLAY"
|
|
||||||
#define MTREE_FNAME "+MTREE_DIRS"
|
|
||||||
#define BUILD_VERSION_FNAME "+BUILD_VERSION"
|
|
||||||
#define BUILD_INFO_FNAME "+BUILD_INFO"
|
|
||||||
#define INSTALLED_INFO_FNAME "+INSTALLED_INFO"
|
|
||||||
#define SIZE_PKG_FNAME "+SIZE_PKG"
|
|
||||||
#define SIZE_ALL_FNAME "+SIZE_ALL"
|
|
||||||
#define PRESERVE_FNAME "+PRESERVE"
|
|
||||||
#define VIEWS_FNAME "+VIEWS"
|
|
||||||
#define VIEWS_FNAME_TMP "+VIEWS.tmp"
|
|
||||||
#define DEPOT_FNAME "+DEPOT"
|
|
||||||
|
|
||||||
/* The names of special variables */
|
|
||||||
#define AUTOMATIC_VARNAME "automatic"
|
|
||||||
|
|
||||||
/* Prefix for extended PLIST cmd */
|
|
||||||
#define CMD_CHAR '@'
|
|
||||||
|
|
||||||
/* The name of the "prefix" environment variable given to scripts */
|
|
||||||
#define PKG_PREFIX_VNAME "PKG_PREFIX"
|
|
||||||
|
|
||||||
/* The name of the "destdir" environment variable given to scripts */
|
|
||||||
#define PKG_DESTDIR_VNAME "PKG_DESTDIR"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The name of the "metadatadir" environment variable given to scripts.
|
|
||||||
* This variable holds the location of the +-files for this package.
|
|
||||||
*/
|
|
||||||
#define PKG_METADATA_DIR_VNAME "PKG_METADATA_DIR"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The name of the environment variable holding the location to the
|
|
||||||
* reference-counts database directory.
|
|
||||||
*/
|
|
||||||
#define PKG_REFCOUNT_DBDIR_VNAME "PKG_REFCOUNT_DBDIR"
|
|
||||||
|
|
||||||
#define PKG_PATTERN_MAX MaxPathSize /* max length of pattern, including nul */
|
|
||||||
#define PKG_SUFFIX_MAX 10 /* max length of suffix, including nul */
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ReadWrite,
|
|
||||||
ReadOnly
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Enumerated constants for plist entry types */
|
|
||||||
typedef enum pl_ent_t {
|
|
||||||
PLIST_SHOW_ALL = -1,
|
|
||||||
PLIST_FILE, /* 0 */
|
|
||||||
PLIST_CWD, /* 1 */
|
|
||||||
PLIST_CMD, /* 2 */
|
|
||||||
PLIST_CHMOD, /* 3 */
|
|
||||||
PLIST_CHOWN, /* 4 */
|
|
||||||
PLIST_CHGRP, /* 5 */
|
|
||||||
PLIST_COMMENT, /* 6 */
|
|
||||||
PLIST_IGNORE, /* 7 */
|
|
||||||
PLIST_NAME, /* 8 */
|
|
||||||
PLIST_UNEXEC, /* 9 */
|
|
||||||
PLIST_SRC, /* 10 */
|
|
||||||
PLIST_DISPLAY, /* 11 */
|
|
||||||
PLIST_PKGDEP, /* 12 */
|
|
||||||
PLIST_DIR_RM, /* 13 */
|
|
||||||
PLIST_OPTION, /* 14 */
|
|
||||||
PLIST_PKGCFL, /* 15 */
|
|
||||||
PLIST_BLDDEP, /* 16 */
|
|
||||||
PLIST_PKGDIR /* 17 */
|
|
||||||
} pl_ent_t;
|
|
||||||
|
|
||||||
/* Enumerated constants for build info */
|
|
||||||
typedef enum bi_ent_t {
|
|
||||||
BI_OPSYS, /* 0 */
|
|
||||||
BI_OS_VERSION, /* 1 */
|
|
||||||
BI_MACHINE_ARCH, /* 2 */
|
|
||||||
BI_IGNORE_RECOMMENDED, /* 3 */
|
|
||||||
BI_USE_ABI_DEPENDS, /* 4 */
|
|
||||||
BI_LICENSE, /* 5 */
|
|
||||||
BI_PKGTOOLS_VERSION, /* 6 */
|
|
||||||
BI_ENUM_COUNT /* 7 */
|
|
||||||
} bi_ent_t;
|
|
||||||
|
|
||||||
/* Types */
|
|
||||||
typedef unsigned int Boolean;
|
|
||||||
|
|
||||||
/* This structure describes a packing list entry */
|
|
||||||
typedef struct plist_t {
|
|
||||||
struct plist_t *prev; /* previous entry */
|
|
||||||
struct plist_t *next; /* next entry */
|
|
||||||
char *name; /* name of entry */
|
|
||||||
Boolean marked; /* whether entry has been marked */
|
|
||||||
pl_ent_t type; /* type of entry */
|
|
||||||
} plist_t;
|
|
||||||
|
|
||||||
/* This structure describes a package's complete packing list */
|
|
||||||
typedef struct package_t {
|
|
||||||
plist_t *head; /* head of list */
|
|
||||||
plist_t *tail; /* tail of list */
|
|
||||||
} package_t;
|
|
||||||
|
|
||||||
#define SYMLINK_HEADER "Symlink:"
|
|
||||||
#define CHECKSUM_HEADER "MD5:"
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ChecksumHeaderLen = 4, /* strlen(CHECKSUM_HEADER) */
|
|
||||||
SymlinkHeaderLen = 8, /* strlen(SYMLINK_HEADER) */
|
|
||||||
ChecksumLen = 16,
|
|
||||||
LegibleChecksumLen = 33
|
|
||||||
};
|
|
||||||
|
|
||||||
/* List of files */
|
|
||||||
typedef struct _lfile_t {
|
|
||||||
TAILQ_ENTRY(_lfile_t) lf_link;
|
|
||||||
char *lf_name;
|
|
||||||
} lfile_t;
|
|
||||||
TAILQ_HEAD(_lfile_head_t, _lfile_t);
|
|
||||||
typedef struct _lfile_head_t lfile_head_t;
|
|
||||||
#define LFILE_ADD(lfhead,lfp,str) do { \
|
|
||||||
lfp = xmalloc(sizeof(lfile_t)); \
|
|
||||||
lfp->lf_name = str; \
|
|
||||||
TAILQ_INSERT_TAIL(lfhead,lfp,lf_link); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
/* List of packages */
|
|
||||||
typedef struct _lpkg_t {
|
|
||||||
TAILQ_ENTRY(_lpkg_t) lp_link;
|
|
||||||
char *lp_name;
|
|
||||||
} lpkg_t;
|
|
||||||
TAILQ_HEAD(_lpkg_head_t, _lpkg_t);
|
|
||||||
typedef struct _lpkg_head_t lpkg_head_t;
|
|
||||||
|
|
||||||
struct pkg_vulnerabilities {
|
|
||||||
size_t entries;
|
|
||||||
char **vulnerability;
|
|
||||||
char **classification;
|
|
||||||
char **advisory;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* If URLlength()>0, then there is a ftp:// or http:// in the string,
|
|
||||||
* and this must be an URL. Hide this behind a more obvious name. */
|
|
||||||
#define IS_URL(str) (URLlength(str) > 0)
|
|
||||||
|
|
||||||
#define IS_STDIN(str) ((str) != NULL && !strcmp((str), "-"))
|
|
||||||
#define IS_FULLPATH(str) ((str) != NULL && (str)[0] == '/')
|
|
||||||
|
|
||||||
/* Conflict handling (conflicts.c) */
|
|
||||||
int some_installed_package_conflicts_with(const char *, const char *, char **, char **);
|
|
||||||
|
|
||||||
|
|
||||||
/* Prototypes */
|
|
||||||
/* Misc */
|
|
||||||
void show_version(void);
|
|
||||||
int fexec(const char *, ...);
|
|
||||||
int fexec_skipempty(const char *, ...);
|
|
||||||
int fcexec(const char *, const char *, ...);
|
|
||||||
int pfcexec(const char *, const char *, const char **);
|
|
||||||
|
|
||||||
/* variables file handling */
|
|
||||||
|
|
||||||
char *var_get(const char *, const char *);
|
|
||||||
char *var_get_memory(const char *, const char *);
|
|
||||||
int var_set(const char *, const char *, const char *);
|
|
||||||
int var_copy_list(const char *, const char **);
|
|
||||||
|
|
||||||
/* automatically installed as dependency */
|
|
||||||
|
|
||||||
Boolean is_automatic_installed(const char *);
|
|
||||||
int mark_as_automatic_installed(const char *, int);
|
|
||||||
|
|
||||||
/* String */
|
|
||||||
const char *basename_of(const char *);
|
|
||||||
const char *dirname_of(const char *);
|
|
||||||
const char *suffix_of(const char *);
|
|
||||||
int pkg_match(const char *, const char *);
|
|
||||||
int pkg_order(const char *, const char *, const char *);
|
|
||||||
int ispkgpattern(const char *);
|
|
||||||
int quick_pkg_match(const char *, const char *);
|
|
||||||
|
|
||||||
/* Iterator functions */
|
|
||||||
int iterate_pkg_generic_src(int (*)(const char *, void *), void *,
|
|
||||||
const char *(*)(void *),void *);
|
|
||||||
int iterate_local_pkg_dir(const char *, int, int, int (*)(const char *, void *),
|
|
||||||
void *);
|
|
||||||
int iterate_pkg_db(int (*)(const char *, void *), void *);
|
|
||||||
|
|
||||||
int add_installed_pkgs_by_basename(const char *, lpkg_head_t *);
|
|
||||||
int add_installed_pkgs_by_pattern(const char *, lpkg_head_t *);
|
|
||||||
char *find_best_matching_installed_pkg(const char *);
|
|
||||||
char *find_best_matching_file(const char *, const char *, int, int);
|
|
||||||
int match_installed_pkgs(const char *, int (*)(const char *, void *), void *);
|
|
||||||
int match_local_files(const char *, int, int, const char *, int (*cb)(const char *, void *), void *);
|
|
||||||
|
|
||||||
/* File */
|
|
||||||
Boolean fexists(const char *);
|
|
||||||
Boolean isdir(const char *);
|
|
||||||
Boolean islinktodir(const char *);
|
|
||||||
Boolean isemptydir(const char *);
|
|
||||||
Boolean isemptyfile(const char *);
|
|
||||||
Boolean isfile(const char *);
|
|
||||||
Boolean isbrokenlink(const char *);
|
|
||||||
Boolean isempty(const char *);
|
|
||||||
int URLlength(const char *);
|
|
||||||
Boolean make_preserve_name(char *, size_t, const char *, const char *);
|
|
||||||
void remove_files(const char *, const char *);
|
|
||||||
int format_cmd(char *, size_t, const char *, const char *, const char *);
|
|
||||||
int readfile(int fd, char *buf, size_t s);
|
|
||||||
|
|
||||||
int recursive_remove(const char *, int);
|
|
||||||
|
|
||||||
void add_pkgdir(const char *, const char *, const char *);
|
|
||||||
void delete_pkgdir(const char *, const char *, const char *);
|
|
||||||
int has_pkgdir(const char *);
|
|
||||||
|
|
||||||
/* pkg_io.c: Local and remote archive handling */
|
|
||||||
struct archive;
|
|
||||||
struct archive_entry;
|
|
||||||
|
|
||||||
struct archive *open_archive(const char *, char **);
|
|
||||||
struct archive *find_archive(const char *, int, char **);
|
|
||||||
void process_pkg_path(void);
|
|
||||||
struct url *find_best_package(const char *, const char *, int);
|
|
||||||
|
|
||||||
/* Packing list */
|
|
||||||
plist_t *new_plist_entry(void);
|
|
||||||
plist_t *last_plist(package_t *);
|
|
||||||
plist_t *find_plist(package_t *, pl_ent_t);
|
|
||||||
char *find_plist_option(package_t *, const char *);
|
|
||||||
void plist_delete(package_t *, Boolean, pl_ent_t, char *);
|
|
||||||
void free_plist(package_t *);
|
|
||||||
void mark_plist(package_t *);
|
|
||||||
void csum_plist_entry(char *, plist_t *);
|
|
||||||
void add_plist(package_t *, pl_ent_t, const char *);
|
|
||||||
void add_plist_top(package_t *, pl_ent_t, const char *);
|
|
||||||
void delete_plist(package_t *, Boolean, pl_ent_t, char *);
|
|
||||||
void write_plist(package_t *, FILE *, char *);
|
|
||||||
void stringify_plist(package_t *, char **, size_t *, const char *);
|
|
||||||
void parse_plist(package_t *, const char *);
|
|
||||||
void read_plist(package_t *, FILE *);
|
|
||||||
void append_plist(package_t *, FILE *);
|
|
||||||
int delete_package(Boolean, package_t *, Boolean, const char *);
|
|
||||||
|
|
||||||
/* Package Database */
|
|
||||||
int pkgdb_open(int);
|
|
||||||
void pkgdb_close(void);
|
|
||||||
int pkgdb_store(const char *, const char *);
|
|
||||||
char *pkgdb_retrieve(const char *);
|
|
||||||
int pkgdb_dump(void);
|
|
||||||
int pkgdb_remove(const char *);
|
|
||||||
int pkgdb_remove_pkg(const char *);
|
|
||||||
char *pkgdb_refcount_dir(void);
|
|
||||||
char *pkgdb_get_database(void);
|
|
||||||
const char *pkgdb_get_dir(void);
|
|
||||||
/*
|
|
||||||
* Priorities:
|
|
||||||
* 0 builtin default
|
|
||||||
* 1 config file
|
|
||||||
* 2 environment
|
|
||||||
* 3 command line
|
|
||||||
* 4 destdir/views reset
|
|
||||||
*/
|
|
||||||
void pkgdb_set_dir(const char *, int);
|
|
||||||
char *pkgdb_pkg_dir(const char *);
|
|
||||||
char *pkgdb_pkg_file(const char *, const char *);
|
|
||||||
|
|
||||||
/* List of packages functions */
|
|
||||||
lpkg_t *alloc_lpkg(const char *);
|
|
||||||
lpkg_t *find_on_queue(lpkg_head_t *, const char *);
|
|
||||||
void free_lpkg(lpkg_t *);
|
|
||||||
|
|
||||||
/* Read pkg_vulnerabilities from file */
|
|
||||||
struct pkg_vulnerabilities *read_pkg_vulnerabilities_file(const char *, int, int);
|
|
||||||
/* Read pkg_vulnerabilities from memory */
|
|
||||||
struct pkg_vulnerabilities *read_pkg_vulnerabilities_memory(void *, size_t, int);
|
|
||||||
void free_pkg_vulnerabilities(struct pkg_vulnerabilities *);
|
|
||||||
int audit_package(struct pkg_vulnerabilities *, const char *, const char *,
|
|
||||||
int);
|
|
||||||
|
|
||||||
/* Parse configuration file */
|
|
||||||
void pkg_install_config(void);
|
|
||||||
/* Print configuration variable */
|
|
||||||
void pkg_install_show_variable(const char *);
|
|
||||||
|
|
||||||
/* Package signature creation and validation */
|
|
||||||
int pkg_verify_signature(const char *, struct archive **, struct archive_entry **, char **);
|
|
||||||
int pkg_full_signature_check(const char *, struct archive **);
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
void pkg_sign_x509(const char *, const char *, const char *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void pkg_sign_gpg(const char *, const char *);
|
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
/* PKCS7 signing/verification */
|
|
||||||
int easy_pkcs7_verify(const char *, size_t, const char *, size_t,
|
|
||||||
const char *, int);
|
|
||||||
int easy_pkcs7_sign(const char *, size_t, char **, size_t *, const char *,
|
|
||||||
const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int inline_gpg_verify(const char *, size_t, const char *);
|
|
||||||
int detached_gpg_verify(const char *, size_t, const char *, size_t,
|
|
||||||
const char *);
|
|
||||||
int detached_gpg_sign(const char *, size_t, char **, size_t *, const char *,
|
|
||||||
const char *);
|
|
||||||
|
|
||||||
/* License handling */
|
|
||||||
int add_licenses(const char *);
|
|
||||||
int acceptable_license(const char *);
|
|
||||||
int acceptable_pkg_license(const char *);
|
|
||||||
void load_license_lists(void);
|
|
||||||
|
|
||||||
/* Helper functions for memory allocation */
|
|
||||||
char *xstrdup(const char *);
|
|
||||||
void *xrealloc(void *, size_t);
|
|
||||||
void *xcalloc(size_t, size_t);
|
|
||||||
void *xmalloc(size_t);
|
|
||||||
char *xasprintf(const char *, ...);
|
|
||||||
|
|
||||||
/* Externs */
|
|
||||||
extern Boolean Verbose;
|
|
||||||
extern Boolean Fake;
|
|
||||||
extern Boolean Force;
|
|
||||||
extern const char *cert_chain_file;
|
|
||||||
extern const char *certs_packages;
|
|
||||||
extern const char *certs_pkg_vulnerabilities;
|
|
||||||
extern const char *check_eol;
|
|
||||||
extern const char *check_vulnerabilities;
|
|
||||||
extern const char *config_file;
|
|
||||||
extern const char *config_pkg_dbdir;
|
|
||||||
extern const char *config_pkg_path;
|
|
||||||
extern const char *config_pkg_refcount_dbdir;
|
|
||||||
extern const char *do_license_check;
|
|
||||||
extern const char *verified_installation;
|
|
||||||
extern const char *gpg_cmd;
|
|
||||||
extern const char *gpg_keyring_pkgvuln;
|
|
||||||
extern const char *gpg_keyring_sign;
|
|
||||||
extern const char *gpg_keyring_verify;
|
|
||||||
extern const char *gpg_sign_as;
|
|
||||||
extern char fetch_flags[];
|
|
||||||
|
|
||||||
extern const char *pkg_vulnerabilities_dir;
|
|
||||||
extern const char *pkg_vulnerabilities_file;
|
|
||||||
extern const char *pkg_vulnerabilities_url;
|
|
||||||
extern const char *ignore_advisories;
|
|
||||||
extern const char tnf_vulnerability_base[];
|
|
||||||
|
|
||||||
extern const char *acceptable_licenses;
|
|
||||||
extern const char *default_acceptable_licenses;
|
|
||||||
|
|
||||||
#endif /* _INST_LIB_LIB_H_ */
|
|
|
@ -1,303 +0,0 @@
|
||||||
/* $NetBSD: license.c,v 1.14 2010/05/06 13:16:59 obache Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#define HASH_SIZE 521
|
|
||||||
|
|
||||||
const char *default_acceptable_licenses =
|
|
||||||
"public-domain "
|
|
||||||
"gnu-fdl-v1.1 gnu-fdl-v1.2 gnu-fdl-v1.3 "
|
|
||||||
"gnu-gpl-v2 gnu-lgpl-v2 gnu-lgpl-v2.1 "
|
|
||||||
"gnu-gpl-v3 gnu-lgpl-v3 "
|
|
||||||
"original-bsd modified-bsd 2-clause-bsd "
|
|
||||||
"x11 mit miros "
|
|
||||||
"apache-1.1 apache-2.0 "
|
|
||||||
"artistic artistic-2.0 "
|
|
||||||
"cddl-1.0 "
|
|
||||||
"cpl-1.0 "
|
|
||||||
"open-font-license "
|
|
||||||
"mpl-1.0 mpl-1.1 "
|
|
||||||
"zpl "
|
|
||||||
"python-software-foundation "
|
|
||||||
"ipafont "
|
|
||||||
"isc "
|
|
||||||
"info-zip";
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static size_t hash_collisions;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char **license_hash[HASH_SIZE];
|
|
||||||
static const char license_spaces[] = " \t\n";
|
|
||||||
static const char license_chars[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.";
|
|
||||||
|
|
||||||
static size_t
|
|
||||||
hash_license(const char *license, size_t len)
|
|
||||||
{
|
|
||||||
size_t hash;
|
|
||||||
|
|
||||||
for (hash = 0; *license && len; ++license, --len)
|
|
||||||
hash = *license + hash * 32;
|
|
||||||
return hash % HASH_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
add_license_internal(const char *license, size_t len)
|
|
||||||
{
|
|
||||||
char *new_license;
|
|
||||||
size_t slot, i;
|
|
||||||
|
|
||||||
slot = hash_license(license, len);
|
|
||||||
|
|
||||||
new_license = malloc(len + 1);
|
|
||||||
memcpy(new_license, license, len);
|
|
||||||
new_license[len] = '\0';
|
|
||||||
|
|
||||||
if (license_hash[slot] == NULL) {
|
|
||||||
license_hash[slot] = calloc(sizeof(char *), 2);
|
|
||||||
license_hash[slot][0] = new_license;
|
|
||||||
} else {
|
|
||||||
for (i = 0; license_hash[slot][i]; ++i) {
|
|
||||||
if (!memcmp(license_hash[slot][i], license, len) &&
|
|
||||||
license_hash[slot][i][len] == '\0') {
|
|
||||||
free(new_license);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
++hash_collisions;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
license_hash[slot] = realloc(license_hash[slot],
|
|
||||||
sizeof(char *) * (i + 2));
|
|
||||||
license_hash[slot][i] = new_license;
|
|
||||||
license_hash[slot][i + 1] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
add_licenses(const char *line)
|
|
||||||
{
|
|
||||||
const char *next;
|
|
||||||
|
|
||||||
if (line == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (line += strspn(line, license_spaces); line; ) {
|
|
||||||
next = line + strspn(line, license_chars);
|
|
||||||
if (next == line)
|
|
||||||
return *line ? -1 : 0;
|
|
||||||
add_license_internal(line, next - line);
|
|
||||||
line = next + strspn(next, license_spaces);
|
|
||||||
if (next == line)
|
|
||||||
return *line ? -1 : 0;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
acceptable_license_internal(const char *license, size_t len)
|
|
||||||
{
|
|
||||||
size_t slot, i;
|
|
||||||
|
|
||||||
slot = hash_license(license, len);
|
|
||||||
|
|
||||||
if (license_hash[slot] == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; license_hash[slot][i]; ++i) {
|
|
||||||
if (strncmp(license_hash[slot][i], license, len) == 0 &&
|
|
||||||
license_hash[slot][i][len] == '\0')
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
acceptable_license(const char *license)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(license);
|
|
||||||
if (strspn(license, license_chars) != len) {
|
|
||||||
warnx("Invalid character in license name at position %" PRIzu, len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return acceptable_license_internal(license, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
acceptable_pkg_license_internal(const char **licensep, int toplevel, const char *start)
|
|
||||||
{
|
|
||||||
const char *license = *licensep;
|
|
||||||
int need_parenthesis, is_true = 0;
|
|
||||||
int expr_type = 0; /* 0: unset, 1: or, 2: and */
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
license += strspn(license, license_spaces);
|
|
||||||
|
|
||||||
if (*license == '(' && !toplevel) {
|
|
||||||
need_parenthesis = 1;
|
|
||||||
++license;
|
|
||||||
license += strspn(license, license_spaces);
|
|
||||||
} else {
|
|
||||||
need_parenthesis = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (*license == '(') {
|
|
||||||
switch (acceptable_pkg_license_internal(&license, 0, start)) {
|
|
||||||
case -1:
|
|
||||||
return -1;
|
|
||||||
case 0:
|
|
||||||
if (expr_type == 2)
|
|
||||||
is_true = 0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
is_true = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
license += strspn(license, license_spaces);
|
|
||||||
} else {
|
|
||||||
len = strspn(license, license_chars);
|
|
||||||
if (len == 0) {
|
|
||||||
warnx("Invalid character in license name at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acceptable_license_internal(license, len)) {
|
|
||||||
if (expr_type != 2)
|
|
||||||
is_true = 1;
|
|
||||||
} else if (expr_type == 2) {
|
|
||||||
is_true = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
license += len;
|
|
||||||
|
|
||||||
len = strspn(license, license_spaces);
|
|
||||||
if (len == 0 && *license && *license != ')') {
|
|
||||||
warnx("Missing space at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
license += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*license == ')') {
|
|
||||||
if (!need_parenthesis) {
|
|
||||||
warnx("Missing open parenthesis at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*licensep = license + 1;
|
|
||||||
return is_true;
|
|
||||||
}
|
|
||||||
if (*license == '\0') {
|
|
||||||
if (need_parenthesis) {
|
|
||||||
warnx("Unbalanced parenthesis at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*licensep = license;
|
|
||||||
return is_true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(license, "AND", 3) == 0) {
|
|
||||||
if (expr_type == 1) {
|
|
||||||
warnx("Invalid operator in OR expression at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
expr_type = 2;
|
|
||||||
license += 3;
|
|
||||||
} else if (strncmp(license, "OR", 2) == 0) {
|
|
||||||
if (expr_type == 2) {
|
|
||||||
warnx("Invalid operator in AND expression at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
expr_type = 1;
|
|
||||||
license += 2;
|
|
||||||
} else {
|
|
||||||
warnx("Invalid operator at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
len = strspn(license, license_spaces);
|
|
||||||
if (len == 0 && *license != '(') {
|
|
||||||
warnx("Missing space at position %" PRIzu, license - start + 1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
license += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
acceptable_pkg_license(const char *license)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = acceptable_pkg_license_internal(&license, 1, license);
|
|
||||||
if (ret == -1)
|
|
||||||
return -1;
|
|
||||||
license += strspn(license, license_spaces);
|
|
||||||
if (*license) {
|
|
||||||
warnx("Trailing garbage in license specification");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
load_license_lists(void)
|
|
||||||
{
|
|
||||||
if (add_licenses(getenv("PKGSRC_ACCEPTABLE_LICENSES")))
|
|
||||||
errx(EXIT_FAILURE, "syntax error in PKGSRC_ACCEPTABLE_LICENSES");
|
|
||||||
if (add_licenses(acceptable_licenses))
|
|
||||||
errx(EXIT_FAILURE, "syntax error in ACCEPTABLE_LICENSES");
|
|
||||||
if (add_licenses(getenv("PKGSRC_DEFAULT_ACCEPTABLE_LICENSES")))
|
|
||||||
errx(EXIT_FAILURE, "syntax error in PKGSRC_DEFAULT_ACCEPTABLE_LICENSES");
|
|
||||||
if (add_licenses(default_acceptable_licenses))
|
|
||||||
errx(EXIT_FAILURE, "syntax error in DEFAULT_ACCEPTABLE_LICENSES");
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/* $NetBSD: lpkg.c,v 1.6 2009/02/02 12:35:01 joerg Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1999 Christian E. Hopps
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
* Package-list auxiliary functions
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add a package to the (add/recursive delete) list
|
|
||||||
*/
|
|
||||||
lpkg_t *
|
|
||||||
alloc_lpkg(const char *pkgname)
|
|
||||||
{
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
lpp = xmalloc(sizeof(*lpp));
|
|
||||||
lpp->lp_name = xstrdup(pkgname);
|
|
||||||
return (lpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_lpkg(lpkg_t *lpp)
|
|
||||||
{
|
|
||||||
free(lpp->lp_name);
|
|
||||||
free(lpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
lpkg_t *
|
|
||||||
find_on_queue(lpkg_head_t *qp, const char *name)
|
|
||||||
{
|
|
||||||
lpkg_t *lpp;
|
|
||||||
|
|
||||||
for (lpp = TAILQ_FIRST(qp); lpp; lpp = TAILQ_NEXT(lpp, lp_link))
|
|
||||||
if (!strcmp(name, lpp->lp_name))
|
|
||||||
return (lpp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
|
@ -1,213 +0,0 @@
|
||||||
/* $NetBSD: opattern.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: opattern.c,v 1.5 2009/02/02 12:35:01 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Miscellaneous string utilities.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ASSERT_H
|
|
||||||
#include <assert.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FNMATCH_H
|
|
||||||
#include <fnmatch.h>
|
|
||||||
#endif
|
|
||||||
#include "lib.h"
|
|
||||||
#include "dewey.h"
|
|
||||||
|
|
||||||
/* pull in definitions and macros for resizing arrays as we go */
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform alternate match on "pkg" against "pattern",
|
|
||||||
* calling pkg_match (recursively) to resolve any other patterns.
|
|
||||||
* Return 1 on match, 0 otherwise
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
alternate_match(const char *pattern, const char *pkg)
|
|
||||||
{
|
|
||||||
char *sep;
|
|
||||||
char buf[MaxPathSize];
|
|
||||||
char *last;
|
|
||||||
char *alt;
|
|
||||||
char *cp;
|
|
||||||
int cnt;
|
|
||||||
int found;
|
|
||||||
|
|
||||||
if ((sep = strchr(pattern, '{')) == (char *) NULL) {
|
|
||||||
errx(EXIT_FAILURE, "alternate_match(): '{' expected in `%s'", pattern);
|
|
||||||
}
|
|
||||||
(void) strncpy(buf, pattern, (size_t) (sep - pattern));
|
|
||||||
alt = &buf[sep - pattern];
|
|
||||||
last = (char *) NULL;
|
|
||||||
for (cnt = 0, cp = sep; *cp && last == (char *) NULL; cp++) {
|
|
||||||
if (*cp == '{') {
|
|
||||||
cnt++;
|
|
||||||
} else if (*cp == '}' && --cnt == 0 && last == (char *) NULL) {
|
|
||||||
last = cp + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cnt != 0) {
|
|
||||||
errx(EXIT_FAILURE, "Malformed alternate `%s'", pattern);
|
|
||||||
}
|
|
||||||
for (found = 0, cp = sep + 1; *sep != '}'; cp = sep + 1) {
|
|
||||||
for (cnt = 0, sep = cp; cnt > 0 || (cnt == 0 && *sep != '}' && *sep != ','); sep++) {
|
|
||||||
if (*sep == '{') {
|
|
||||||
cnt++;
|
|
||||||
} else if (*sep == '}') {
|
|
||||||
cnt--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) snprintf(alt, sizeof(buf) - (alt - buf), "%.*s%s", (int) (sep - cp), cp, last);
|
|
||||||
if (pkg_match(buf, pkg) == 1) {
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform glob match on "pkg" against "pattern".
|
|
||||||
* Return 1 on match, 0 otherwise
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
glob_match(const char *pattern, const char *pkg)
|
|
||||||
{
|
|
||||||
return fnmatch(pattern, pkg, FNM_PERIOD) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform simple match on "pkg" against "pattern".
|
|
||||||
* Return 1 on match, 0 otherwise
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
simple_match(const char *pattern, const char *pkg)
|
|
||||||
{
|
|
||||||
return strcmp(pattern, pkg) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Performs a fast check if pattern can ever match pkg.
|
|
||||||
* Returns 1 if a match is possible and 0 otherwise.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
quick_pkg_match(const char *pattern, const char *pkg)
|
|
||||||
{
|
|
||||||
#define simple(x) (isalnum((unsigned char)(x)) || (x) == '-')
|
|
||||||
if (!simple(pattern[0]))
|
|
||||||
return 1;
|
|
||||||
if (pattern[0] != pkg[0])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!simple(pattern[1]))
|
|
||||||
return 1;
|
|
||||||
if (pattern[1] != pkg[1])
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
#undef simple
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Match pkg against pattern, return 1 if matching, 0 else
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pkg_match(const char *pattern, const char *pkg)
|
|
||||||
{
|
|
||||||
if (!quick_pkg_match(pattern, pkg))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (strchr(pattern, '{') != (char *) NULL) {
|
|
||||||
/* emulate csh-type alternates */
|
|
||||||
return alternate_match(pattern, pkg);
|
|
||||||
}
|
|
||||||
if (strpbrk(pattern, "<>") != (char *) NULL) {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* perform relational dewey match on version number */
|
|
||||||
ret = dewey_match(pattern, pkg);
|
|
||||||
if (ret < 0)
|
|
||||||
errx(EXIT_FAILURE, "dewey_match returned error");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (strpbrk(pattern, "*?[]") != (char *) NULL) {
|
|
||||||
/* glob match */
|
|
||||||
if (glob_match(pattern, pkg))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no alternate, dewey or glob match -> simple compare */
|
|
||||||
if (simple_match(pattern, pkg))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* globbing patterns and simple matches may be specified with or
|
|
||||||
* without the version number, so check for both cases. */
|
|
||||||
|
|
||||||
{
|
|
||||||
char *pattern_ver;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
pattern_ver = xasprintf("%s-[0-9]*", pattern);
|
|
||||||
retval = glob_match(pattern_ver, pkg);
|
|
||||||
free(pattern_ver);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pkg_order(const char *pattern, const char *first_pkg, const char *second_pkg)
|
|
||||||
{
|
|
||||||
const char *first_version;
|
|
||||||
const char *second_version;
|
|
||||||
|
|
||||||
if (first_pkg == NULL && second_pkg == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (first_pkg == NULL)
|
|
||||||
return pkg_match(pattern, second_pkg) ? 2 : 0;
|
|
||||||
if (second_pkg == NULL)
|
|
||||||
return pkg_match(pattern, first_pkg) ? 1 : 0;
|
|
||||||
|
|
||||||
first_version = strrchr(first_pkg, '-');
|
|
||||||
second_version = strrchr(second_pkg, '-');
|
|
||||||
|
|
||||||
if (first_version == NULL || !pkg_match(pattern, first_pkg))
|
|
||||||
return pkg_match(pattern, second_pkg) ? 2 : 0;
|
|
||||||
|
|
||||||
if (second_version == NULL || !pkg_match(pattern, second_pkg))
|
|
||||||
return pkg_match(pattern, first_pkg) ? 1 : 0;
|
|
||||||
|
|
||||||
if (dewey_cmp(first_version + 1, DEWEY_GT, second_version + 1))
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 2;
|
|
||||||
}
|
|
|
@ -1,275 +0,0 @@
|
||||||
/* $NetBSD: parse-config.c,v 1.15 2010/06/16 23:02:49 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: parse-config.c,v 1.15 2010/06/16 23:02:49 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
#include <fetch.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static int cache_connections = 16;
|
|
||||||
static int cache_connections_host = 4;
|
|
||||||
|
|
||||||
const char *config_file = SYSCONFDIR"/pkg_install.conf";
|
|
||||||
|
|
||||||
char fetch_flags[10] = ""; /* Workaround Mac OS X linker issues with BSS */
|
|
||||||
static const char *active_ftp;
|
|
||||||
static const char *verbose_netio;
|
|
||||||
static const char *ignore_proxy;
|
|
||||||
const char *cache_index = "yes";
|
|
||||||
const char *cert_chain_file;
|
|
||||||
const char *certs_packages;
|
|
||||||
const char *certs_pkg_vulnerabilities;
|
|
||||||
const char *check_eol = "yes";
|
|
||||||
const char *check_vulnerabilities;
|
|
||||||
static const char *config_cache_connections;
|
|
||||||
static const char *config_cache_connections_host;
|
|
||||||
const char *config_pkg_dbdir;
|
|
||||||
const char *config_pkg_path;
|
|
||||||
const char *config_pkg_refcount_dbdir;
|
|
||||||
const char *do_license_check;
|
|
||||||
const char *verified_installation;
|
|
||||||
const char *gpg_cmd;
|
|
||||||
const char *gpg_keyring_pkgvuln;
|
|
||||||
const char *gpg_keyring_sign;
|
|
||||||
const char *gpg_keyring_verify;
|
|
||||||
const char *gpg_sign_as;
|
|
||||||
const char *pkg_vulnerabilities_dir;
|
|
||||||
const char *pkg_vulnerabilities_file;
|
|
||||||
const char *pkg_vulnerabilities_url;
|
|
||||||
const char *ignore_advisories = NULL;
|
|
||||||
const char tnf_vulnerability_base[] = "http://ftp.NetBSD.org/pub/NetBSD/packages/vulns";
|
|
||||||
const char *acceptable_licenses = NULL;
|
|
||||||
|
|
||||||
static struct config_variable {
|
|
||||||
const char *name;
|
|
||||||
const char **var;
|
|
||||||
} config_variables[] = {
|
|
||||||
{ "ACCEPTABLE_LICENSES", &acceptable_licenses },
|
|
||||||
{ "ACTIVE_FTP", &active_ftp },
|
|
||||||
{ "CACHE_INDEX", &cache_index },
|
|
||||||
{ "CACHE_CONNECTIONS", &config_cache_connections },
|
|
||||||
{ "CACHE_CONNECTIONS_HOST", &config_cache_connections_host },
|
|
||||||
{ "CERTIFICATE_ANCHOR_PKGS", &certs_packages },
|
|
||||||
{ "CERTIFICATE_ANCHOR_PKGVULN", &certs_pkg_vulnerabilities },
|
|
||||||
{ "CERTIFICATE_CHAIN", &cert_chain_file },
|
|
||||||
{ "CHECK_LICENSE", &do_license_check },
|
|
||||||
{ "CHECK_END_OF_LIFE", &check_eol },
|
|
||||||
{ "CHECK_VULNERABILITIES", &check_vulnerabilities },
|
|
||||||
{ "DEFAULT_ACCEPTABLE_LICENSES", &default_acceptable_licenses },
|
|
||||||
{ "GPG", &gpg_cmd },
|
|
||||||
{ "GPG_KEYRING_PKGVULN", &gpg_keyring_pkgvuln },
|
|
||||||
{ "GPG_KEYRING_SIGN", &gpg_keyring_sign },
|
|
||||||
{ "GPG_KEYRING_VERIFY", &gpg_keyring_verify },
|
|
||||||
{ "GPG_SIGN_AS", &gpg_sign_as },
|
|
||||||
{ "IGNORE_PROXY", &ignore_proxy },
|
|
||||||
{ "IGNORE_URL", &ignore_advisories },
|
|
||||||
{ "PKG_DBDIR", &config_pkg_dbdir },
|
|
||||||
{ "PKG_PATH", &config_pkg_path },
|
|
||||||
{ "PKG_REFCOUNT_DBDIR", &config_pkg_refcount_dbdir },
|
|
||||||
{ "PKGVULNDIR", &pkg_vulnerabilities_dir },
|
|
||||||
{ "PKGVULNURL", &pkg_vulnerabilities_url },
|
|
||||||
{ "VERBOSE_NETIO", &verbose_netio },
|
|
||||||
{ "VERIFIED_INSTALLATION", &verified_installation },
|
|
||||||
{ NULL, NULL }, /* For use by pkg_install_show_variable */
|
|
||||||
{ NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
char *config_tmp_variables[sizeof config_variables/sizeof config_variables[0]];
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_pkg_install_conf(void)
|
|
||||||
{
|
|
||||||
struct config_variable *var;
|
|
||||||
FILE *fp;
|
|
||||||
char *line, *value;
|
|
||||||
size_t len, var_len, i;
|
|
||||||
|
|
||||||
fp = fopen(config_file, "r");
|
|
||||||
if (!fp) {
|
|
||||||
if (errno != ENOENT)
|
|
||||||
warn("Can't open '%s' for reading", config_file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((line = fgetln(fp, &len)) != (char *) NULL) {
|
|
||||||
if (line[len - 1] == '\n')
|
|
||||||
--len;
|
|
||||||
for (i = 0; (var = &config_variables[i])->name != NULL; ++i) {
|
|
||||||
var_len = strlen(var->name);
|
|
||||||
if (strncmp(var->name, line, var_len) != 0)
|
|
||||||
continue;
|
|
||||||
if (line[var_len] != '=')
|
|
||||||
continue;
|
|
||||||
line += var_len + 1;
|
|
||||||
len -= var_len + 1;
|
|
||||||
if (config_tmp_variables[i])
|
|
||||||
value = xasprintf("%s\n%.*s",
|
|
||||||
config_tmp_variables[i], (int)len, line);
|
|
||||||
else
|
|
||||||
value = xasprintf("%.*s", (int)len, line);
|
|
||||||
free(config_tmp_variables[i]);
|
|
||||||
config_tmp_variables[i] = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; (var = &config_variables[i])->name != NULL; ++i) {
|
|
||||||
if (config_tmp_variables[i] == NULL)
|
|
||||||
continue;
|
|
||||||
*var->var = config_tmp_variables[i];
|
|
||||||
config_tmp_variables[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pkg_install_config(void)
|
|
||||||
{
|
|
||||||
int do_cache_index;
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
parse_pkg_install_conf();
|
|
||||||
|
|
||||||
if ((value = getenv("PKG_DBDIR")) != NULL)
|
|
||||||
pkgdb_set_dir(value, 2);
|
|
||||||
else if (config_pkg_dbdir != NULL)
|
|
||||||
pkgdb_set_dir(config_pkg_dbdir, 1);
|
|
||||||
config_pkg_dbdir = xstrdup(pkgdb_get_dir());
|
|
||||||
|
|
||||||
if ((value = getenv("PKG_REFCOUNT_DBDIR")) != NULL)
|
|
||||||
config_pkg_refcount_dbdir = value;
|
|
||||||
else if (config_pkg_refcount_dbdir == NULL)
|
|
||||||
config_pkg_refcount_dbdir = xasprintf("%s.refcount",
|
|
||||||
pkgdb_get_dir());
|
|
||||||
|
|
||||||
if (pkg_vulnerabilities_dir == NULL)
|
|
||||||
pkg_vulnerabilities_dir = pkgdb_get_dir();
|
|
||||||
pkg_vulnerabilities_file = xasprintf("%s/pkg-vulnerabilities",
|
|
||||||
pkg_vulnerabilities_dir);
|
|
||||||
if (pkg_vulnerabilities_url == NULL) {
|
|
||||||
pkg_vulnerabilities_url = xasprintf("%s/pkg-vulnerabilities.gz",
|
|
||||||
tnf_vulnerability_base);
|
|
||||||
}
|
|
||||||
if (verified_installation == NULL)
|
|
||||||
verified_installation = "never";
|
|
||||||
|
|
||||||
if (check_vulnerabilities == NULL)
|
|
||||||
check_vulnerabilities = "never";
|
|
||||||
|
|
||||||
if (do_license_check == NULL)
|
|
||||||
do_license_check = "no";
|
|
||||||
|
|
||||||
if ((value = getenv("PKG_PATH")) != NULL)
|
|
||||||
config_pkg_path = value;
|
|
||||||
|
|
||||||
if (strcasecmp(cache_index, "yes") == 0)
|
|
||||||
do_cache_index = 1;
|
|
||||||
else {
|
|
||||||
if (strcasecmp(cache_index, "no"))
|
|
||||||
warnx("Invalid value for configuration option "
|
|
||||||
"CACHE_INDEX");
|
|
||||||
do_cache_index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_cache_connections && *config_cache_connections) {
|
|
||||||
long v = strtol(config_cache_connections, &value, 10);
|
|
||||||
if (*value == '\0') {
|
|
||||||
if (v >= INT_MAX || v < 0)
|
|
||||||
v = -1;
|
|
||||||
cache_connections = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config_cache_connections = xasprintf("%d", cache_connections);
|
|
||||||
|
|
||||||
if (config_cache_connections_host) {
|
|
||||||
long v = strtol(config_cache_connections_host, &value, 10);
|
|
||||||
if (*value == '\0') {
|
|
||||||
if (v >= INT_MAX || v < 0)
|
|
||||||
v = -1;
|
|
||||||
cache_connections_host = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config_cache_connections_host = xasprintf("%d", cache_connections_host);
|
|
||||||
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
fetchConnectionCacheInit(cache_connections, cache_connections_host);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
snprintf(fetch_flags, sizeof(fetch_flags), "%s%s%s%s",
|
|
||||||
(do_cache_index) ? "c" : "",
|
|
||||||
(verbose_netio && *verbose_netio) ? "v" : "",
|
|
||||||
(active_ftp && *active_ftp) ? "a" : "",
|
|
||||||
(ignore_proxy && *ignore_proxy) ? "d" : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pkg_install_show_variable(const char *var_name)
|
|
||||||
{
|
|
||||||
struct config_variable *var;
|
|
||||||
const char *tmp_value = NULL;
|
|
||||||
|
|
||||||
for (var = config_variables; var->name != NULL; ++var) {
|
|
||||||
if (strcmp(var->name, var_name) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (var->name == NULL) {
|
|
||||||
var->name = var_name;
|
|
||||||
var->var = &tmp_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
pkg_install_config();
|
|
||||||
|
|
||||||
if (*var->var != NULL)
|
|
||||||
puts(*var->var);
|
|
||||||
}
|
|
|
@ -1,336 +0,0 @@
|
||||||
/* $NetBSD: pkcs7.c,v 1.5 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: pkcs7.c,v 1.5 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Love Hörnquist Åstrand <lha@it.su.se>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <openssl/pkcs7.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/x509.h>
|
|
||||||
#include <openssl/x509v3.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#ifndef NS_ANY_CA
|
|
||||||
#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const unsigned int pkg_key_usage = XKU_CODE_SIGN | XKU_SMIME;
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_ca(X509 *cert)
|
|
||||||
{
|
|
||||||
if ((cert->ex_flags & EXFLAG_KUSAGE) != 0 &&
|
|
||||||
(cert->ex_kusage & KU_KEY_CERT_SIGN) != KU_KEY_CERT_SIGN)
|
|
||||||
return 0;
|
|
||||||
if ((cert->ex_flags & EXFLAG_BCONS) != 0)
|
|
||||||
return (cert->ex_flags & EXFLAG_CA) == EXFLAG_CA;
|
|
||||||
if ((cert->ex_flags & (EXFLAG_V1|EXFLAG_SS)) == (EXFLAG_V1|EXFLAG_SS))
|
|
||||||
return 1;
|
|
||||||
if ((cert->ex_flags & EXFLAG_KUSAGE) != 0)
|
|
||||||
return 1;
|
|
||||||
if ((cert->ex_flags & EXFLAG_NSCERT) != 0 &&
|
|
||||||
(cert->ex_nscert & NS_ANY_CA) != 0)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static STACK_OF(X509) *
|
|
||||||
file_to_certs(const char *file)
|
|
||||||
{
|
|
||||||
unsigned long ret;
|
|
||||||
STACK_OF(X509) *certs;
|
|
||||||
FILE *f;
|
|
||||||
|
|
||||||
if ((f = fopen(file, "r")) == NULL) {
|
|
||||||
warn("open failed %s", file);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
certs = sk_X509_new_null();
|
|
||||||
for (;;) {
|
|
||||||
X509 *cert;
|
|
||||||
|
|
||||||
cert = PEM_read_X509(f, NULL, NULL, NULL);
|
|
||||||
if (cert == NULL) {
|
|
||||||
ret = ERR_GET_REASON(ERR_peek_error());
|
|
||||||
if (ret == PEM_R_NO_START_LINE) {
|
|
||||||
/* End of file reached. no error */
|
|
||||||
ERR_clear_error();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sk_X509_free(certs);
|
|
||||||
warnx("Can't read certificate in file: %s", file);
|
|
||||||
fclose(f);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
sk_X509_insert(certs, cert, sk_X509_num(certs));
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
if (sk_X509_num(certs) == 0) {
|
|
||||||
sk_X509_free(certs);
|
|
||||||
certs = NULL;
|
|
||||||
warnx("No certificate found in file %s", file);
|
|
||||||
}
|
|
||||||
|
|
||||||
return certs;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
easy_pkcs7_verify(const char *content, size_t len,
|
|
||||||
const char *signature, size_t signature_len,
|
|
||||||
const char *anchor, int is_pkg)
|
|
||||||
{
|
|
||||||
STACK_OF(X509) *cert_chain, *signers;
|
|
||||||
X509_STORE *store;
|
|
||||||
BIO *sig, *in;
|
|
||||||
PKCS7 *p7;
|
|
||||||
int i, status;
|
|
||||||
X509_NAME *name;
|
|
||||||
char *subject;
|
|
||||||
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
ERR_load_crypto_strings();
|
|
||||||
|
|
||||||
status = -1;
|
|
||||||
|
|
||||||
if (cert_chain_file)
|
|
||||||
cert_chain = file_to_certs(cert_chain_file);
|
|
||||||
else
|
|
||||||
cert_chain = NULL;
|
|
||||||
|
|
||||||
store = X509_STORE_new();
|
|
||||||
if (store == NULL) {
|
|
||||||
sk_X509_free(cert_chain);
|
|
||||||
warnx("Failed to create certificate store");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509_STORE_load_locations(store, anchor, NULL);
|
|
||||||
|
|
||||||
in = BIO_new_mem_buf(__UNCONST(content), len);
|
|
||||||
sig = BIO_new_mem_buf(__UNCONST(signature), signature_len);
|
|
||||||
signers = NULL;
|
|
||||||
|
|
||||||
p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL);
|
|
||||||
if (p7 == NULL) {
|
|
||||||
warnx("Failed to parse the signature");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) {
|
|
||||||
warnx("Failed to verify signature");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
signers = PKCS7_get0_signers(p7, NULL, 0);
|
|
||||||
if (signers == NULL) {
|
|
||||||
warnx("Failed to get signers");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sk_X509_num(signers) == 0) {
|
|
||||||
warnx("No signers found");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < sk_X509_num(signers); i++) {
|
|
||||||
/* Compute ex_xkusage */
|
|
||||||
X509_check_purpose(sk_X509_value(signers, i), -1, -1);
|
|
||||||
|
|
||||||
if (check_ca(sk_X509_value(signers, i))) {
|
|
||||||
warnx("CA keys are not valid for signatures");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (is_pkg) {
|
|
||||||
if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) {
|
|
||||||
warnx("Certificate must have CODE SIGNING "
|
|
||||||
"and EMAIL PROTECTION property");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (sk_X509_value(signers, i)->ex_xkusage != 0) {
|
|
||||||
warnx("Certificate must not have any property");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Sigature ok, signed by:\n");
|
|
||||||
|
|
||||||
for (i = 0; i < sk_X509_num(signers); i++) {
|
|
||||||
name = X509_get_subject_name(sk_X509_value(signers, i));
|
|
||||||
subject = X509_NAME_oneline(name, NULL, 0);
|
|
||||||
|
|
||||||
printf("\t%s\n", subject);
|
|
||||||
|
|
||||||
OPENSSL_free(subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
sk_X509_free(cert_chain);
|
|
||||||
sk_X509_free(signers);
|
|
||||||
X509_STORE_free(store);
|
|
||||||
|
|
||||||
PKCS7_free(p7);
|
|
||||||
BIO_free(in);
|
|
||||||
BIO_free(sig);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ssl_pass_cb(char *buf, int size, int rwflag, void *u)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (EVP_read_pw_string(buf, size, "Passphrase :", 0)) {
|
|
||||||
#if OPENSSL_VERSION >= 0x0090608fL
|
|
||||||
OPENSSL_cleanse(buf, size);
|
|
||||||
#else
|
|
||||||
memset(buf, 0, size);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return strlen(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
easy_pkcs7_sign(const char *content, size_t len,
|
|
||||||
char **signature, size_t *signature_len,
|
|
||||||
const char *key_file, const char *cert_file)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
X509 *certificate;
|
|
||||||
STACK_OF(X509) *c, *cert_chain;
|
|
||||||
EVP_PKEY *private_key;
|
|
||||||
char *tmp_sig;
|
|
||||||
BIO *out, *in;
|
|
||||||
PKCS7 *p7;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
ERR_load_crypto_strings();
|
|
||||||
|
|
||||||
status = -1;
|
|
||||||
private_key = NULL;
|
|
||||||
cert_chain = NULL;
|
|
||||||
in = NULL;
|
|
||||||
|
|
||||||
c = file_to_certs(cert_file);
|
|
||||||
|
|
||||||
if (sk_X509_num(c) != 1) {
|
|
||||||
warnx("More then one certificate in the certificate file");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
certificate = sk_X509_value(c, 0);
|
|
||||||
|
|
||||||
/* Compute ex_kusage */
|
|
||||||
X509_check_purpose(certificate, -1, 0);
|
|
||||||
|
|
||||||
if (check_ca(certificate)) {
|
|
||||||
warnx("CA keys are not valid for signatures");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (certificate->ex_xkusage != pkg_key_usage) {
|
|
||||||
warnx("Certificate must have CODE SIGNING "
|
|
||||||
"and EMAIL PROTECTION property");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cert_chain_file)
|
|
||||||
cert_chain = file_to_certs(cert_chain_file);
|
|
||||||
|
|
||||||
if ((f = fopen(key_file, "r")) == NULL) {
|
|
||||||
warn("Failed to open private key file %s", key_file);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL);
|
|
||||||
fclose(f);
|
|
||||||
if (private_key == NULL) {
|
|
||||||
warnx("Can't read private key: %s", key_file);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (X509_check_private_key(certificate, private_key) != 1) {
|
|
||||||
warnx("The private key %s doesn't match the certificate %s",
|
|
||||||
key_file, cert_file);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
in = BIO_new_mem_buf(__UNCONST(content), len);
|
|
||||||
|
|
||||||
p7 = PKCS7_sign(certificate, private_key, cert_chain, in,
|
|
||||||
PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY);
|
|
||||||
if (p7 == NULL) {
|
|
||||||
warnx("Failed to create signature structure");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
out = BIO_new(BIO_s_mem());
|
|
||||||
PEM_write_bio_PKCS7(out, p7);
|
|
||||||
*signature_len = BIO_get_mem_data(out, &tmp_sig);
|
|
||||||
*signature = xmalloc(*signature_len);
|
|
||||||
memcpy(*signature, tmp_sig, *signature_len);
|
|
||||||
BIO_free_all(out);
|
|
||||||
|
|
||||||
PKCS7_free(p7);
|
|
||||||
|
|
||||||
status = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
sk_X509_free(c);
|
|
||||||
sk_X509_free(cert_chain);
|
|
||||||
EVP_PKEY_free(private_key);
|
|
||||||
BIO_free(in);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
.\" $NetBSD: pkg_install.conf.5.in,v 1.14 2010/06/16 23:02:49 joerg Exp $
|
|
||||||
.\"
|
|
||||||
.\" Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
|
|
||||||
.\" All rights reserved.
|
|
||||||
.\"
|
|
||||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
.\" by Thomas Klausner.
|
|
||||||
.\"
|
|
||||||
.\" 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.
|
|
||||||
.\"
|
|
||||||
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
.\"
|
|
||||||
.Dd June 16, 2010
|
|
||||||
.Dt PKG_INSTALL.CONF 5
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pkg_install.conf
|
|
||||||
.Nd configuration file for package installation tools
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
The file
|
|
||||||
.Nm
|
|
||||||
contains system defaults for the package installation tools
|
|
||||||
as a list of variable-value pairs.
|
|
||||||
Each line has the format
|
|
||||||
.Ev VARIABLE=VALUE .
|
|
||||||
If the value consists of more than one line, each line is prefixed with
|
|
||||||
.Ev VARIABLE= .
|
|
||||||
.Pp
|
|
||||||
The current value of a variable can be checked by running
|
|
||||||
.Dl Ic pkg_admin config-var VARIABLE
|
|
||||||
.Pp
|
|
||||||
Some variables are overriden by environmental variables of the same name.
|
|
||||||
Those are marked by (*).
|
|
||||||
.Pp
|
|
||||||
The following variables are supported:
|
|
||||||
.Bl -tag -width indent
|
|
||||||
.It Dv ACCEPTABLE_LICENSES
|
|
||||||
List of licenses packages are allowed to carry.
|
|
||||||
License names are case-sensitive.
|
|
||||||
.It Dv ACTIVE_FTP
|
|
||||||
Force the use of active FTP.
|
|
||||||
.It Dv CACHE_INDEX
|
|
||||||
Cache directory listenings in memory.
|
|
||||||
This avoids retransfers of the large directory index for HTTP and is
|
|
||||||
enabled by default.
|
|
||||||
.It Dv CERTIFICATE_ANCHOR_PKGS
|
|
||||||
Path to the file containing the certificates used for validating
|
|
||||||
binary packages.
|
|
||||||
A package is trusted when a certificate chain ends in one of the
|
|
||||||
certificates contained in this file.
|
|
||||||
The certificates must be PEM-encoded.
|
|
||||||
.It Dv CERTIFICATE_ANCHOR_PKGVULN
|
|
||||||
Analogous to
|
|
||||||
.Dv CERTIFICATE_ANCHOR_PKGS .
|
|
||||||
The
|
|
||||||
.Pa pkg-vulnerabilities
|
|
||||||
is trusted when a certificate chain ends in one of the certificates
|
|
||||||
contained in this file.
|
|
||||||
.It Dv CERTIFICATE_CHAIN
|
|
||||||
Path to a file containing additional certificates that can be used
|
|
||||||
for completing certificate chains when validating binary packages or
|
|
||||||
pkg-vulnerabilities files.
|
|
||||||
.It Dv CHECK_LICENSE
|
|
||||||
Check the license conditions of packages before installing them.
|
|
||||||
Supported values are:
|
|
||||||
.Bl -tag -width interactiveXX
|
|
||||||
.It Dv no
|
|
||||||
The check is not performed.
|
|
||||||
.It Dv yes
|
|
||||||
The check is performed if the package has license conditions set.
|
|
||||||
.It Dv always
|
|
||||||
Passing the license check is required.
|
|
||||||
Missing license conditions are considered an error.
|
|
||||||
.El
|
|
||||||
.It Dv CHECK_END_OF_FILE
|
|
||||||
During vulnerability checks, consider packages that have reached end-of-life
|
|
||||||
as vulnerable.
|
|
||||||
This option is enabled by default.
|
|
||||||
.It Dv CHECK_VULNERABILITIES
|
|
||||||
Check for vulnerabilities when installing packages.
|
|
||||||
Supported values are:
|
|
||||||
.Bl -tag -width interactiveXX
|
|
||||||
.It Dv never
|
|
||||||
No check is performed.
|
|
||||||
.It Dv always
|
|
||||||
Passing the vulnerability check is required.
|
|
||||||
A missing pkg-vulnerabilities file is considered an error.
|
|
||||||
.It Dv interactive
|
|
||||||
The user is always asked to confirm installation of vulnerable packages.
|
|
||||||
.El
|
|
||||||
.It Dv CONFIG_CACHE_CONNECTIONS
|
|
||||||
Limit the global connection cache to this value.
|
|
||||||
For FTP this is the number of sessions without active command.
|
|
||||||
For HTTP this is the number of connections open with keep-alive.
|
|
||||||
.It Dv CONFIG_CACHE_CONNECTIONS_HOST
|
|
||||||
Like
|
|
||||||
.Dv CONFIG_CACHE_CONNECTIONS ,
|
|
||||||
but limit the number of connections to the host as well.
|
|
||||||
See
|
|
||||||
.Xr fetch 3
|
|
||||||
for further details
|
|
||||||
.It Dv DEFAULT_ACCEPTABLE_LICENSES
|
|
||||||
List of common Free and Open Source licenses packages are allowed to carry.
|
|
||||||
The default value contains all OSI approved licenses in pkgsrc on the date
|
|
||||||
pkg_install was released.
|
|
||||||
License names are case-sensitive.
|
|
||||||
.It Dv GPG
|
|
||||||
Path to
|
|
||||||
.Xr gpg 1 ,
|
|
||||||
which can be used to verify the signature in the
|
|
||||||
.Pa pkg-vulnerabilities
|
|
||||||
file when running
|
|
||||||
.Dl Ic pkg_admin check-pkg-vulnerabilities -s
|
|
||||||
or
|
|
||||||
.Dl Ic pkg_admin fetch-pkg-vulnerabilities -s
|
|
||||||
It can also be used to verify and sign binary packages.
|
|
||||||
.It Dv GPG_KEYRING_PKGVULN
|
|
||||||
Non-default keyring to use for verifying GPG signatures of
|
|
||||||
.Pa pkg-vulnerabilities .
|
|
||||||
.It Dv GPG_KEYRING_SIGN
|
|
||||||
Non-default keyring to use for signing packages with GPG.
|
|
||||||
.It Dv GPG_KEYRING_VERIFY
|
|
||||||
Non-default keyring to use for verifying GPG signature of packages.
|
|
||||||
.It Dv GPG_SIGN_AS
|
|
||||||
User-id to use for signing packages.
|
|
||||||
.It Dv IGNORE_PROXY
|
|
||||||
Use direct connections and ignore
|
|
||||||
.Ev FTP_PROXY
|
|
||||||
and
|
|
||||||
.Ev HTTP_PROXY .
|
|
||||||
.It Dv IGNORE_URL
|
|
||||||
One line per advisory which should be ignored when running
|
|
||||||
.Dl Ic pkg_admin audit
|
|
||||||
The URL from the
|
|
||||||
.Pa pkg-vulnerabilities
|
|
||||||
file should be used as value.
|
|
||||||
.It Dv PKG_DBDIR (*)
|
|
||||||
Location of the packages database.
|
|
||||||
This option is always overriden by the argument of the
|
|
||||||
.Fl K
|
|
||||||
option.
|
|
||||||
.It Dv PKG_PATH (*)
|
|
||||||
Search path for packages.
|
|
||||||
The entries are separated by semicolon.
|
|
||||||
Each entry specifies a directory or URL to search for packages.
|
|
||||||
.It Dv PKG_REFCOUNT_DBDIR (*)
|
|
||||||
Location of the package reference counts database directory.
|
|
||||||
The default value is
|
|
||||||
.Pa ${PKG_DBDIR}.refcount .
|
|
||||||
.It Dv PKGVULNDIR
|
|
||||||
Directory name in which the
|
|
||||||
.Pa pkg-vulnerabilities
|
|
||||||
file resides.
|
|
||||||
Default is
|
|
||||||
.Pa ${PKG_DBDIR} .
|
|
||||||
.It Dv PKGVULNURL
|
|
||||||
URL which is used for updating the local
|
|
||||||
.Pa pkg-vulnerabilities
|
|
||||||
file when running
|
|
||||||
.Dl Ic pkg_admin fetch-pkg-vulnerabilities
|
|
||||||
The default location is ftp.NetBSD.org using HTTP.
|
|
||||||
.Em Note :
|
|
||||||
Usually, only the compression type should be changed.
|
|
||||||
Currently supported are uncompressed files and files compressed by
|
|
||||||
.Xr bzip2 1
|
|
||||||
.Pq Pa .bz2
|
|
||||||
or
|
|
||||||
.Xr gzip 1
|
|
||||||
.Pq Pa .gz .
|
|
||||||
.It Dv VERBOSE_NETIO
|
|
||||||
Log details of network IO to stderr.
|
|
||||||
.It Dv VERIFIED_INSTALLATION
|
|
||||||
Set trust level used when installation.
|
|
||||||
Supported values are:
|
|
||||||
.Bl -tag -width interactiveXX
|
|
||||||
.It Dv never
|
|
||||||
No signature checks are performed.
|
|
||||||
.It Dv always
|
|
||||||
A valid signature is required.
|
|
||||||
If the binary package can not be verified, the installation is terminated
|
|
||||||
.It Dv trusted
|
|
||||||
A valid signature is required.
|
|
||||||
If the binary package can not be verified, the user is asked interactively.
|
|
||||||
.It Dv interactive
|
|
||||||
The user is always asked interactively when installing a package.
|
|
||||||
.El
|
|
||||||
.El
|
|
||||||
.Sh FILES
|
|
||||||
.Bl -tag -width ".Pa @SYSCONFDIR@/pkg_install.conf"
|
|
||||||
.It Pa @SYSCONFDIR@/pkg_install.conf
|
|
||||||
Default location for the file described in this manual page.
|
|
||||||
.El
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr pkg_add 1 ,
|
|
||||||
.Xr pkg_admin 1
|
|
||||||
.Xr pkg_create 1 ,
|
|
||||||
.Xr pkg_delete 1 ,
|
|
||||||
.Xr pkg_info 1
|
|
|
@ -1,173 +0,0 @@
|
||||||
PKG_INSTALL.CONF(5) NetBSD File Formats Manual PKG_INSTALL.CONF(5)
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
ppkkgg__iinnssttaallll..ccoonnff -- configuration file for package installation tools
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
The file ppkkgg__iinnssttaallll..ccoonnff contains system defaults for the package
|
|
||||||
installation tools as a list of variable-value pairs. Each line has the
|
|
||||||
format VARIABLE=VALUE. If the value consists of more than one line, each
|
|
||||||
line is prefixed with VARIABLE=.
|
|
||||||
|
|
||||||
The current value of a variable can be checked by running
|
|
||||||
ppkkgg__aaddmmiinn ccoonnffiigg--vvaarr VVAARRIIAABBLLEE
|
|
||||||
|
|
||||||
Some variables are overriden by environmental variables of the same name.
|
|
||||||
Those are marked by (*).
|
|
||||||
|
|
||||||
The following variables are supported:
|
|
||||||
|
|
||||||
ACCEPTABLE_LICENSES
|
|
||||||
List of licenses packages are allowed to carry. License names
|
|
||||||
are case-sensitive.
|
|
||||||
|
|
||||||
ACTIVE_FTP
|
|
||||||
Force the use of active FTP.
|
|
||||||
|
|
||||||
CACHE_INDEX
|
|
||||||
Cache directory listenings in memory. This avoids retransfers of
|
|
||||||
the large directory index for HTTP and is enabled by default.
|
|
||||||
|
|
||||||
CERTIFICATE_ANCHOR_PKGS
|
|
||||||
Path to the file containing the certificates used for validating
|
|
||||||
binary packages. A package is trusted when a certificate chain
|
|
||||||
ends in one of the certificates contained in this file. The cer-
|
|
||||||
tificates must be PEM-encoded.
|
|
||||||
|
|
||||||
CERTIFICATE_ANCHOR_PKGVULN
|
|
||||||
Analogous to CERTIFICATE_ANCHOR_PKGS. The _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s is
|
|
||||||
trusted when a certificate chain ends in one of the certificates
|
|
||||||
contained in this file.
|
|
||||||
|
|
||||||
CERTIFICATE_CHAIN
|
|
||||||
Path to a file containing additional certificates that can be
|
|
||||||
used for completing certificate chains when validating binary
|
|
||||||
packages or pkg-vulnerabilities files.
|
|
||||||
|
|
||||||
CHECK_LICENSE
|
|
||||||
Check the license conditions of packages before installing them.
|
|
||||||
Supported values are:
|
|
||||||
|
|
||||||
no The check is not performed.
|
|
||||||
|
|
||||||
yes The check is performed if the package has license
|
|
||||||
conditions set.
|
|
||||||
|
|
||||||
always Passing the license check is required. Missing
|
|
||||||
license conditions are considered an error.
|
|
||||||
|
|
||||||
CHECK_END_OF_FILE
|
|
||||||
During vulnerability checks, consider packages that have reached
|
|
||||||
end-of-life as vulnerable. This option is enabled by default.
|
|
||||||
|
|
||||||
CHECK_VULNERABILITIES
|
|
||||||
Check for vulnerabilities when installing packages. Supported
|
|
||||||
values are:
|
|
||||||
|
|
||||||
never No check is performed.
|
|
||||||
|
|
||||||
always Passing the vulnerability check is required. A
|
|
||||||
missing pkg-vulnerabilities file is considered an
|
|
||||||
error.
|
|
||||||
|
|
||||||
interactive The user is always asked to confirm installation
|
|
||||||
of vulnerable packages.
|
|
||||||
|
|
||||||
CONFIG_CACHE_CONNECTIONS
|
|
||||||
Limit the global connection cache to this value. For FTP this is
|
|
||||||
the number of sessions without active command. For HTTP this is
|
|
||||||
the number of connections open with keep-alive.
|
|
||||||
|
|
||||||
CONFIG_CACHE_CONNECTIONS_HOST
|
|
||||||
Like CONFIG_CACHE_CONNECTIONS, but limit the number of connec-
|
|
||||||
tions to the host as well. See fetch(3) for further details
|
|
||||||
|
|
||||||
DEFAULT_ACCEPTABLE_LICENSES
|
|
||||||
List of common Free and Open Source licenses packages are allowed
|
|
||||||
to carry. The default value contains all OSI approved licenses
|
|
||||||
in pkgsrc on the date pkg_install was released. License names
|
|
||||||
are case-sensitive.
|
|
||||||
|
|
||||||
GPG Path to gpg(1), which can be used to verify the signature in the
|
|
||||||
_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file when running
|
|
||||||
ppkkgg__aaddmmiinn cchheecckk--ppkkgg--vvuullnneerraabbiilliittiieess --ss
|
|
||||||
or
|
|
||||||
ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess --ss
|
|
||||||
It can also be used to verify and sign binary packages.
|
|
||||||
|
|
||||||
GPG_KEYRING_PKGVULN
|
|
||||||
Non-default keyring to use for verifying GPG signatures of
|
|
||||||
_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s.
|
|
||||||
|
|
||||||
GPG_KEYRING_SIGN
|
|
||||||
Non-default keyring to use for signing packages with GPG.
|
|
||||||
|
|
||||||
GPG_KEYRING_VERIFY
|
|
||||||
Non-default keyring to use for verifying GPG signature of pack-
|
|
||||||
ages.
|
|
||||||
|
|
||||||
GPG_SIGN_AS
|
|
||||||
User-id to use for signing packages.
|
|
||||||
|
|
||||||
IGNORE_PROXY
|
|
||||||
Use direct connections and ignore FTP_PROXY and HTTP_PROXY.
|
|
||||||
|
|
||||||
IGNORE_URL
|
|
||||||
One line per advisory which should be ignored when running
|
|
||||||
ppkkgg__aaddmmiinn aauuddiitt
|
|
||||||
The URL from the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file should be used as
|
|
||||||
value.
|
|
||||||
|
|
||||||
PKG_DBDIR (*)
|
|
||||||
Location of the packages database. This option is always overri-
|
|
||||||
den by the argument of the --KK option.
|
|
||||||
|
|
||||||
PKG_PATH (*)
|
|
||||||
Search path for packages. The entries are separated by semi-
|
|
||||||
colon. Each entry specifies a directory or URL to search for
|
|
||||||
packages.
|
|
||||||
|
|
||||||
PKG_REFCOUNT_DBDIR (*)
|
|
||||||
Location of the package reference counts database directory. The
|
|
||||||
default value is _$_{_P_K_G___D_B_D_I_R_}_._r_e_f_c_o_u_n_t.
|
|
||||||
|
|
||||||
PKGVULNDIR
|
|
||||||
Directory name in which the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file resides.
|
|
||||||
Default is _$_{_P_K_G___D_B_D_I_R_}.
|
|
||||||
|
|
||||||
PKGVULNURL
|
|
||||||
URL which is used for updating the local _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file
|
|
||||||
when running
|
|
||||||
ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess
|
|
||||||
The default location is ftp.NetBSD.org using HTTP. _N_o_t_e: Usu-
|
|
||||||
ally, only the compression type should be changed. Currently
|
|
||||||
supported are uncompressed files and files compressed by bzip2(1)
|
|
||||||
(_._b_z_2) or gzip(1) (_._g_z).
|
|
||||||
|
|
||||||
VERBOSE_NETIO
|
|
||||||
Log details of network IO to stderr.
|
|
||||||
|
|
||||||
VERIFIED_INSTALLATION
|
|
||||||
Set trust level used when installation. Supported values are:
|
|
||||||
|
|
||||||
never No signature checks are performed.
|
|
||||||
|
|
||||||
always A valid signature is required. If the binary
|
|
||||||
package can not be verified, the installation is
|
|
||||||
terminated
|
|
||||||
|
|
||||||
trusted A valid signature is required. If the binary
|
|
||||||
package can not be verified, the user is asked
|
|
||||||
interactively.
|
|
||||||
|
|
||||||
interactive The user is always asked interactively when
|
|
||||||
installing a package.
|
|
||||||
|
|
||||||
FFIILLEESS
|
|
||||||
/etc/pkg_install.conf Default location for the file described in
|
|
||||||
this manual page.
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
pkg_add(1), pkg_admin(1) pkg_create(1), pkg_delete(1), pkg_info(1)
|
|
||||||
|
|
||||||
NetBSD 5.0 June 16, 2010 NetBSD 5.0
|
|
|
@ -1,173 +0,0 @@
|
||||||
PKG_INSTALL.CONF(5) NetBSD File Formats Manual PKG_INSTALL.CONF(5)
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
ppkkgg__iinnssttaallll..ccoonnff -- configuration file for package installation tools
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
The file ppkkgg__iinnssttaallll..ccoonnff contains system defaults for the package
|
|
||||||
installation tools as a list of variable-value pairs. Each line has the
|
|
||||||
format VARIABLE=VALUE. If the value consists of more than one line, each
|
|
||||||
line is prefixed with VARIABLE=.
|
|
||||||
|
|
||||||
The current value of a variable can be checked by running
|
|
||||||
ppkkgg__aaddmmiinn ccoonnffiigg--vvaarr VVAARRIIAABBLLEE
|
|
||||||
|
|
||||||
Some variables are overriden by environmental variables of the same name.
|
|
||||||
Those are marked by (*).
|
|
||||||
|
|
||||||
The following variables are supported:
|
|
||||||
|
|
||||||
ACCEPTABLE_LICENSES
|
|
||||||
List of licenses packages are allowed to carry. License names
|
|
||||||
are case-sensitive.
|
|
||||||
|
|
||||||
ACTIVE_FTP
|
|
||||||
Force the use of active FTP.
|
|
||||||
|
|
||||||
CACHE_INDEX
|
|
||||||
Cache directory listenings in memory. This avoids retransfers of
|
|
||||||
the large directory index for HTTP and is enabled by default.
|
|
||||||
|
|
||||||
CERTIFICATE_ANCHOR_PKGS
|
|
||||||
Path to the file containing the certificates used for validating
|
|
||||||
binary packages. A package is trusted when a certificate chain
|
|
||||||
ends in one of the certificates contained in this file. The cer-
|
|
||||||
tificates must be PEM-encoded.
|
|
||||||
|
|
||||||
CERTIFICATE_ANCHOR_PKGVULN
|
|
||||||
Analogous to CERTIFICATE_ANCHOR_PKGS. The _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s is
|
|
||||||
trusted when a certificate chain ends in one of the certificates
|
|
||||||
contained in this file.
|
|
||||||
|
|
||||||
CERTIFICATE_CHAIN
|
|
||||||
Path to a file containing additional certificates that can be
|
|
||||||
used for completing certificate chains when validating binary
|
|
||||||
packages or pkg-vulnerabilities files.
|
|
||||||
|
|
||||||
CHECK_LICENSE
|
|
||||||
Check the license conditions of packages before installing them.
|
|
||||||
Supported values are:
|
|
||||||
|
|
||||||
no The check is not performed.
|
|
||||||
|
|
||||||
yes The check is performed if the package has license
|
|
||||||
conditions set.
|
|
||||||
|
|
||||||
always Passing the license check is required. Missing
|
|
||||||
license conditions are considered an error.
|
|
||||||
|
|
||||||
CHECK_END_OF_FILE
|
|
||||||
During vulnerability checks, consider packages that have reached
|
|
||||||
end-of-life as vulnerable. This option is enabled by default.
|
|
||||||
|
|
||||||
CHECK_VULNERABILITIES
|
|
||||||
Check for vulnerabilities when installing packages. Supported
|
|
||||||
values are:
|
|
||||||
|
|
||||||
never No check is performed.
|
|
||||||
|
|
||||||
always Passing the vulnerability check is required. A
|
|
||||||
missing pkg-vulnerabilities file is considered an
|
|
||||||
error.
|
|
||||||
|
|
||||||
interactive The user is always asked to confirm installation
|
|
||||||
of vulnerable packages.
|
|
||||||
|
|
||||||
CONFIG_CACHE_CONNECTIONS
|
|
||||||
Limit the global connection cache to this value. For FTP this is
|
|
||||||
the number of sessions without active command. For HTTP this is
|
|
||||||
the number of connections open with keep-alive.
|
|
||||||
|
|
||||||
CONFIG_CACHE_CONNECTIONS_HOST
|
|
||||||
Like CONFIG_CACHE_CONNECTIONS, but limit the number of connec-
|
|
||||||
tions to the host as well. See fetch(3) for further details
|
|
||||||
|
|
||||||
DEFAULT_ACCEPTABLE_LICENSES
|
|
||||||
List of common Free and Open Source licenses packages are allowed
|
|
||||||
to carry. The default value contains all OSI approved licenses
|
|
||||||
in pkgsrc on the date pkg_install was released. License names
|
|
||||||
are case-sensitive.
|
|
||||||
|
|
||||||
GPG Path to gpg(1), which can be used to verify the signature in the
|
|
||||||
_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file when running
|
|
||||||
ppkkgg__aaddmmiinn cchheecckk--ppkkgg--vvuullnneerraabbiilliittiieess --ss
|
|
||||||
or
|
|
||||||
ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess --ss
|
|
||||||
It can also be used to verify and sign binary packages.
|
|
||||||
|
|
||||||
GPG_KEYRING_PKGVULN
|
|
||||||
Non-default keyring to use for verifying GPG signatures of
|
|
||||||
_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s.
|
|
||||||
|
|
||||||
GPG_KEYRING_SIGN
|
|
||||||
Non-default keyring to use for signing packages with GPG.
|
|
||||||
|
|
||||||
GPG_KEYRING_VERIFY
|
|
||||||
Non-default keyring to use for verifying GPG signature of pack-
|
|
||||||
ages.
|
|
||||||
|
|
||||||
GPG_SIGN_AS
|
|
||||||
User-id to use for signing packages.
|
|
||||||
|
|
||||||
IGNORE_PROXY
|
|
||||||
Use direct connections and ignore FTP_PROXY and HTTP_PROXY.
|
|
||||||
|
|
||||||
IGNORE_URL
|
|
||||||
One line per advisory which should be ignored when running
|
|
||||||
ppkkgg__aaddmmiinn aauuddiitt
|
|
||||||
The URL from the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file should be used as
|
|
||||||
value.
|
|
||||||
|
|
||||||
PKG_DBDIR (*)
|
|
||||||
Location of the packages database. This option is always overri-
|
|
||||||
den by the argument of the --KK option.
|
|
||||||
|
|
||||||
PKG_PATH (*)
|
|
||||||
Search path for packages. The entries are separated by semi-
|
|
||||||
colon. Each entry specifies a directory or URL to search for
|
|
||||||
packages.
|
|
||||||
|
|
||||||
PKG_REFCOUNT_DBDIR (*)
|
|
||||||
Location of the package reference counts database directory. The
|
|
||||||
default value is _$_{_P_K_G___D_B_D_I_R_}_._r_e_f_c_o_u_n_t.
|
|
||||||
|
|
||||||
PKGVULNDIR
|
|
||||||
Directory name in which the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file resides.
|
|
||||||
Default is _$_{_P_K_G___D_B_D_I_R_}.
|
|
||||||
|
|
||||||
PKGVULNURL
|
|
||||||
URL which is used for updating the local _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file
|
|
||||||
when running
|
|
||||||
ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess
|
|
||||||
The default location is ftp.NetBSD.org using HTTP. _N_o_t_e: Usu-
|
|
||||||
ally, only the compression type should be changed. Currently
|
|
||||||
supported are uncompressed files and files compressed by bzip2(1)
|
|
||||||
(_._b_z_2) or gzip(1) (_._g_z).
|
|
||||||
|
|
||||||
VERBOSE_NETIO
|
|
||||||
Log details of network IO to stderr.
|
|
||||||
|
|
||||||
VERIFIED_INSTALLATION
|
|
||||||
Set trust level used when installation. Supported values are:
|
|
||||||
|
|
||||||
never No signature checks are performed.
|
|
||||||
|
|
||||||
always A valid signature is required. If the binary
|
|
||||||
package can not be verified, the installation is
|
|
||||||
terminated
|
|
||||||
|
|
||||||
trusted A valid signature is required. If the binary
|
|
||||||
package can not be verified, the user is asked
|
|
||||||
interactively.
|
|
||||||
|
|
||||||
interactive The user is always asked interactively when
|
|
||||||
installing a package.
|
|
||||||
|
|
||||||
FFIILLEESS
|
|
||||||
@SYSCONFDIR@/pkg_install.conf Default location for the file described in
|
|
||||||
this manual page.
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
pkg_add(1), pkg_admin(1) pkg_create(1), pkg_delete(1), pkg_info(1)
|
|
||||||
|
|
||||||
NetBSD 5.0 June 16, 2010 NetBSD 5.0
|
|
|
@ -1,387 +0,0 @@
|
||||||
/* $NetBSD: pkg_io.c,v 1.11 2010/04/20 00:39:13 joerg Exp $ */
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: pkg_io.c,v 1.11 2010/04/20 00:39:13 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <archive.h>
|
|
||||||
#include <archive_entry.h>
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#include <fetch.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
struct pkg_path {
|
|
||||||
TAILQ_ENTRY(pkg_path) pl_link;
|
|
||||||
char *pl_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
static char *orig_cwd, *last_toplevel;
|
|
||||||
static TAILQ_HEAD(, pkg_path) pkg_path = TAILQ_HEAD_INITIALIZER(pkg_path);
|
|
||||||
|
|
||||||
struct fetch_archive {
|
|
||||||
struct url *url;
|
|
||||||
fetchIO *fetch;
|
|
||||||
char buffer[32768];
|
|
||||||
off_t size;
|
|
||||||
int restart;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
fetch_archive_open(struct archive *a, void *client_data)
|
|
||||||
{
|
|
||||||
struct fetch_archive *f = client_data;
|
|
||||||
struct url_stat us;
|
|
||||||
|
|
||||||
f->fetch = fetchXGet(f->url, &us, fetch_flags);
|
|
||||||
if (f->fetch == NULL)
|
|
||||||
return ENOENT;
|
|
||||||
f->size = us.size;
|
|
||||||
f->restart = 1;
|
|
||||||
f->url->offset = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
fetch_archive_read(struct archive *a, void *client_data,
|
|
||||||
const void **buffer)
|
|
||||||
{
|
|
||||||
struct fetch_archive *f = client_data;
|
|
||||||
struct url_stat us;
|
|
||||||
ssize_t rv;
|
|
||||||
|
|
||||||
*buffer = f->buffer;
|
|
||||||
rv = fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer));
|
|
||||||
if (rv > 0) {
|
|
||||||
f->url->offset += rv;
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
if (f->restart == 0)
|
|
||||||
return rv;
|
|
||||||
if (rv == 0) {
|
|
||||||
if (f->size == -1)
|
|
||||||
return 0;
|
|
||||||
if (f->url->offset == f->size)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
f->restart = 0;
|
|
||||||
if (1) {
|
|
||||||
char *url = fetchStringifyURL(f->url);
|
|
||||||
fprintf(stderr, "Trying to reconnect %s\n", url);
|
|
||||||
free(url);
|
|
||||||
}
|
|
||||||
fetchIO_close(f->fetch);
|
|
||||||
f->fetch = fetchXGet(f->url, &us, fetch_flags);
|
|
||||||
if (f->fetch == NULL)
|
|
||||||
return -1;
|
|
||||||
if (us.size != f->size)
|
|
||||||
return -1;
|
|
||||||
rv = fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer));
|
|
||||||
if (rv > 0)
|
|
||||||
f->url->offset += rv;
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
fetch_archive_close(struct archive *a, void *client_data)
|
|
||||||
{
|
|
||||||
struct fetch_archive *f = client_data;
|
|
||||||
|
|
||||||
if (f->fetch != NULL)
|
|
||||||
fetchIO_close(f->fetch);
|
|
||||||
fetchFreeURL(f->url);
|
|
||||||
free(f);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct archive *
|
|
||||||
open_archive_by_url(struct url *url, char **archive_name)
|
|
||||||
{
|
|
||||||
struct fetch_archive *f;
|
|
||||||
struct archive *a;
|
|
||||||
|
|
||||||
f = xmalloc(sizeof(*f));
|
|
||||||
f->url = fetchCopyURL(url);
|
|
||||||
|
|
||||||
*archive_name = fetchStringifyURL(url);
|
|
||||||
|
|
||||||
a = archive_read_new();
|
|
||||||
archive_read_support_compression_all(a);
|
|
||||||
archive_read_support_format_all(a);
|
|
||||||
if (archive_read_open(a, f, fetch_archive_open, fetch_archive_read,
|
|
||||||
fetch_archive_close)) {
|
|
||||||
free(*archive_name);
|
|
||||||
*archive_name = NULL;
|
|
||||||
archive_read_finish(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct archive *
|
|
||||||
open_archive(const char *url, char **archive_name)
|
|
||||||
{
|
|
||||||
struct url *u;
|
|
||||||
struct archive *a;
|
|
||||||
|
|
||||||
*archive_name = NULL;
|
|
||||||
|
|
||||||
if (!IS_URL(url)) {
|
|
||||||
a = archive_read_new();
|
|
||||||
archive_read_support_compression_all(a);
|
|
||||||
archive_read_support_format_all(a);
|
|
||||||
if (archive_read_open_filename(a, url, 1024)) {
|
|
||||||
archive_read_close(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*archive_name = xstrdup(url);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((u = fetchParseURL(url)) == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
a = open_archive_by_url(u, archive_name);
|
|
||||||
|
|
||||||
fetchFreeURL(u);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
strip_suffix(char *filename)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
len = strlen(filename);
|
|
||||||
if (len <= 4)
|
|
||||||
return 0;
|
|
||||||
if (strcmp(filename + len - 4, ".tgz") == 0 ||
|
|
||||||
strcmp(filename + len - 4, ".tbz") == 0) {
|
|
||||||
filename[len - 4] = '\0';
|
|
||||||
return 1;
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
find_best_package_int(struct url *url, const char *pattern,
|
|
||||||
struct url **best_url)
|
|
||||||
{
|
|
||||||
char *cur_match, *url_pattern, *best_match = NULL;
|
|
||||||
struct url_list ue;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (*best_url) {
|
|
||||||
if ((best_match = fetchUnquoteFilename(*best_url)) == NULL)
|
|
||||||
return -1;
|
|
||||||
} else
|
|
||||||
best_match = NULL;
|
|
||||||
|
|
||||||
if (best_match && strip_suffix(best_match) == 0) {
|
|
||||||
free(best_match);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; pattern[i] != '\0'; ++i) {
|
|
||||||
if (!isalnum((unsigned char)(pattern[i])) &&
|
|
||||||
(pattern[i]) != '-')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
url_pattern = xasprintf("%*.*s*", (int)i, (int)i, pattern);
|
|
||||||
|
|
||||||
fetchInitURLList(&ue);
|
|
||||||
if (fetchList(&ue, url, url_pattern, fetch_flags)) {
|
|
||||||
char *base_url;
|
|
||||||
base_url = fetchStringifyURL(url);
|
|
||||||
warnx("Can't process %s/%s: %s", base_url, url_pattern,
|
|
||||||
fetchLastErrString);
|
|
||||||
free(base_url);
|
|
||||||
free(url_pattern);
|
|
||||||
fetchFreeURLList(&ue);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free(url_pattern);
|
|
||||||
|
|
||||||
for (i = 0; i < ue.length; ++i) {
|
|
||||||
cur_match = fetchUnquoteFilename(ue.urls + i);
|
|
||||||
|
|
||||||
if (cur_match == NULL) {
|
|
||||||
free(best_match);
|
|
||||||
fetchFreeURLList(&ue);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (strip_suffix(cur_match) == 0) {
|
|
||||||
free(cur_match);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pkg_order(pattern, cur_match, best_match) == 1) {
|
|
||||||
if (*best_url)
|
|
||||||
fetchFreeURL(*best_url);
|
|
||||||
*best_url = fetchCopyURL(ue.urls + i);
|
|
||||||
free(best_match);
|
|
||||||
best_match = cur_match;
|
|
||||||
cur_match = NULL;
|
|
||||||
if (*best_url == NULL) {
|
|
||||||
free(best_match);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(cur_match);
|
|
||||||
}
|
|
||||||
free(best_match);
|
|
||||||
fetchFreeURLList(&ue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
process_pkg_path(void)
|
|
||||||
{
|
|
||||||
char cwd[PATH_MAX];
|
|
||||||
int relative_path;
|
|
||||||
struct pkg_path *pl;
|
|
||||||
const char *start, *next;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (getcwd(cwd, sizeof(cwd)) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "getcwd failed");
|
|
||||||
|
|
||||||
orig_cwd = xstrdup(cwd);
|
|
||||||
|
|
||||||
if (config_pkg_path == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (start = config_pkg_path; *start; start = next) {
|
|
||||||
len = strcspn(start, ";");
|
|
||||||
if (*(next = start + len) != '\0')
|
|
||||||
++next;
|
|
||||||
|
|
||||||
relative_path = !IS_FULLPATH(start) && !IS_URL(start);
|
|
||||||
pl = xmalloc(sizeof(*pl));
|
|
||||||
pl->pl_path = xasprintf("%s%s%*.*s",
|
|
||||||
relative_path ? cwd : "", len && relative_path ? "/" : "",
|
|
||||||
(int)len, (int)len, start);
|
|
||||||
TAILQ_INSERT_TAIL(&pkg_path, pl, pl_link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct url *
|
|
||||||
find_best_package(const char *toplevel, const char *pattern, int do_path)
|
|
||||||
{
|
|
||||||
struct url *url, *best_match = NULL;
|
|
||||||
struct pkg_path *pl;
|
|
||||||
|
|
||||||
if (toplevel) {
|
|
||||||
url = fetchParseURL(last_toplevel);
|
|
||||||
if (url != NULL) {
|
|
||||||
find_best_package_int(url, pattern, &best_match);
|
|
||||||
/* XXX Check return value and complain */
|
|
||||||
fetchFreeURL(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!do_path)
|
|
||||||
return best_match;
|
|
||||||
|
|
||||||
TAILQ_FOREACH(pl, &pkg_path, pl_link) {
|
|
||||||
url = fetchParseURL(pl->pl_path);
|
|
||||||
if (url != NULL) {
|
|
||||||
find_best_package_int(url, pattern, &best_match);
|
|
||||||
/* XXX Check return value and complain */
|
|
||||||
fetchFreeURL(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return best_match;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct archive *
|
|
||||||
find_archive(const char *fname, int top_level, char **archive_name)
|
|
||||||
{
|
|
||||||
struct archive *a;
|
|
||||||
struct url *best_match;
|
|
||||||
char *full_fname, *last_slash;
|
|
||||||
int search_path;
|
|
||||||
|
|
||||||
search_path = 0;
|
|
||||||
if (IS_FULLPATH(fname) || IS_URL(fname)) {
|
|
||||||
full_fname = xstrdup(fname);
|
|
||||||
} else {
|
|
||||||
if (strchr(fname, '/') == NULL)
|
|
||||||
search_path = 1;
|
|
||||||
full_fname = xasprintf("%s/%s", orig_cwd, fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_slash = strrchr(full_fname, '/');
|
|
||||||
if (top_level) {
|
|
||||||
free(last_toplevel);
|
|
||||||
*last_slash = '\0';
|
|
||||||
last_toplevel = xstrdup(full_fname);
|
|
||||||
*last_slash = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
a = open_archive(full_fname, archive_name);
|
|
||||||
if (a != NULL) {
|
|
||||||
free(full_fname);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
fname = last_slash + 1;
|
|
||||||
*last_slash = '\0';
|
|
||||||
|
|
||||||
best_match = find_best_package(full_fname, fname, 0);
|
|
||||||
|
|
||||||
if (search_path && best_match == NULL)
|
|
||||||
best_match = find_best_package(last_toplevel, fname, 1);
|
|
||||||
|
|
||||||
free(full_fname);
|
|
||||||
|
|
||||||
if (best_match == NULL)
|
|
||||||
return NULL;
|
|
||||||
a = open_archive_by_url(best_match, archive_name);
|
|
||||||
fetchFreeURL(best_match);
|
|
||||||
return a;
|
|
||||||
}
|
|
|
@ -1,748 +0,0 @@
|
||||||
/* $NetBSD: pkg_signature.c,v 1.10 2010/02/20 04:40:03 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: pkg_signature.c,v 1.10 2010/02/20 04:40:03 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
#include <ctype.h>
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#if defined(NETBSD)
|
|
||||||
#include <sha2.h>
|
|
||||||
#elif defined(__minix)
|
|
||||||
#include <minix/sha2.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/sha2.h>
|
|
||||||
#endif
|
|
||||||
#include <signal.h>
|
|
||||||
#if defined(NETBSD) || defined(__minix)
|
|
||||||
#include <unistd.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <archive.h>
|
|
||||||
#include <archive_entry.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#define HASH_FNAME "+PKG_HASH"
|
|
||||||
#define SIGNATURE_FNAME "+PKG_SIGNATURE"
|
|
||||||
#define GPG_SIGNATURE_FNAME "+PKG_GPG_SIGNATURE"
|
|
||||||
|
|
||||||
struct signature_archive {
|
|
||||||
struct archive *archive;
|
|
||||||
off_t pkg_size;
|
|
||||||
size_t sign_block_len, sign_block_number, sign_cur_block;
|
|
||||||
char **sign_blocks;
|
|
||||||
unsigned char *sign_buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
hash_block(unsigned char *buf, size_t buf_len,
|
|
||||||
char hash[SHA512_DIGEST_STRING_LENGTH])
|
|
||||||
{
|
|
||||||
unsigned char digest[SHA512_DIGEST_LENGTH];
|
|
||||||
SHA512_CTX hash_ctx;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
SHA512_Init(&hash_ctx);
|
|
||||||
SHA512_Update(&hash_ctx, buf, buf_len);
|
|
||||||
SHA512_Final(digest, &hash_ctx);
|
|
||||||
for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) {
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
c = digest[i] / 16;
|
|
||||||
if (c < 10)
|
|
||||||
hash[2 * i] = '0' + c;
|
|
||||||
else
|
|
||||||
hash[2 * i] = 'a' - 10 + c;
|
|
||||||
|
|
||||||
c = digest[i] % 16;
|
|
||||||
if (c < 10)
|
|
||||||
hash[2 * i + 1] = '0' + c;
|
|
||||||
else
|
|
||||||
hash[2 * i + 1] = 'a' - 10 + c;
|
|
||||||
}
|
|
||||||
hash[2 * i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
verify_signature_read_cb(struct archive *archive, void *cookie, const void **buf)
|
|
||||||
{
|
|
||||||
struct signature_archive *state = cookie;
|
|
||||||
char hash[SHA512_DIGEST_STRING_LENGTH];
|
|
||||||
ssize_t len, expected;
|
|
||||||
|
|
||||||
if (state->sign_cur_block >= state->sign_block_number)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* The following works for sign_block_len > 1 */
|
|
||||||
if (state->sign_cur_block + 1 == state->sign_block_number)
|
|
||||||
expected = state->pkg_size % state->sign_block_len;
|
|
||||||
else
|
|
||||||
expected = state->sign_block_len;
|
|
||||||
|
|
||||||
len = archive_read_data(state->archive, state->sign_buf, expected);
|
|
||||||
if (len != expected) {
|
|
||||||
warnx("Short read from package");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash_block(state->sign_buf, len, hash);
|
|
||||||
|
|
||||||
if (strcmp(hash, state->sign_blocks[state->sign_cur_block]) != 0) {
|
|
||||||
#ifndef __minix
|
|
||||||
warnx("Invalid signature of block %llu",
|
|
||||||
(unsigned long long)state->sign_cur_block);
|
|
||||||
#else
|
|
||||||
warnx("Invalid signature of block %lu",
|
|
||||||
(unsigned long)state->sign_cur_block);
|
|
||||||
#endif
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
++state->sign_cur_block;
|
|
||||||
*buf = state->sign_buf;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_signature_int(struct signature_archive *state)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (state->sign_blocks != NULL) {
|
|
||||||
for (i = 0; i < state->sign_block_number; ++i)
|
|
||||||
free(state->sign_blocks[i]);
|
|
||||||
}
|
|
||||||
free(state->sign_blocks);
|
|
||||||
free(state->sign_buf);
|
|
||||||
free(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
verify_signature_close_cb(struct archive *archive, void *cookie)
|
|
||||||
{
|
|
||||||
struct signature_archive *state = cookie;
|
|
||||||
|
|
||||||
archive_read_finish(state->archive);
|
|
||||||
free_signature_int(state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
read_file_from_archive(const char *archive_name, struct archive *archive,
|
|
||||||
struct archive_entry **entry,
|
|
||||||
const char *fname, char **content, size_t *len)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
*content = NULL;
|
|
||||||
*len = 0;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
if (*entry == NULL &&
|
|
||||||
(r = archive_read_next_header(archive, entry)) != ARCHIVE_OK) {
|
|
||||||
if (r == ARCHIVE_FATAL) {
|
|
||||||
warnx("Cannot read from archive `%s': %s",
|
|
||||||
archive_name, archive_error_string(archive));
|
|
||||||
} else {
|
|
||||||
warnx("Premature end of archive `%s'", archive_name);
|
|
||||||
}
|
|
||||||
*entry = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (strcmp(archive_entry_pathname(*entry), "//") == 0) {
|
|
||||||
archive_read_data_skip(archive);
|
|
||||||
*entry = NULL;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(fname, archive_entry_pathname(*entry)) != 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (archive_entry_size(*entry) > SSIZE_MAX - 1) {
|
|
||||||
warnx("Signature of archive `%s' too large to process",
|
|
||||||
archive_name);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
*len = archive_entry_size(*entry);
|
|
||||||
*content = xmalloc(*len + 1);
|
|
||||||
|
|
||||||
if (archive_read_data(archive, *content, *len) != (ssize_t)*len) {
|
|
||||||
warnx("Cannot read complete %s from archive `%s'", fname,
|
|
||||||
archive_name);
|
|
||||||
free(*content);
|
|
||||||
*len = 0;
|
|
||||||
*content = NULL;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
(*content)[*len] = '\0';
|
|
||||||
*entry = NULL;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
parse_hash_file(const char *hash_file, char **pkgname,
|
|
||||||
struct signature_archive *state)
|
|
||||||
{
|
|
||||||
static const char block1[] = "pkgsrc signature\n\nversion: 1\npkgname: ";
|
|
||||||
static const char block2[] = "algorithm: SHA512\nblock size: ";
|
|
||||||
static const char block3[] = "file size: ";
|
|
||||||
static const char block4[] = "end pkgsrc signature\n";
|
|
||||||
char *next;
|
|
||||||
size_t i, len;
|
|
||||||
|
|
||||||
*pkgname = NULL;
|
|
||||||
|
|
||||||
if (strncmp(hash_file, block1, strlen(block1)) != 0)
|
|
||||||
goto cleanup;
|
|
||||||
hash_file += strlen(block1);
|
|
||||||
|
|
||||||
len = strcspn(hash_file, "\n");
|
|
||||||
*pkgname = xmalloc(len + 1);
|
|
||||||
memcpy(*pkgname, hash_file, len);
|
|
||||||
(*pkgname)[len] = '\0';
|
|
||||||
for (i = 0; i < len; ++i) {
|
|
||||||
if (!isgraph((unsigned char)(*pkgname)[i]))
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
hash_file += len + 1;
|
|
||||||
|
|
||||||
if (strncmp(hash_file, block2, strlen(block2)) != 0)
|
|
||||||
goto cleanup;
|
|
||||||
hash_file += strlen(block2);
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
if (!isdigit((unsigned char)*hash_file))
|
|
||||||
goto cleanup;
|
|
||||||
state->sign_block_len = strtoul(hash_file, &next, 10);
|
|
||||||
hash_file = next;
|
|
||||||
|
|
||||||
/* Assert sane minimum block size of 1KB */
|
|
||||||
if (*hash_file++ != '\n' || errno == ERANGE || state->sign_block_len < 1024)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (strncmp(hash_file, block3, strlen(block3)) != 0)
|
|
||||||
goto cleanup;
|
|
||||||
hash_file += strlen(block3);
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
if (!isdigit((unsigned char)*hash_file))
|
|
||||||
goto cleanup;
|
|
||||||
#ifndef __minix
|
|
||||||
if (/* CONSTCOND */sizeof(off_t) >= sizeof(long long))
|
|
||||||
state->pkg_size = strtoll(hash_file, &next, 10);
|
|
||||||
else
|
|
||||||
state->pkg_size = strtol(hash_file, &next, 10);
|
|
||||||
#else
|
|
||||||
state->pkg_size = strtol(hash_file, &next, 10);
|
|
||||||
#endif
|
|
||||||
hash_file = next;
|
|
||||||
if (*hash_file++ != '\n' || errno == ERANGE || state->pkg_size < 1)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (*hash_file++ != '\n')
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if (state->pkg_size / state->sign_block_len > SSIZE_MAX)
|
|
||||||
goto cleanup;
|
|
||||||
state->sign_block_number = (state->pkg_size +
|
|
||||||
state->sign_block_len - 1) / state->sign_block_len;
|
|
||||||
|
|
||||||
state->sign_buf = xmalloc(state->sign_block_len);
|
|
||||||
state->sign_blocks = xcalloc(state->sign_block_number, sizeof(char *));
|
|
||||||
|
|
||||||
for (i = 0; i < state->sign_block_number; ++i) {
|
|
||||||
len = strspn(hash_file, "01234567889abcdef");
|
|
||||||
if (len != SHA512_DIGEST_LENGTH * 2 || hash_file[len] != '\n')
|
|
||||||
goto cleanup_hashes;
|
|
||||||
state->sign_blocks[i] = xmalloc(len + 1);
|
|
||||||
memcpy(state->sign_blocks[i], hash_file, len);
|
|
||||||
state->sign_blocks[i][len] = '\0';
|
|
||||||
hash_file += len + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(hash_file, block4) != 0)
|
|
||||||
goto cleanup_hashes;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cleanup_hashes:
|
|
||||||
for (i = 0; i < state->sign_block_number; ++i)
|
|
||||||
free(state->sign_blocks[i]);
|
|
||||||
free(state->sign_blocks);
|
|
||||||
state->sign_blocks = NULL;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
warnx("Unknown format of hash file");
|
|
||||||
free(*pkgname);
|
|
||||||
*pkgname = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pkg_verify_signature(const char *archive_name, struct archive **archive,
|
|
||||||
struct archive_entry **entry, char **pkgname)
|
|
||||||
{
|
|
||||||
struct signature_archive *state;
|
|
||||||
struct archive_entry *my_entry;
|
|
||||||
struct archive *a;
|
|
||||||
char *hash_file, *signature_file;
|
|
||||||
size_t hash_len, signature_len;
|
|
||||||
int r, has_sig;
|
|
||||||
|
|
||||||
*pkgname = NULL;
|
|
||||||
|
|
||||||
state = xmalloc(sizeof(*state));
|
|
||||||
state->sign_blocks = NULL;
|
|
||||||
state->sign_buf = NULL;
|
|
||||||
state->archive = NULL;
|
|
||||||
|
|
||||||
r = read_file_from_archive(archive_name, *archive, entry, HASH_FNAME,
|
|
||||||
&hash_file, &hash_len);
|
|
||||||
if (r == -1) {
|
|
||||||
archive_read_finish(*archive);
|
|
||||||
*archive = NULL;
|
|
||||||
free(state);
|
|
||||||
goto no_valid_signature;
|
|
||||||
} else if (r == 1) {
|
|
||||||
free(state);
|
|
||||||
goto no_valid_signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_hash_file(hash_file, pkgname, state))
|
|
||||||
goto no_valid_signature;
|
|
||||||
|
|
||||||
r = read_file_from_archive(archive_name, *archive, entry, SIGNATURE_FNAME,
|
|
||||||
&signature_file, &signature_len);
|
|
||||||
if (r == -1) {
|
|
||||||
archive_read_finish(*archive);
|
|
||||||
*archive = NULL;
|
|
||||||
free(state);
|
|
||||||
free(hash_file);
|
|
||||||
goto no_valid_signature;
|
|
||||||
} else if (r != 0) {
|
|
||||||
if (*entry != NULL)
|
|
||||||
r = read_file_from_archive(archive_name, *archive,
|
|
||||||
entry, GPG_SIGNATURE_FNAME,
|
|
||||||
&signature_file, &signature_len);
|
|
||||||
if (r == -1) {
|
|
||||||
archive_read_finish(*archive);
|
|
||||||
*archive = NULL;
|
|
||||||
free(state);
|
|
||||||
free(hash_file);
|
|
||||||
goto no_valid_signature;
|
|
||||||
} else if (r != 0) {
|
|
||||||
free(hash_file);
|
|
||||||
free(state);
|
|
||||||
goto no_valid_signature;
|
|
||||||
}
|
|
||||||
has_sig = !detached_gpg_verify(hash_file, hash_len,
|
|
||||||
signature_file, signature_len, gpg_keyring_verify);
|
|
||||||
|
|
||||||
free(signature_file);
|
|
||||||
} else {
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file,
|
|
||||||
signature_len, certs_packages, 1);
|
|
||||||
|
|
||||||
free(signature_file);
|
|
||||||
#else
|
|
||||||
warnx("No OpenSSL support compiled in, skipping signature");
|
|
||||||
has_sig = 0;
|
|
||||||
free(signature_file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
r = archive_read_next_header(*archive, &my_entry);
|
|
||||||
if (r != ARCHIVE_OK) {
|
|
||||||
warnx("Cannot read inner package: %s",
|
|
||||||
archive_error_string(*archive));
|
|
||||||
free_signature_int(state);
|
|
||||||
goto no_valid_signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (archive_entry_size(my_entry) != state->pkg_size) {
|
|
||||||
warnx("Package size doesn't match signature");
|
|
||||||
free_signature_int(state);
|
|
||||||
goto no_valid_signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->archive = *archive;
|
|
||||||
|
|
||||||
a = archive_read_new();
|
|
||||||
archive_read_support_compression_all(a);
|
|
||||||
archive_read_support_format_all(a);
|
|
||||||
if (archive_read_open(a, state, NULL, verify_signature_read_cb,
|
|
||||||
verify_signature_close_cb)) {
|
|
||||||
warnx("Can't open signed package file");
|
|
||||||
archive_read_finish(a);
|
|
||||||
goto no_valid_signature;
|
|
||||||
}
|
|
||||||
*archive = a;
|
|
||||||
*entry = NULL;
|
|
||||||
|
|
||||||
return has_sig ? 0 : -1;
|
|
||||||
|
|
||||||
no_valid_signature:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
pkg_full_signature_check(const char *archive_name, struct archive **archive)
|
|
||||||
{
|
|
||||||
struct archive_entry *entry = NULL;
|
|
||||||
char *pkgname;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
if (pkg_verify_signature(archive_name, archive, &entry, &pkgname))
|
|
||||||
return -1;
|
|
||||||
if (pkgname == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* XXX read PLIST and compare pkgname */
|
|
||||||
while ((r = archive_read_next_header(*archive, &entry)) == ARCHIVE_OK)
|
|
||||||
archive_read_data_skip(*archive);
|
|
||||||
|
|
||||||
free(pkgname);
|
|
||||||
return r == ARCHIVE_EOF ? 0 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
extract_pkgname(int fd)
|
|
||||||
{
|
|
||||||
package_t plist;
|
|
||||||
plist_t *p;
|
|
||||||
struct archive *a;
|
|
||||||
struct archive_entry *entry;
|
|
||||||
char *buf;
|
|
||||||
ssize_t len;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
a = archive_read_new();
|
|
||||||
archive_read_support_compression_all(a);
|
|
||||||
archive_read_support_format_all(a);
|
|
||||||
if (archive_read_open_fd(a, fd, 1024)) {
|
|
||||||
warnx("Cannot open binary package: %s",
|
|
||||||
archive_error_string(a));
|
|
||||||
archive_read_finish(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = archive_read_next_header(a, &entry);
|
|
||||||
if (r != ARCHIVE_OK) {
|
|
||||||
warnx("Cannot extract package name: %s",
|
|
||||||
r == ARCHIVE_EOF ? "EOF" : archive_error_string(a));
|
|
||||||
archive_read_finish(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (strcmp(archive_entry_pathname(entry), "+CONTENTS") != 0) {
|
|
||||||
warnx("Invalid binary package, doesn't start with +CONTENTS");
|
|
||||||
archive_read_finish(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
if (archive_entry_size(entry) > SSIZE_MAX - 1) {
|
|
||||||
warnx("+CONTENTS too large to process");
|
|
||||||
archive_read_finish(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
len = archive_entry_size(entry);
|
|
||||||
buf = xmalloc(len + 1);
|
|
||||||
|
|
||||||
if (archive_read_data(a, buf, len) != len) {
|
|
||||||
warnx("Short read when extracing +CONTENTS");
|
|
||||||
free(buf);
|
|
||||||
archive_read_finish(a);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
buf[len] = '\0';
|
|
||||||
|
|
||||||
archive_read_finish(a);
|
|
||||||
|
|
||||||
parse_plist(&plist, buf);
|
|
||||||
free(buf);
|
|
||||||
p = find_plist(&plist, PLIST_NAME);
|
|
||||||
if (p != NULL) {
|
|
||||||
buf = xstrdup(p->name);
|
|
||||||
} else {
|
|
||||||
warnx("Invalid PLIST: missing @name");
|
|
||||||
buf = NULL;
|
|
||||||
}
|
|
||||||
free_plist(&plist);
|
|
||||||
|
|
||||||
if (lseek(fd, 0, SEEK_SET) != 0) {
|
|
||||||
warn("Cannot seek in archive");
|
|
||||||
free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
static const char hash_template[] =
|
|
||||||
"pkgsrc signature\n"
|
|
||||||
"\n"
|
|
||||||
"version: 1\n"
|
|
||||||
"pkgname: %s\n"
|
|
||||||
"algorithm: SHA512\n"
|
|
||||||
"block size: 65536\n"
|
|
||||||
"file size: %lld\n"
|
|
||||||
"\n";
|
|
||||||
#else
|
|
||||||
static const char hash_template[] =
|
|
||||||
"pkgsrc signature\n"
|
|
||||||
"\n"
|
|
||||||
"version: 1\n"
|
|
||||||
"pkgname: %s\n"
|
|
||||||
"algorithm: SHA512\n"
|
|
||||||
"block size: 65536\n"
|
|
||||||
"file size: %ld\n"
|
|
||||||
"\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char hash_trailer[] = "end pkgsrc signature\n";
|
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
void
|
|
||||||
pkg_sign_x509(const char *name, const char *output, const char *key_file, const char *cert_file)
|
|
||||||
{
|
|
||||||
struct archive *pkg;
|
|
||||||
struct archive_entry *entry, *hash_entry, *sign_entry;
|
|
||||||
int fd;
|
|
||||||
struct stat sb;
|
|
||||||
char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH];
|
|
||||||
unsigned char block[65536];
|
|
||||||
off_t i, size;
|
|
||||||
size_t block_len, signature_len;
|
|
||||||
|
|
||||||
if ((fd = open(name, O_RDONLY)) == -1)
|
|
||||||
err(EXIT_FAILURE, "Cannot open binary package %s", name);
|
|
||||||
if (fstat(fd, &sb) == -1)
|
|
||||||
err(EXIT_FAILURE, "Cannot stat %s", name);
|
|
||||||
|
|
||||||
entry = archive_entry_new();
|
|
||||||
archive_entry_copy_stat(entry, &sb);
|
|
||||||
|
|
||||||
pkgname = extract_pkgname(fd);
|
|
||||||
hash_file = xasprintf(hash_template, pkgname,
|
|
||||||
(long long)archive_entry_size(entry));
|
|
||||||
free(pkgname);
|
|
||||||
|
|
||||||
for (i = 0; i < archive_entry_size(entry); i += block_len) {
|
|
||||||
if (i + (off_t)sizeof(block) < archive_entry_size(entry))
|
|
||||||
block_len = sizeof(block);
|
|
||||||
else
|
|
||||||
block_len = archive_entry_size(entry) % sizeof(block);
|
|
||||||
if (read(fd, block, block_len) != (ssize_t)block_len)
|
|
||||||
err(2, "short read");
|
|
||||||
hash_block(block, block_len, hash);
|
|
||||||
tmp = xasprintf("%s%s\n", hash_file, hash);
|
|
||||||
free(hash_file);
|
|
||||||
hash_file = tmp;
|
|
||||||
}
|
|
||||||
tmp = xasprintf("%s%s", hash_file, hash_trailer);
|
|
||||||
free(hash_file);
|
|
||||||
hash_file = tmp;
|
|
||||||
|
|
||||||
if (easy_pkcs7_sign(hash_file, strlen(hash_file), &signature_file,
|
|
||||||
&signature_len, key_file, cert_file))
|
|
||||||
err(EXIT_FAILURE, "Cannot sign hash file");
|
|
||||||
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
sign_entry = archive_entry_clone(entry);
|
|
||||||
hash_entry = archive_entry_clone(entry);
|
|
||||||
pkgname = strrchr(name, '/');
|
|
||||||
archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name);
|
|
||||||
archive_entry_set_pathname(hash_entry, HASH_FNAME);
|
|
||||||
archive_entry_set_pathname(sign_entry, SIGNATURE_FNAME);
|
|
||||||
archive_entry_set_size(hash_entry, strlen(hash_file));
|
|
||||||
archive_entry_set_size(sign_entry, signature_len);
|
|
||||||
|
|
||||||
pkg = archive_write_new();
|
|
||||||
archive_write_set_compression_none(pkg);
|
|
||||||
archive_write_set_format_ar_bsd(pkg);
|
|
||||||
archive_write_open_filename(pkg, output);
|
|
||||||
|
|
||||||
archive_write_header(pkg, hash_entry);
|
|
||||||
archive_write_data(pkg, hash_file, strlen(hash_file));
|
|
||||||
archive_write_finish_entry(pkg);
|
|
||||||
archive_entry_free(hash_entry);
|
|
||||||
|
|
||||||
archive_write_header(pkg, sign_entry);
|
|
||||||
archive_write_data(pkg, signature_file, signature_len);
|
|
||||||
archive_write_finish_entry(pkg);
|
|
||||||
archive_entry_free(sign_entry);
|
|
||||||
|
|
||||||
size = archive_entry_size(entry);
|
|
||||||
archive_write_header(pkg, entry);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i += block_len) {
|
|
||||||
if (i + (off_t)sizeof(block) < size)
|
|
||||||
block_len = sizeof(block);
|
|
||||||
else
|
|
||||||
block_len = size % sizeof(block);
|
|
||||||
if (read(fd, block, block_len) != (ssize_t)block_len)
|
|
||||||
err(2, "short read");
|
|
||||||
archive_write_data(pkg, block, block_len);
|
|
||||||
}
|
|
||||||
archive_write_finish_entry(pkg);
|
|
||||||
archive_entry_free(entry);
|
|
||||||
|
|
||||||
archive_write_finish(pkg);
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
pkg_sign_gpg(const char *name, const char *output)
|
|
||||||
{
|
|
||||||
struct archive *pkg;
|
|
||||||
struct archive_entry *entry, *hash_entry, *sign_entry;
|
|
||||||
int fd;
|
|
||||||
struct stat sb;
|
|
||||||
char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH];
|
|
||||||
unsigned char block[65536];
|
|
||||||
off_t i, size;
|
|
||||||
size_t block_len, signature_len;
|
|
||||||
|
|
||||||
if ((fd = open(name, O_RDONLY)) == -1)
|
|
||||||
err(EXIT_FAILURE, "Cannot open binary package %s", name);
|
|
||||||
if (fstat(fd, &sb) == -1)
|
|
||||||
err(EXIT_FAILURE, "Cannot stat %s", name);
|
|
||||||
|
|
||||||
entry = archive_entry_new();
|
|
||||||
archive_entry_copy_stat(entry, &sb);
|
|
||||||
|
|
||||||
pkgname = extract_pkgname(fd);
|
|
||||||
#ifndef __minix
|
|
||||||
hash_file = xasprintf(hash_template, pkgname,
|
|
||||||
(long long)archive_entry_size(entry));
|
|
||||||
#else
|
|
||||||
hash_file = xasprintf(hash_template, pkgname,
|
|
||||||
archive_entry_size(entry));
|
|
||||||
#endif
|
|
||||||
free(pkgname);
|
|
||||||
|
|
||||||
for (i = 0; i < archive_entry_size(entry); i += block_len) {
|
|
||||||
if (i + (off_t)sizeof(block) < archive_entry_size(entry))
|
|
||||||
block_len = sizeof(block);
|
|
||||||
else
|
|
||||||
block_len = archive_entry_size(entry) % sizeof(block);
|
|
||||||
if (read(fd, block, block_len) != (ssize_t)block_len)
|
|
||||||
err(2, "short read");
|
|
||||||
hash_block(block, block_len, hash);
|
|
||||||
tmp = xasprintf("%s%s\n", hash_file, hash);
|
|
||||||
free(hash_file);
|
|
||||||
hash_file = tmp;
|
|
||||||
}
|
|
||||||
tmp = xasprintf("%s%s", hash_file, hash_trailer);
|
|
||||||
free(hash_file);
|
|
||||||
hash_file = tmp;
|
|
||||||
|
|
||||||
if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file,
|
|
||||||
&signature_len, gpg_keyring_sign, gpg_sign_as))
|
|
||||||
err(EXIT_FAILURE, "Cannot sign hash file");
|
|
||||||
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
sign_entry = archive_entry_clone(entry);
|
|
||||||
hash_entry = archive_entry_clone(entry);
|
|
||||||
pkgname = strrchr(name, '/');
|
|
||||||
archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name);
|
|
||||||
archive_entry_set_pathname(hash_entry, HASH_FNAME);
|
|
||||||
archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME);
|
|
||||||
archive_entry_set_size(hash_entry, strlen(hash_file));
|
|
||||||
archive_entry_set_size(sign_entry, signature_len);
|
|
||||||
|
|
||||||
pkg = archive_write_new();
|
|
||||||
archive_write_set_compression_none(pkg);
|
|
||||||
archive_write_set_format_ar_bsd(pkg);
|
|
||||||
archive_write_open_filename(pkg, output);
|
|
||||||
|
|
||||||
archive_write_header(pkg, hash_entry);
|
|
||||||
archive_write_data(pkg, hash_file, strlen(hash_file));
|
|
||||||
archive_write_finish_entry(pkg);
|
|
||||||
archive_entry_free(hash_entry);
|
|
||||||
|
|
||||||
archive_write_header(pkg, sign_entry);
|
|
||||||
archive_write_data(pkg, signature_file, signature_len);
|
|
||||||
archive_write_finish_entry(pkg);
|
|
||||||
archive_entry_free(sign_entry);
|
|
||||||
|
|
||||||
size = archive_entry_size(entry);
|
|
||||||
archive_write_header(pkg, entry);
|
|
||||||
|
|
||||||
for (i = 0; i < size; i += block_len) {
|
|
||||||
if (i + (off_t)sizeof(block) < size)
|
|
||||||
block_len = sizeof(block);
|
|
||||||
else
|
|
||||||
block_len = size % sizeof(block);
|
|
||||||
if (read(fd, block, block_len) != (ssize_t)block_len)
|
|
||||||
err(2, "short read");
|
|
||||||
archive_write_data(pkg, block, block_len);
|
|
||||||
}
|
|
||||||
archive_write_finish_entry(pkg);
|
|
||||||
archive_entry_free(entry);
|
|
||||||
|
|
||||||
archive_write_finish(pkg);
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
PKG_SUMMARY(5) NetBSD File Formats Manual PKG_SUMMARY(5)
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
ppkkgg__ssuummmmaarryy -- summary of binary package repository
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
The file ppkkgg__ssuummmmaarryy contains information about each package in a binary
|
|
||||||
package repository as a list of variable-value pairs. The variables
|
|
||||||
describing different packages are separated by one empty line. Each line
|
|
||||||
has the format VARIABLE=VALUE. If the value consists of more than one
|
|
||||||
line, each line is prefixed with VARIABLE=. Multi-line variables are
|
|
||||||
guaranteed to be in consecutive lines.
|
|
||||||
|
|
||||||
The following variables are used:
|
|
||||||
|
|
||||||
BUILD_DATE
|
|
||||||
(required) The date and time when the package was built.
|
|
||||||
|
|
||||||
CATEGORIES
|
|
||||||
(required) A list of categories which this package fits in, sepa-
|
|
||||||
rated by space.
|
|
||||||
|
|
||||||
COMMENT
|
|
||||||
(required) A one-line description of the package.
|
|
||||||
|
|
||||||
CONFLICTS
|
|
||||||
(optional) A list of dewey patterns of packages the package con-
|
|
||||||
flicts with, one per line. If missing, this package has no con-
|
|
||||||
flicts.
|
|
||||||
|
|
||||||
DEPENDS
|
|
||||||
(optional) A list of dewey patterns of packages the package
|
|
||||||
depends on, one per line. If missing, this package has no depen-
|
|
||||||
dencies.
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
(required) A more detailed description of the package.
|
|
||||||
|
|
||||||
FILE_NAME
|
|
||||||
(optional) The name of the binary package file. If not given,
|
|
||||||
_P_K_G_N_A_M_E_._t_g_z can be assumed.
|
|
||||||
|
|
||||||
FILE_SIZE
|
|
||||||
(optional) The size of the binary package file, in bytes.
|
|
||||||
|
|
||||||
HOMEPAGE
|
|
||||||
(optional) A URL where more information about the package can be
|
|
||||||
found.
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
(optional) The type of license this package is distributed under.
|
|
||||||
If empty or missing, it is OSI-approved.
|
|
||||||
|
|
||||||
MACHINE_ARCH
|
|
||||||
(required) The architecture on which the package was compiled.
|
|
||||||
|
|
||||||
OPSYS (required) The operating system on which the package was com-
|
|
||||||
piled.
|
|
||||||
|
|
||||||
OS_VERSION
|
|
||||||
(required) The version of the operating system on which the pack-
|
|
||||||
age was compiled.
|
|
||||||
|
|
||||||
PKG_OPTIONS
|
|
||||||
(optional) Any options selected to compile this package. If
|
|
||||||
missing, the package does not support options.
|
|
||||||
|
|
||||||
PKGNAME
|
|
||||||
(required) The name of the package.
|
|
||||||
|
|
||||||
PKGPATH
|
|
||||||
(required) The path of the package directory within pkgsrc.
|
|
||||||
|
|
||||||
PKGTOOLS_VERSION
|
|
||||||
(required) The version of the package tools used to create the
|
|
||||||
package.
|
|
||||||
|
|
||||||
PREV_PKGPATH
|
|
||||||
(optional) The previous path of the package directory within
|
|
||||||
pkgsrc when a package was moved. (See SUPERSEDES below for a
|
|
||||||
renamed package.)
|
|
||||||
|
|
||||||
PROVIDES
|
|
||||||
(optional) A list of shared libraries provided by the package,
|
|
||||||
including major version number, one per line. If missing, this
|
|
||||||
package does not provide shared libraries.
|
|
||||||
|
|
||||||
REQUIRES
|
|
||||||
(optional) A list of shared libraries needed by the package,
|
|
||||||
including major version number, one per line. If missing, this
|
|
||||||
package does not require shared libraries.
|
|
||||||
|
|
||||||
SIZE_PKG
|
|
||||||
(required) The size of the package when installed, in bytes.
|
|
||||||
|
|
||||||
SUPERSEDES
|
|
||||||
(optional) A list of dewey patterns of previous packages this
|
|
||||||
package replaces, one per line. This is used for package renam-
|
|
||||||
ing.
|
|
||||||
|
|
||||||
The ppkkgg__ssuummmmaarryy file can be generated using the pkg_info(1) --XX option.
|
|
||||||
For example, the following will list this data for all installed pack-
|
|
||||||
ages:
|
|
||||||
|
|
||||||
pkg_info -X -a
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
pkg_info(1)
|
|
||||||
|
|
||||||
HHIISSTTOORRYY
|
|
||||||
The ppkkgg__ssuummmmaarryy format was first officially documented in April 2006.
|
|
||||||
|
|
||||||
NetBSD 5.0 April 11, 2009 NetBSD 5.0
|
|
|
@ -1,343 +0,0 @@
|
||||||
/* $NetBSD: pkgdb.c,v 1.39 2010/04/20 21:22:38 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: pkgdb.c,v 1.39 2010/04/20 21:22:38 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 1999-2010 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Hubert Feyrer <hubert@feyrer.de>.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(NETBSD) || defined(__minix)
|
|
||||||
#include <db.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/db.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDARG_H
|
|
||||||
#include <stdarg.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
#define PKGDB_FILE "pkgdb.byfile.db" /* indexed by filename */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Where we put logging information by default if PKG_DBDIR is unset.
|
|
||||||
*/
|
|
||||||
#ifndef DEF_LOG_DIR
|
|
||||||
#define DEF_LOG_DIR "/var/db/pkg"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* just in case we change the environment variable name */
|
|
||||||
#define PKG_DBDIR "PKG_DBDIR"
|
|
||||||
|
|
||||||
static DB *pkgdbp;
|
|
||||||
static char pkgdb_dir_default[] = DEF_LOG_DIR;
|
|
||||||
static char *pkgdb_dir = pkgdb_dir_default;
|
|
||||||
static int pkgdb_dir_prio = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return name of cache file in the buffer that was passed.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
pkgdb_get_database(void)
|
|
||||||
{
|
|
||||||
return xasprintf("%s/%s", pkgdb_get_dir(), PKGDB_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Open the pkg-database
|
|
||||||
* Return value:
|
|
||||||
* 1: everything ok
|
|
||||||
* 0: error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pkgdb_open(int mode)
|
|
||||||
{
|
|
||||||
BTREEINFO info;
|
|
||||||
char *cachename;
|
|
||||||
|
|
||||||
/* try our btree format first */
|
|
||||||
info.flags = 0;
|
|
||||||
info.cachesize = 2*1024*1024;
|
|
||||||
info.maxkeypage = 0;
|
|
||||||
info.minkeypage = 0;
|
|
||||||
info.psize = 4096;
|
|
||||||
info.compare = NULL;
|
|
||||||
info.prefix = NULL;
|
|
||||||
info.lorder = 0;
|
|
||||||
cachename = pkgdb_get_database();
|
|
||||||
pkgdbp = (DB *) dbopen(cachename,
|
|
||||||
(mode == ReadOnly) ? O_RDONLY : O_RDWR | O_CREAT,
|
|
||||||
0644, DB_BTREE, (void *) &info);
|
|
||||||
free(cachename);
|
|
||||||
return (pkgdbp != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close the pkg database
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pkgdb_close(void)
|
|
||||||
{
|
|
||||||
if (pkgdbp != NULL) {
|
|
||||||
(void) (*pkgdbp->close) (pkgdbp);
|
|
||||||
pkgdbp = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Store value "val" with key "key" in database
|
|
||||||
* Return value is as from ypdb_store:
|
|
||||||
* 0: ok
|
|
||||||
* 1: key already present
|
|
||||||
* -1: some other error, see errno
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pkgdb_store(const char *key, const char *val)
|
|
||||||
{
|
|
||||||
DBT keyd, vald;
|
|
||||||
|
|
||||||
if (pkgdbp == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
keyd.data = __UNCONST(key);
|
|
||||||
keyd.size = strlen(key) + 1;
|
|
||||||
vald.data = __UNCONST(val);
|
|
||||||
vald.size = strlen(val) + 1;
|
|
||||||
|
|
||||||
if (keyd.size > MaxPathSize || vald.size > MaxPathSize)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return (*pkgdbp->put) (pkgdbp, &keyd, &vald, R_NOOVERWRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Recall value for given key
|
|
||||||
* Return value:
|
|
||||||
* NULL if some error occurred or value for key not found (check errno!)
|
|
||||||
* String for "value" else
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
pkgdb_retrieve(const char *key)
|
|
||||||
{
|
|
||||||
DBT keyd, vald;
|
|
||||||
int status;
|
|
||||||
char *eos;
|
|
||||||
static int corruption_warning;
|
|
||||||
|
|
||||||
if (pkgdbp == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
keyd.data = __UNCONST(key);
|
|
||||||
keyd.size = strlen(key) + 1;
|
|
||||||
errno = 0; /* to be sure it's 0 if the key doesn't match anything */
|
|
||||||
|
|
||||||
vald.data = (void *)NULL;
|
|
||||||
vald.size = 0;
|
|
||||||
status = (*pkgdbp->get) (pkgdbp, &keyd, &vald, 0);
|
|
||||||
if (status)
|
|
||||||
return NULL;
|
|
||||||
eos = memchr(vald.data, 0, vald.size);
|
|
||||||
if (eos == NULL || eos + 1 != (char *)vald.data + vald.size) {
|
|
||||||
if (!corruption_warning) {
|
|
||||||
warnx("pkgdb corrupted, please run ``pkg_admin rebuild''");
|
|
||||||
corruption_warning = 1;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vald.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* dump contents of the database to stdout */
|
|
||||||
int
|
|
||||||
pkgdb_dump(void)
|
|
||||||
{
|
|
||||||
DBT key;
|
|
||||||
DBT val;
|
|
||||||
int type;
|
|
||||||
|
|
||||||
if (pkgdb_open(ReadOnly)) {
|
|
||||||
for (type = R_FIRST ; (*pkgdbp->seq)(pkgdbp, &key, &val, type) == 0 ; type = R_NEXT) {
|
|
||||||
printf("file: %.*s pkg: %.*s\n",
|
|
||||||
(int) key.size, (char *) key.data,
|
|
||||||
(int) val.size, (char *) val.data);
|
|
||||||
}
|
|
||||||
pkgdb_close();
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove data set from pkgdb
|
|
||||||
* Return value as ypdb_delete:
|
|
||||||
* 0: everything ok
|
|
||||||
* 1: key not present
|
|
||||||
* -1: some error occurred (see errno)
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pkgdb_remove(const char *key)
|
|
||||||
{
|
|
||||||
DBT keyd;
|
|
||||||
|
|
||||||
if (pkgdbp == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
keyd.data = __UNCONST(key);
|
|
||||||
keyd.size = strlen(key) + 1;
|
|
||||||
if (keyd.size > MaxPathSize)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return (*pkgdbp->del) (pkgdbp, &keyd, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove any entry from the cache which has a data field of `pkg'.
|
|
||||||
* Return value:
|
|
||||||
* 1: everything ok
|
|
||||||
* 0: error
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
pkgdb_remove_pkg(const char *pkg)
|
|
||||||
{
|
|
||||||
DBT data;
|
|
||||||
DBT key;
|
|
||||||
int type;
|
|
||||||
int ret;
|
|
||||||
size_t cc;
|
|
||||||
char *cachename;
|
|
||||||
|
|
||||||
if (pkgdbp == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cachename = pkgdb_get_database();
|
|
||||||
cc = strlen(pkg);
|
|
||||||
for (ret = 1, type = R_FIRST; (*pkgdbp->seq)(pkgdbp, &key, &data, type) == 0 ; type = R_NEXT) {
|
|
||||||
if ((cc + 1) == data.size && strncmp(data.data, pkg, cc) == 0) {
|
|
||||||
if (Verbose) {
|
|
||||||
printf("Removing file `%s' from %s\n", (char *)key.data, cachename);
|
|
||||||
}
|
|
||||||
switch ((*pkgdbp->del)(pkgdbp, &key, 0)) {
|
|
||||||
case -1:
|
|
||||||
warn("Error removing `%s' from %s", (char *)key.data, cachename);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
warn("Key `%s' not present in %s", (char *)key.data, cachename);
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(cachename);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the location of the package reference counts database directory.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
pkgdb_refcount_dir(void)
|
|
||||||
{
|
|
||||||
static char buf[MaxPathSize];
|
|
||||||
char *tmp;
|
|
||||||
|
|
||||||
if ((tmp = getenv(PKG_REFCOUNT_DBDIR_VNAME)) != NULL)
|
|
||||||
strlcpy(buf, tmp, sizeof(buf));
|
|
||||||
else
|
|
||||||
snprintf(buf, sizeof(buf), "%s.refcount", pkgdb_get_dir());
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return directory where pkgdb is stored
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
pkgdb_get_dir(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
return pkgdb_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the first place we look for where pkgdb is stored.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
pkgdb_set_dir(const char *dir, int prio)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (prio < pkgdb_dir_prio)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pkgdb_dir_prio = prio;
|
|
||||||
|
|
||||||
if (dir == pkgdb_dir)
|
|
||||||
return;
|
|
||||||
if (pkgdb_dir != pkgdb_dir_default)
|
|
||||||
free(pkgdb_dir);
|
|
||||||
pkgdb_dir = xstrdup(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
pkgdb_pkg_dir(const char *pkg)
|
|
||||||
{
|
|
||||||
return xasprintf("%s/%s", pkgdb_get_dir(), pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
pkgdb_pkg_file(const char *pkg, const char *file)
|
|
||||||
{
|
|
||||||
return xasprintf("%s/%s/%s", pkgdb_get_dir(), pkg, file);
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
PKGSRC(7) NetBSD Miscellaneous Information Manual PKGSRC(7)
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
ppkkggssrrcc -- NetBSD packages collection (framework for third-party software)
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
The NetBSD Packages Collection (pkgsrc) is a framework for building and
|
|
||||||
maintaining third-party software on NetBSD and other UNIX-like systems.
|
|
||||||
It is used to enable freely available software to be configured and built
|
|
||||||
easily on supported platforms.
|
|
||||||
|
|
||||||
Tools are available to install ready-to-use packages and to perform vari-
|
|
||||||
ous administrative tasks for the package system.
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
pkg_add(1), pkg_delete(1), pkg_info(1),
|
|
||||||
_h_t_t_p_:_/_/_w_w_w_._n_e_t_b_s_d_._o_r_g_/_d_o_c_s_/_p_k_g_s_r_c_/
|
|
||||||
|
|
||||||
NetBSD 5.0 March 2, 2007 NetBSD 5.0
|
|
|
@ -1,792 +0,0 @@
|
||||||
/* $NetBSD: plist.c,v 1.29 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: plist.c,v 1.29 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* General packing list routines.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if defined(NETBSD)
|
|
||||||
#include <md5.h>
|
|
||||||
#elif defined(__minix)
|
|
||||||
#include <minix/md5.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/md5.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int delete_with_parents(const char *, Boolean, Boolean);
|
|
||||||
|
|
||||||
/* This struct defines a plist command type */
|
|
||||||
typedef struct cmd_t {
|
|
||||||
const char *c_s; /* string to recognise */
|
|
||||||
pl_ent_t c_type; /* type of command */
|
|
||||||
int c_argc; /* # of arguments */
|
|
||||||
int c_subst; /* can substitute real prefix */
|
|
||||||
} cmd_t;
|
|
||||||
|
|
||||||
/* Commands to recognise */
|
|
||||||
static const cmd_t cmdv[] = {
|
|
||||||
{"cwd", PLIST_CWD, 1, 1},
|
|
||||||
{"src", PLIST_SRC, 1, 1},
|
|
||||||
{"exec", PLIST_CMD, 1, 0},
|
|
||||||
{"unexec", PLIST_UNEXEC, 1, 0},
|
|
||||||
{"mode", PLIST_CHMOD, 1, 0},
|
|
||||||
{"owner", PLIST_CHOWN, 1, 0},
|
|
||||||
{"group", PLIST_CHGRP, 1, 0},
|
|
||||||
{"comment", PLIST_COMMENT, 1, 0},
|
|
||||||
{"ignore", PLIST_IGNORE, 0, 0},
|
|
||||||
{"name", PLIST_NAME, 1, 0},
|
|
||||||
{"display", PLIST_DISPLAY, 1, 0},
|
|
||||||
{"pkgdep", PLIST_PKGDEP, 1, 0},
|
|
||||||
{"pkgcfl", PLIST_PKGCFL, 1, 0},
|
|
||||||
{"pkgdir", PLIST_PKGDIR, 1, 0},
|
|
||||||
{"dirrm", PLIST_DIR_RM, 1, 0},
|
|
||||||
{"option", PLIST_OPTION, 1, 0},
|
|
||||||
{"blddep", PLIST_BLDDEP, 1, 0},
|
|
||||||
{NULL, FAIL, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add an item to the end of a packing list
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
add_plist(package_t *p, pl_ent_t type, const char *arg)
|
|
||||||
{
|
|
||||||
plist_t *tmp;
|
|
||||||
|
|
||||||
tmp = new_plist_entry();
|
|
||||||
tmp->name = (arg == NULL) ? NULL : xstrdup(arg);
|
|
||||||
tmp->type = type;
|
|
||||||
if (!p->head) {
|
|
||||||
p->head = p->tail = tmp;
|
|
||||||
} else {
|
|
||||||
tmp->prev = p->tail;
|
|
||||||
p->tail->next = tmp;
|
|
||||||
p->tail = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add an item to the start of a packing list
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
add_plist_top(package_t *p, pl_ent_t type, const char *arg)
|
|
||||||
{
|
|
||||||
plist_t *tmp;
|
|
||||||
|
|
||||||
tmp = new_plist_entry();
|
|
||||||
tmp->name = (arg == NULL) ? NULL : xstrdup(arg);
|
|
||||||
tmp->type = type;
|
|
||||||
if (!p->head) {
|
|
||||||
p->head = p->tail = tmp;
|
|
||||||
} else {
|
|
||||||
tmp->next = p->head;
|
|
||||||
p->head->prev = tmp;
|
|
||||||
p->head = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the last (most recent) entry in a packing list
|
|
||||||
*/
|
|
||||||
plist_t *
|
|
||||||
last_plist(package_t *p)
|
|
||||||
{
|
|
||||||
return p->tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Mark all items in a packing list to prevent iteration over them
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mark_plist(package_t *pkg)
|
|
||||||
{
|
|
||||||
plist_t *pp;
|
|
||||||
|
|
||||||
for (pp = pkg->head; pp; pp = pp->next) {
|
|
||||||
pp->marked = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a given item in a packing list and, if so, return it (else NULL)
|
|
||||||
*/
|
|
||||||
plist_t *
|
|
||||||
find_plist(package_t *pkg, pl_ent_t type)
|
|
||||||
{
|
|
||||||
plist_t *pp;
|
|
||||||
|
|
||||||
for (pp = pkg->head; pp && pp->type != type; pp = pp->next) {
|
|
||||||
}
|
|
||||||
return pp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look for a specific boolean option argument in the list
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
find_plist_option(package_t *pkg, const char *name)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_OPTION
|
|
||||||
&& strcmp(p->name, name) == 0) {
|
|
||||||
return p->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (char *) NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete plist item 'type' in the list (if 'name' is non-null, match it
|
|
||||||
* too.) If 'all' is set, delete all items, not just the first occurance.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
delete_plist(package_t *pkg, Boolean all, pl_ent_t type, char *name)
|
|
||||||
{
|
|
||||||
plist_t *p = pkg->head;
|
|
||||||
|
|
||||||
while (p) {
|
|
||||||
plist_t *pnext = p->next;
|
|
||||||
|
|
||||||
if (p->type == type && (!name || !strcmp(name, p->name))) {
|
|
||||||
free(p->name);
|
|
||||||
if (p->prev)
|
|
||||||
p->prev->next = pnext;
|
|
||||||
else
|
|
||||||
pkg->head = pnext;
|
|
||||||
if (pnext)
|
|
||||||
pnext->prev = p->prev;
|
|
||||||
else
|
|
||||||
pkg->tail = p->prev;
|
|
||||||
free(p);
|
|
||||||
if (!all)
|
|
||||||
return;
|
|
||||||
p = pnext;
|
|
||||||
} else
|
|
||||||
p = p->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a new packing list entry, and return a pointer to it.
|
|
||||||
*/
|
|
||||||
plist_t *
|
|
||||||
new_plist_entry(void)
|
|
||||||
{
|
|
||||||
return xcalloc(1, sizeof(plist_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Free an entire packing list
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
free_plist(package_t *pkg)
|
|
||||||
{
|
|
||||||
plist_t *p = pkg->head;
|
|
||||||
|
|
||||||
while (p) {
|
|
||||||
plist_t *p1 = p->next;
|
|
||||||
|
|
||||||
free(p->name);
|
|
||||||
free(p);
|
|
||||||
p = p1;
|
|
||||||
}
|
|
||||||
pkg->head = pkg->tail = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For an ASCII string denoting a plist command, return its code and
|
|
||||||
* optionally its argument(s)
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
plist_cmd(const char *s, char **arg)
|
|
||||||
{
|
|
||||||
const cmd_t *cmdp;
|
|
||||||
const char *cp, *sp;
|
|
||||||
char *sp2;
|
|
||||||
|
|
||||||
sp = NULL; /* Older GCC can't detect that the loop is executed */
|
|
||||||
|
|
||||||
for (cmdp = cmdv; cmdp->c_s; ++cmdp) {
|
|
||||||
for (sp = s, cp = cmdp->c_s; *sp && *cp; ++cp, ++sp)
|
|
||||||
if (*sp != *cp)
|
|
||||||
break;
|
|
||||||
if (*cp == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmdp->c_s == NULL || arg == NULL)
|
|
||||||
return cmdp->c_type;
|
|
||||||
|
|
||||||
while (isspace((unsigned char)*sp))
|
|
||||||
++sp;
|
|
||||||
*arg = xstrdup(sp);
|
|
||||||
if (*sp) {
|
|
||||||
sp2 = *arg + strlen(*arg) - 1;
|
|
||||||
/*
|
|
||||||
* The earlier loop ensured that at least one non-whitespace
|
|
||||||
* is in the string.
|
|
||||||
*/
|
|
||||||
while (isspace((unsigned char)*sp2))
|
|
||||||
--sp2;
|
|
||||||
sp2[1] = '\0';
|
|
||||||
}
|
|
||||||
return cmdp->c_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse a packaging list from a memory buffer.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
parse_plist(package_t *pkg, const char *buf)
|
|
||||||
{
|
|
||||||
int cmd;
|
|
||||||
char *line, *cp;
|
|
||||||
const char *eol, *next;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
pkg->head = NULL;
|
|
||||||
pkg->tail = NULL;
|
|
||||||
|
|
||||||
for (; *buf; buf = next) {
|
|
||||||
/* Until add_plist can deal with trailing whitespace. */
|
|
||||||
if ((eol = strchr(buf, '\n')) != NULL) {
|
|
||||||
next = eol + 1;
|
|
||||||
len = eol - buf;
|
|
||||||
} else {
|
|
||||||
len = strlen(buf);
|
|
||||||
next = buf + len;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len && isspace((unsigned char)buf[len - 1]))
|
|
||||||
--len;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
line = xmalloc(len + 1);
|
|
||||||
memcpy(line, buf, len);
|
|
||||||
line[len] = '\0';
|
|
||||||
|
|
||||||
if (*(cp = line) == CMD_CHAR) {
|
|
||||||
if ((cmd = plist_cmd(line + 1, &cp)) == FAIL) {
|
|
||||||
warnx("Unrecognised PLIST command `%s'", line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*cp == '\0') {
|
|
||||||
free(cp);
|
|
||||||
cp = NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cmd = PLIST_FILE;
|
|
||||||
}
|
|
||||||
add_plist(pkg, cmd, cp);
|
|
||||||
free(cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read a packing list from a file
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
append_plist(package_t *pkg, FILE * fp)
|
|
||||||
{
|
|
||||||
char pline[MaxPathSize];
|
|
||||||
char *cp;
|
|
||||||
int cmd;
|
|
||||||
int len;
|
|
||||||
int free_cp;
|
|
||||||
|
|
||||||
while (fgets(pline, MaxPathSize, fp) != (char *) NULL) {
|
|
||||||
for (len = strlen(pline); len &&
|
|
||||||
isspace((unsigned char) pline[len - 1]);) {
|
|
||||||
pline[--len] = '\0';
|
|
||||||
}
|
|
||||||
if (len == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
free_cp = 0;
|
|
||||||
if (*(cp = pline) == CMD_CHAR) {
|
|
||||||
if ((cmd = plist_cmd(pline + 1, &cp)) == FAIL) {
|
|
||||||
warnx("Unrecognised PLIST command `%s'", pline);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*cp == '\0') {
|
|
||||||
free(cp);
|
|
||||||
cp = NULL;
|
|
||||||
}
|
|
||||||
free_cp = 1;
|
|
||||||
} else {
|
|
||||||
cmd = PLIST_FILE;
|
|
||||||
}
|
|
||||||
add_plist(pkg, cmd, cp);
|
|
||||||
if (free_cp)
|
|
||||||
free(cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
read_plist(package_t *pkg, FILE * fp)
|
|
||||||
{
|
|
||||||
pkg->head = NULL;
|
|
||||||
pkg->tail = NULL;
|
|
||||||
|
|
||||||
append_plist(pkg, fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write a packing list to a file, converting commands to ASCII equivs
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
write_plist(package_t *pkg, FILE * fp, char *realprefix)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
const cmd_t *cmdp;
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_FILE) {
|
|
||||||
/* Fast-track files - these are the most common */
|
|
||||||
(void) fprintf(fp, "%s\n", p->name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) {
|
|
||||||
}
|
|
||||||
if (cmdp->c_type == FAIL) {
|
|
||||||
warnx("Unknown PLIST command type %d (%s)", p->type, p->name);
|
|
||||||
} else if (cmdp->c_argc == 0) {
|
|
||||||
(void) fprintf(fp, "%c%s\n", CMD_CHAR, cmdp->c_s);
|
|
||||||
} else if (cmdp->c_subst && realprefix) {
|
|
||||||
(void) fprintf(fp, "%c%s %s\n", CMD_CHAR, cmdp->c_s, realprefix);
|
|
||||||
} else {
|
|
||||||
(void) fprintf(fp, "%c%s %s\n", CMD_CHAR, cmdp->c_s,
|
|
||||||
(p->name) ? p->name : "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Like write_plist, but compute memory string.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
stringify_plist(package_t *pkg, char **real_buf, size_t *real_len,
|
|
||||||
const char *realprefix)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
const cmd_t *cmdp;
|
|
||||||
char *buf;
|
|
||||||
size_t len;
|
|
||||||
int item_len;
|
|
||||||
|
|
||||||
/* Pass One: compute output size only. */
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_FILE) {
|
|
||||||
len += strlen(p->name) + 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) {
|
|
||||||
}
|
|
||||||
if (cmdp->c_type == FAIL)
|
|
||||||
continue;
|
|
||||||
if (cmdp->c_argc == 0)
|
|
||||||
len += 1 + strlen(cmdp->c_s) + 1;
|
|
||||||
else if (cmdp->c_subst && realprefix)
|
|
||||||
len += 1 + strlen(cmdp->c_s) + 1 + strlen(realprefix) + 1;
|
|
||||||
else
|
|
||||||
len += 1 + strlen(cmdp->c_s) + 1 + strlen(p->name ? p->name : "") + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pass Two: build actual string. */
|
|
||||||
buf = xmalloc(len + 1);
|
|
||||||
*real_buf = buf;
|
|
||||||
*real_len = len;
|
|
||||||
++len;
|
|
||||||
|
|
||||||
#define UPDATE_LEN \
|
|
||||||
do { \
|
|
||||||
if (item_len < 0 || (size_t)item_len > len) \
|
|
||||||
errx(2, "Size computation failed, aborted."); \
|
|
||||||
buf += item_len; \
|
|
||||||
len -= item_len; \
|
|
||||||
} while (/* CONSTCOND */0)
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_FILE) {
|
|
||||||
/* Fast-track files - these are the most common */
|
|
||||||
item_len = snprintf(buf, len, "%s\n", p->name);
|
|
||||||
UPDATE_LEN;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (cmdp = cmdv; cmdp->c_type != FAIL && cmdp->c_type != p->type; cmdp++) {
|
|
||||||
}
|
|
||||||
if (cmdp->c_type == FAIL) {
|
|
||||||
warnx("Unknown PLIST command type %d (%s)", p->type, p->name);
|
|
||||||
} else if (cmdp->c_argc == 0) {
|
|
||||||
item_len = snprintf(buf, len, "%c%s\n", CMD_CHAR, cmdp->c_s);
|
|
||||||
UPDATE_LEN;
|
|
||||||
} else if (cmdp->c_subst && realprefix) {
|
|
||||||
item_len = snprintf(buf, len, "%c%s %s\n", CMD_CHAR, cmdp->c_s, realprefix);
|
|
||||||
UPDATE_LEN;
|
|
||||||
} else {
|
|
||||||
item_len = snprintf(buf, len, "%c%s %s\n", CMD_CHAR, cmdp->c_s,
|
|
||||||
(p->name) ? p->name : "");
|
|
||||||
UPDATE_LEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len != 1)
|
|
||||||
errx(2, "Size computation failed, aborted.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Delete the results of a package installation.
|
|
||||||
*
|
|
||||||
* This is here rather than in the pkg_delete code because pkg_add needs to
|
|
||||||
* run it too in cases of failure.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
delete_package(Boolean ign_err, package_t *pkg, Boolean NoDeleteFiles,
|
|
||||||
const char *destdir)
|
|
||||||
{
|
|
||||||
plist_t *p;
|
|
||||||
const char *last_file = "";
|
|
||||||
int fail = SUCCESS;
|
|
||||||
Boolean preserve;
|
|
||||||
char tmp[MaxPathSize];
|
|
||||||
char cmd[MaxPathSize];
|
|
||||||
const char *prefix = NULL, *name = NULL;
|
|
||||||
|
|
||||||
if (!pkgdb_open(ReadWrite)) {
|
|
||||||
err(EXIT_FAILURE, "cannot open pkgdb");
|
|
||||||
}
|
|
||||||
|
|
||||||
preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_NAME:
|
|
||||||
name = p->name;
|
|
||||||
break;
|
|
||||||
case PLIST_CWD:
|
|
||||||
if (prefix == NULL)
|
|
||||||
prefix = p->name;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == NULL || prefix == NULL)
|
|
||||||
errx(EXIT_FAILURE, "broken PLIST");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove database entries first, directory removal is done
|
|
||||||
* in the main loop below.
|
|
||||||
*/
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
if (p->type == PLIST_PKGDIR)
|
|
||||||
delete_pkgdir(name, prefix, p->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p = pkg->head; p; p = p->next) {
|
|
||||||
switch (p->type) {
|
|
||||||
case PLIST_NAME:
|
|
||||||
/* Handled already */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PLIST_PKGDIR:
|
|
||||||
case PLIST_DIR_RM:
|
|
||||||
(void) snprintf(tmp, sizeof(tmp), "%s/%s",
|
|
||||||
prefix, p->name);
|
|
||||||
if (has_pkgdir(tmp))
|
|
||||||
continue;
|
|
||||||
(void) snprintf(tmp, sizeof(tmp), "%s%s%s/%s",
|
|
||||||
destdir ? destdir : "", destdir ? "/" : "",
|
|
||||||
prefix, p->name);
|
|
||||||
if (!fexists(tmp)) {
|
|
||||||
if (p->type == PLIST_PKGDIR)
|
|
||||||
warnx("Directory `%s' disappeared, skipping", tmp);
|
|
||||||
} else if (!isdir(tmp)) {
|
|
||||||
warnx("attempting to delete a file `%s' as a directory\n"
|
|
||||||
"this packing list is incorrect - ignoring delete request", tmp);
|
|
||||||
} else if (delete_with_parents(tmp, ign_err, TRUE))
|
|
||||||
fail = FAIL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PLIST_IGNORE:
|
|
||||||
p = p->next;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PLIST_UNEXEC:
|
|
||||||
if (NoDeleteFiles)
|
|
||||||
break;
|
|
||||||
(void) snprintf(tmp, sizeof(tmp), "%s%s%s",
|
|
||||||
destdir ? destdir : "", destdir ? "/" : "", prefix);
|
|
||||||
format_cmd(cmd, sizeof(cmd), p->name, tmp, last_file);
|
|
||||||
printf("Executing `%s'\n", cmd);
|
|
||||||
if (!Fake && system(cmd)) {
|
|
||||||
warnx("unexec command for `%s' failed", cmd);
|
|
||||||
fail = FAIL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PLIST_FILE:
|
|
||||||
last_file = p->name;
|
|
||||||
(void) snprintf(tmp, sizeof(tmp), "%s%s%s/%s",
|
|
||||||
destdir ? destdir : "", destdir ? "/" : "",
|
|
||||||
prefix, p->name);
|
|
||||||
if (isdir(tmp)) {
|
|
||||||
warnx("attempting to delete directory `%s' as a file\n"
|
|
||||||
"this packing list is incorrect - ignoring delete request", tmp);
|
|
||||||
} else {
|
|
||||||
int restored = 0; /* restored from preserve? */
|
|
||||||
|
|
||||||
if (p->next && p->next->type == PLIST_COMMENT) {
|
|
||||||
if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) {
|
|
||||||
char *cp, buf[LegibleChecksumLen];
|
|
||||||
|
|
||||||
if ((cp = MD5File(tmp, buf)) != NULL) {
|
|
||||||
/* Mismatch? */
|
|
||||||
if (strcmp(cp, p->next->name + ChecksumHeaderLen) != 0) {
|
|
||||||
printf("original MD5 checksum failed, %s: %s\n",
|
|
||||||
Force ? "deleting anyway" : "not deleting", tmp);
|
|
||||||
if (!Force) {
|
|
||||||
fail = FAIL;
|
|
||||||
goto pkgdb_cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (strncmp(p->next->name, SYMLINK_HEADER, SymlinkHeaderLen) == 0) {
|
|
||||||
char buf[MaxPathSize + SymlinkHeaderLen];
|
|
||||||
int cc;
|
|
||||||
|
|
||||||
(void) strlcpy(buf, SYMLINK_HEADER,
|
|
||||||
sizeof(buf));
|
|
||||||
if ((cc = readlink(tmp, &buf[SymlinkHeaderLen],
|
|
||||||
sizeof(buf) - SymlinkHeaderLen - 1)) < 0) {
|
|
||||||
warn("can't readlink `%s'", tmp);
|
|
||||||
goto pkgdb_cleanup;
|
|
||||||
}
|
|
||||||
buf[SymlinkHeaderLen + cc] = 0x0;
|
|
||||||
if (strcmp(buf, p->next->name) != 0) {
|
|
||||||
if ((cc = readlink(&buf[SymlinkHeaderLen], &buf[SymlinkHeaderLen],
|
|
||||||
sizeof(buf) - SymlinkHeaderLen)) < 0) {
|
|
||||||
printf("symlink %s is not same as recorded value, %s: %s\n",
|
|
||||||
buf, Force ? "deleting anyway" : "not deleting", tmp);
|
|
||||||
if (!Force) {
|
|
||||||
fail = FAIL;
|
|
||||||
goto pkgdb_cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf[SymlinkHeaderLen + cc] = 0x0;
|
|
||||||
if (strcmp(buf, p->next->name) != 0) {
|
|
||||||
printf("symlink %s is not same as recorded value, %s: %s\n",
|
|
||||||
buf, Force ? "deleting anyway" : "not deleting", tmp);
|
|
||||||
if (!Force) {
|
|
||||||
fail = FAIL;
|
|
||||||
goto pkgdb_cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Verbose && !NoDeleteFiles)
|
|
||||||
printf("Delete file %s\n", tmp);
|
|
||||||
if (!Fake && !NoDeleteFiles) {
|
|
||||||
if (delete_with_parents(tmp, ign_err, FALSE))
|
|
||||||
fail = FAIL;
|
|
||||||
if (preserve && name) {
|
|
||||||
char tmp2[MaxPathSize];
|
|
||||||
|
|
||||||
if (make_preserve_name(tmp2, MaxPathSize, name, tmp)) {
|
|
||||||
if (fexists(tmp2)) {
|
|
||||||
if (rename(tmp2, tmp))
|
|
||||||
warn("preserve: unable to restore %s as %s",
|
|
||||||
tmp2, tmp);
|
|
||||||
else
|
|
||||||
restored = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgdb_cleanup:
|
|
||||||
if (!Fake) {
|
|
||||||
if (!restored) {
|
|
||||||
errno = 0;
|
|
||||||
if (pkgdb_remove(tmp) && errno)
|
|
||||||
perror("pkgdb_remove");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pkgdb_close();
|
|
||||||
return fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Selectively delete a hierarchy
|
|
||||||
* Returns 1 on error, 0 else.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
delete_with_parents(const char *fname, Boolean ign_err, Boolean ign_nonempty)
|
|
||||||
{
|
|
||||||
char *cp, *cp2;
|
|
||||||
|
|
||||||
if (remove(fname)) {
|
|
||||||
if (!ign_err && (!ign_nonempty || errno != ENOTEMPTY))
|
|
||||||
warnx("Couldn't remove %s", fname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
cp = xstrdup(fname);
|
|
||||||
while (*cp) {
|
|
||||||
if ((cp2 = strrchr(cp, '/')) != NULL)
|
|
||||||
*cp2 = '\0';
|
|
||||||
if (!isemptydir(cp))
|
|
||||||
break;
|
|
||||||
if (has_pkgdir(cp))
|
|
||||||
break;
|
|
||||||
if (rmdir(cp))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free(cp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
add_pkgdir(const char *pkg, const char *prefix, const char *path)
|
|
||||||
{
|
|
||||||
char *fullpath, *oldvalue, *newvalue;
|
|
||||||
|
|
||||||
fullpath = xasprintf("%s/%s", prefix, path);
|
|
||||||
oldvalue = pkgdb_retrieve(fullpath);
|
|
||||||
if (oldvalue) {
|
|
||||||
if (strncmp(oldvalue, "@pkgdir ", 8) != 0)
|
|
||||||
errx(EXIT_FAILURE, "Internal error while processing pkgdb, run pkg_admin rebuild");
|
|
||||||
newvalue = xasprintf("%s %s", oldvalue, pkg);
|
|
||||||
pkgdb_remove(fullpath);
|
|
||||||
} else {
|
|
||||||
newvalue = xasprintf("@pkgdir %s", pkg);
|
|
||||||
}
|
|
||||||
pkgdb_store(fullpath, newvalue);
|
|
||||||
|
|
||||||
free(fullpath);
|
|
||||||
free(newvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delete_pkgdir(const char *pkg, const char *prefix, const char *path)
|
|
||||||
{
|
|
||||||
size_t pkg_len, len;
|
|
||||||
char *fullpath, *oldvalue, *newvalue, *iter;
|
|
||||||
|
|
||||||
fullpath = xasprintf("%s/%s", prefix, path);
|
|
||||||
oldvalue = pkgdb_retrieve(fullpath);
|
|
||||||
if (oldvalue && strncmp(oldvalue, "@pkgdir ", 8) == 0) {
|
|
||||||
newvalue = xstrdup(oldvalue);
|
|
||||||
iter = newvalue + 8;
|
|
||||||
pkg_len = strlen(pkg);
|
|
||||||
while (*iter) {
|
|
||||||
if (strncmp(iter, pkg, pkg_len) == 0 &&
|
|
||||||
(iter[pkg_len] == ' ' || iter[pkg_len] == '\0')) {
|
|
||||||
len = strlen(iter + pkg_len);
|
|
||||||
memmove(iter, iter + pkg_len + 1, len);
|
|
||||||
if (len == 0)
|
|
||||||
*iter = '\0';
|
|
||||||
} else {
|
|
||||||
iter += strcspn(iter, " ");
|
|
||||||
iter += strspn(iter, " ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pkgdb_remove(fullpath);
|
|
||||||
if (iter != newvalue + 8)
|
|
||||||
pkgdb_store(fullpath, newvalue);
|
|
||||||
free(newvalue);
|
|
||||||
}
|
|
||||||
free(fullpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
has_pkgdir(const char *path)
|
|
||||||
{
|
|
||||||
const char *value;
|
|
||||||
|
|
||||||
value = pkgdb_retrieve(path);
|
|
||||||
|
|
||||||
if (value && strncmp(value, "@pkgdir ", 8) == 0)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
/* $NetBSD: remove.c,v 1.3 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: remove.c,v 1.3 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_DIRENT_H
|
|
||||||
#include <dirent.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#if HAVE_FCNTL_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#endif
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static int
|
|
||||||
safe_fchdir(int cwd)
|
|
||||||
{
|
|
||||||
int tmp_errno, rv;
|
|
||||||
|
|
||||||
tmp_errno = errno;
|
|
||||||
rv = fchdir(cwd);
|
|
||||||
errno = tmp_errno;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
long_remove(const char **path_ptr, int missing_ok, int *did_chdir)
|
|
||||||
{
|
|
||||||
char tmp_path[PATH_MAX + 1];
|
|
||||||
const char *path;
|
|
||||||
size_t i, len;
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
path = *path_ptr;
|
|
||||||
len = strlen(path);
|
|
||||||
*did_chdir = 0;
|
|
||||||
|
|
||||||
while (len >= PATH_MAX) {
|
|
||||||
for (i = PATH_MAX - 1; i > 0; --i) {
|
|
||||||
if (path[i] == '/')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == 0) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
return -1; /* Assumes PATH_MAX > NAME_MAX */
|
|
||||||
}
|
|
||||||
memcpy(tmp_path, path, i);
|
|
||||||
tmp_path[i] = '\0';
|
|
||||||
if (chdir(tmp_path))
|
|
||||||
return -1;
|
|
||||||
*did_chdir = 1;
|
|
||||||
path += i + 1;
|
|
||||||
len -= i + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remove(path) == 0 || (errno == ENOENT && missing_ok))
|
|
||||||
rv = 0;
|
|
||||||
else
|
|
||||||
rv = -1;
|
|
||||||
|
|
||||||
*path_ptr = path;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
recursive_remove_internal(const char *path, int missing_ok, int cwd)
|
|
||||||
{
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *de;
|
|
||||||
const char *sub_path;
|
|
||||||
char *subdir;
|
|
||||||
int did_chdir, rv;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the argument is longer than PATH_MAX, long_remove
|
|
||||||
* will try to shorten it using chdir. So before returning,
|
|
||||||
* make sure to fchdir back to the original cwd.
|
|
||||||
*/
|
|
||||||
sub_path = path;
|
|
||||||
if (long_remove(&sub_path, missing_ok, &did_chdir) == 0)
|
|
||||||
rv = 0;
|
|
||||||
else if (errno != ENOTEMPTY) /* Other errors are terminal. */
|
|
||||||
rv = -1;
|
|
||||||
else
|
|
||||||
rv = 1;
|
|
||||||
|
|
||||||
if (rv != 1) {
|
|
||||||
if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0)
|
|
||||||
rv = -1;
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dir = opendir(sub_path)) == NULL) {
|
|
||||||
if (errno == EMFILE)
|
|
||||||
warn("opendir failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (did_chdir && fchdir(cwd) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
rv = 0;
|
|
||||||
|
|
||||||
while ((de = readdir(dir)) != NULL) {
|
|
||||||
if (strcmp(de->d_name, ".") == 0)
|
|
||||||
continue;
|
|
||||||
if (strcmp(de->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
subdir = xasprintf("%s/%s", path, de->d_name);
|
|
||||||
rv = recursive_remove_internal(subdir, 1, cwd);
|
|
||||||
free(subdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
safe_fchdir(cwd);
|
|
||||||
|
|
||||||
rv |= long_remove(&path, missing_ok, &did_chdir);
|
|
||||||
|
|
||||||
if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0)
|
|
||||||
rv = -1;
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
recursive_remove(const char *path, int missing_ok)
|
|
||||||
{
|
|
||||||
int orig_cwd, rv;
|
|
||||||
|
|
||||||
/* First try the easy case of regular file or empty directory. */
|
|
||||||
if (remove(path) == 0 || (errno == ENOENT && missing_ok))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the path is too long, long_remove will use chdir to shorten it,
|
|
||||||
* so remember the current directory first.
|
|
||||||
*/
|
|
||||||
if ((orig_cwd = open(".", O_RDONLY)) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
rv = recursive_remove_internal(path, missing_ok, orig_cwd);
|
|
||||||
|
|
||||||
close(orig_cwd);
|
|
||||||
return rv;
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
/* $NetBSD: str.c,v 1.26 2009/02/02 12:35:01 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: str.c,v 1.26 2009/02/02 12:35:01 joerg Exp $");
|
|
||||||
#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
|
|
||||||
* 18 July 1993
|
|
||||||
*
|
|
||||||
* Miscellaneous string utilities.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_ASSERT_H
|
|
||||||
#include <assert.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_FNMATCH_H
|
|
||||||
#include <fnmatch.h>
|
|
||||||
#endif
|
|
||||||
#include "lib.h"
|
|
||||||
#include "dewey.h"
|
|
||||||
|
|
||||||
/* pull in definitions and macros for resizing arrays as we go */
|
|
||||||
#include "defs.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the suffix portion of a path
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
suffix_of(const char *str)
|
|
||||||
{
|
|
||||||
const char *dot;
|
|
||||||
|
|
||||||
return ((dot = strrchr(basename_of(str), '.')) == NULL) ? "" : dot + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the filename portion of a path
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
basename_of(const char *str)
|
|
||||||
{
|
|
||||||
const char *slash;
|
|
||||||
|
|
||||||
return ((slash = strrchr(str, '/')) == NULL) ? str : slash + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the dirname portion of a path
|
|
||||||
*/
|
|
||||||
const char *
|
|
||||||
dirname_of(const char *path)
|
|
||||||
{
|
|
||||||
size_t cc;
|
|
||||||
char *s;
|
|
||||||
static char buf[MaxPathSize];
|
|
||||||
|
|
||||||
if ((s = strrchr(path, '/')) == NULL) {
|
|
||||||
return ".";
|
|
||||||
}
|
|
||||||
if (s == path) {
|
|
||||||
/* "/foo" -> return "/" */
|
|
||||||
return "/";
|
|
||||||
}
|
|
||||||
cc = (size_t) (s - path);
|
|
||||||
if (cc >= sizeof(buf))
|
|
||||||
errx(EXIT_FAILURE, "dirname_of: too long dirname: '%s'", path);
|
|
||||||
(void) memcpy(buf, path, cc);
|
|
||||||
buf[cc] = 0;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does the pkgname contain any of the special chars ("{[]?*<>")?
|
|
||||||
* If so, return 1, else 0
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
ispkgpattern(const char *pkg)
|
|
||||||
{
|
|
||||||
return strpbrk(pkg, "<>[]?*{") != NULL;
|
|
||||||
}
|
|
|
@ -1,349 +0,0 @@
|
||||||
/* $NetBSD: var.c,v 1.8 2009/08/02 17:56:45 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* This code is derived from software contributed to The NetBSD Foundation
|
|
||||||
* by Dieter Baron, Thomas Klausner, Johnny Lam, and Joerg Sonnenberger.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
* 3. Neither the name of The NetBSD Foundation nor the names of its
|
|
||||||
* contributors may be used to endorse or promote products derived
|
|
||||||
* from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
||||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: var.c,v 1.8 2009/08/02 17:56:45 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_ERRNO_H
|
|
||||||
#include <errno.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static const char *var_cmp(const char *, size_t, const char *, size_t);
|
|
||||||
static void var_print(FILE *, const char *, const char *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the specified varibales from the file fname to stdout.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
var_copy_list(const char *buf, const char **variables)
|
|
||||||
{
|
|
||||||
const char *eol, *next;
|
|
||||||
size_t len;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (; *buf; buf = next) {
|
|
||||||
if ((eol = strchr(buf, '\n')) != NULL) {
|
|
||||||
next = eol + 1;
|
|
||||||
len = eol - buf;
|
|
||||||
} else {
|
|
||||||
next = eol;
|
|
||||||
len = strlen(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; variables[i]; i++) {
|
|
||||||
if (var_cmp(buf, len, variables[i],
|
|
||||||
strlen(variables[i])) != NULL) {
|
|
||||||
printf("%.*s\n", (int)len, buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print the value of variable from the file fname to stdout.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
var_get(const char *fname, const char *variable)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char *line;
|
|
||||||
size_t len;
|
|
||||||
size_t varlen;
|
|
||||||
char *value;
|
|
||||||
size_t valuelen;
|
|
||||||
size_t thislen;
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
varlen = strlen(variable);
|
|
||||||
if (varlen == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
fp = fopen(fname, "r");
|
|
||||||
if (!fp) {
|
|
||||||
if (errno != ENOENT)
|
|
||||||
warn("var_get: can't open '%s' for reading", fname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = NULL;
|
|
||||||
valuelen = 0;
|
|
||||||
|
|
||||||
while ((line = fgetln(fp, &len)) != (char *) NULL) {
|
|
||||||
if (line[len - 1] == '\n')
|
|
||||||
--len;
|
|
||||||
if ((p=var_cmp(line, len, variable, varlen)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
thislen = line+len - p;
|
|
||||||
if (value) {
|
|
||||||
value = xrealloc(value, valuelen+thislen+2);
|
|
||||||
value[valuelen++] = '\n';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value = xmalloc(thislen+1);
|
|
||||||
}
|
|
||||||
sprintf(value+valuelen, "%.*s", (int)thislen, p);
|
|
||||||
valuelen += thislen;
|
|
||||||
}
|
|
||||||
(void) fclose(fp);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print the value of variable from the memory buffer to stdout.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
var_get_memory(const char *buf, const char *variable)
|
|
||||||
{
|
|
||||||
const char *eol, *next, *data;
|
|
||||||
size_t len, varlen, thislen, valuelen;
|
|
||||||
char *value;
|
|
||||||
|
|
||||||
varlen = strlen(variable);
|
|
||||||
if (varlen == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
value = NULL;
|
|
||||||
valuelen = 0;
|
|
||||||
|
|
||||||
for (; *buf; buf = next) {
|
|
||||||
if ((eol = strchr(buf, '\n')) != NULL) {
|
|
||||||
next = eol + 1;
|
|
||||||
len = eol - buf;
|
|
||||||
} else {
|
|
||||||
next = eol;
|
|
||||||
len = strlen(buf);
|
|
||||||
}
|
|
||||||
if ((data = var_cmp(buf, len, variable, varlen)) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
thislen = buf + len - data;
|
|
||||||
if (value) {
|
|
||||||
value = xrealloc(value, valuelen+thislen+2);
|
|
||||||
value[valuelen++] = '\n';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value = xmalloc(thislen+1);
|
|
||||||
}
|
|
||||||
sprintf(value + valuelen, "%.*s", (int)thislen, data);
|
|
||||||
valuelen += thislen;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Add given variable with given value to file, overwriting any
|
|
||||||
* previous occurrence.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
var_set(const char *fname, const char *variable, const char *value)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
FILE *fout;
|
|
||||||
char *tmpname;
|
|
||||||
int fd;
|
|
||||||
char *line;
|
|
||||||
size_t len;
|
|
||||||
size_t varlen;
|
|
||||||
Boolean done;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
varlen = strlen(variable);
|
|
||||||
if (varlen == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fp = fopen(fname, "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
if (errno != ENOENT) {
|
|
||||||
warn("var_set: can't open '%s' for reading", fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (value == NULL)
|
|
||||||
return 0; /* Nothing to do */
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpname = xasprintf("%s.XXXXXX", fname);
|
|
||||||
if ((fd = mkstemp(tmpname)) < 0) {
|
|
||||||
free(tmpname);
|
|
||||||
if (fp != NULL)
|
|
||||||
fclose(fp);
|
|
||||||
warn("var_set: can't open temp file for '%s' for writing",
|
|
||||||
fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (chmod(tmpname, 0644) < 0) {
|
|
||||||
close(fd);
|
|
||||||
if (fp != NULL)
|
|
||||||
fclose(fp);
|
|
||||||
free(tmpname);
|
|
||||||
warn("var_set: can't set permissions for temp file for '%s'",
|
|
||||||
fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((fout=fdopen(fd, "w")) == NULL) {
|
|
||||||
close(fd);
|
|
||||||
remove(tmpname);
|
|
||||||
free(tmpname);
|
|
||||||
if (fp != NULL)
|
|
||||||
fclose(fp);
|
|
||||||
warn("var_set: can't open temp file for '%s' for writing",
|
|
||||||
fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
done = FALSE;
|
|
||||||
|
|
||||||
if (fp) {
|
|
||||||
while ((line = fgetln(fp, &len)) != (char *) NULL) {
|
|
||||||
if (var_cmp(line, len, variable, varlen) == NULL)
|
|
||||||
fprintf(fout, "%.*s", (int)len, line);
|
|
||||||
else {
|
|
||||||
if (!done && value) {
|
|
||||||
var_print(fout, variable, value);
|
|
||||||
done = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!done && value)
|
|
||||||
var_print(fout, variable, value);
|
|
||||||
|
|
||||||
if (fclose(fout) < 0) {
|
|
||||||
free(tmpname);
|
|
||||||
warn("var_set: write error for '%s'", fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat(tmpname, &st) < 0) {
|
|
||||||
free(tmpname);
|
|
||||||
warn("var_set: cannot stat tempfile for '%s'", fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (st.st_size == 0) {
|
|
||||||
if (remove(tmpname) < 0) {
|
|
||||||
free(tmpname);
|
|
||||||
warn("var_set: cannot remove tempfile for '%s'",
|
|
||||||
fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free(tmpname);
|
|
||||||
if (remove(fname) < 0) {
|
|
||||||
warn("var_set: cannot remove '%s'", fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(tmpname, fname) < 0) {
|
|
||||||
free(tmpname);
|
|
||||||
warn("var_set: cannot move tempfile to '%s'", fname);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
free(tmpname);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if line contains variable var, return pointer to its value or NULL.
|
|
||||||
*/
|
|
||||||
static const char *
|
|
||||||
var_cmp(const char *line, size_t linelen, const char *var, size_t varlen)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* We expect lines to look like one of the following
|
|
||||||
* forms:
|
|
||||||
* VAR=value
|
|
||||||
* VAR= value
|
|
||||||
* We print out the value of VAR, or nothing if it
|
|
||||||
* doesn't exist.
|
|
||||||
*/
|
|
||||||
if (linelen < varlen+1)
|
|
||||||
return NULL;
|
|
||||||
if (strncmp(var, line, varlen) != 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
line += varlen;
|
|
||||||
if (*line != '=')
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
++line;
|
|
||||||
linelen -= varlen+1;
|
|
||||||
if (linelen > 0 && *line == ' ')
|
|
||||||
++line;
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print given variable with value to file f.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
var_print(FILE *f, const char *variable, const char *value)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
while ((p=strchr(value, '\n')) != NULL) {
|
|
||||||
if (p != value)
|
|
||||||
fprintf(f, "%s=%.*s\n", variable, (int)(p-value), value);
|
|
||||||
value = p+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*value)
|
|
||||||
fprintf(f, "%s=%s\n", variable, value);
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/* $NetBSD: version.c,v 1.7 2010/02/03 14:20:14 joerg Exp $ */
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: version.c,v 1.7 2010/02/03 14:20:14 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001 Thomas Klausner. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_STDIO_H
|
|
||||||
#include <stdio.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
void
|
|
||||||
show_version(void)
|
|
||||||
{
|
|
||||||
printf("%d\n", PKGTOOLS_VERSION);
|
|
||||||
exit (0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
/* $NetBSD: version.h,v 1.156 2010/06/16 23:02:49 joerg Exp $ */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001 Thomas Klausner. All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
||||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _INST_LIB_VERSION_H_
|
|
||||||
#define _INST_LIB_VERSION_H_
|
|
||||||
|
|
||||||
#define PKGTOOLS_VERSION 20100616
|
|
||||||
|
|
||||||
#endif /* _INST_LIB_VERSION_H_ */
|
|
|
@ -1,659 +0,0 @@
|
||||||
/* $NetBSD: vulnerabilities-file.c,v 1.7 2010/06/16 23:02:49 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: vulnerabilities-file.c,v 1.7 2010/06/16 23:02:49 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_SYS_STAT_H
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
#include <archive.h>
|
|
||||||
#endif
|
|
||||||
#include <ctype.h>
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#if defined(NETBSD)
|
|
||||||
#include <sha1.h>
|
|
||||||
#include <sha2.h>
|
|
||||||
#elif defined(__minix)
|
|
||||||
#include <minix/sha1.h>
|
|
||||||
#include <minix/sha2.h>
|
|
||||||
#else
|
|
||||||
#include <nbcompat/sha1.h>
|
|
||||||
#include <nbcompat/sha2.h>
|
|
||||||
#endif
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
static struct pkg_vulnerabilities *read_pkg_vulnerabilities_archive(struct archive *, int);
|
|
||||||
static struct pkg_vulnerabilities *parse_pkg_vuln(const char *, size_t, int);
|
|
||||||
|
|
||||||
static const char pgp_msg_start[] = "-----BEGIN PGP SIGNED MESSAGE-----\n";
|
|
||||||
static const char pgp_msg_end[] = "-----BEGIN PGP SIGNATURE-----\n";
|
|
||||||
static const char pkcs7_begin[] = "-----BEGIN PKCS7-----\n";
|
|
||||||
static const char pkcs7_end[] = "-----END PKCS7-----\n";
|
|
||||||
|
|
||||||
static void
|
|
||||||
verify_signature_pkcs7(const char *input)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
const char *begin_pkgvul, *end_pkgvul, *begin_sig, *end_sig;
|
|
||||||
|
|
||||||
if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) {
|
|
||||||
begin_pkgvul = input + strlen(pgp_msg_start);
|
|
||||||
if ((end_pkgvul = strstr(begin_pkgvul, pgp_msg_end)) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Invalid PGP signature");
|
|
||||||
if ((begin_sig = strstr(end_pkgvul, pkcs7_begin)) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "No PKCS7 signature");
|
|
||||||
} else {
|
|
||||||
begin_pkgvul = input;
|
|
||||||
if ((begin_sig = strstr(begin_pkgvul, pkcs7_begin)) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "No PKCS7 signature");
|
|
||||||
end_pkgvul = begin_sig;
|
|
||||||
}
|
|
||||||
if ((end_sig = strstr(begin_sig, pkcs7_end)) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Invalid PKCS7 signature");
|
|
||||||
end_sig += strlen(pkcs7_end);
|
|
||||||
|
|
||||||
if (easy_pkcs7_verify(begin_pkgvul, end_pkgvul - begin_pkgvul,
|
|
||||||
begin_sig, end_sig - begin_sig, certs_pkg_vulnerabilities, 0))
|
|
||||||
errx(EXIT_FAILURE, "Unable to verify PKCS7 signature");
|
|
||||||
#else
|
|
||||||
errx(EXIT_FAILURE, "OpenSSL support is not compiled in");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
verify_signature(const char *input, size_t input_len)
|
|
||||||
{
|
|
||||||
if (gpg_cmd == NULL && certs_pkg_vulnerabilities == NULL)
|
|
||||||
errx(EXIT_FAILURE,
|
|
||||||
"At least GPG or CERTIFICATE_ANCHOR_PKGVULN "
|
|
||||||
"must be configured");
|
|
||||||
if (gpg_cmd != NULL)
|
|
||||||
inline_gpg_verify(input, input_len, gpg_keyring_pkgvuln);
|
|
||||||
if (certs_pkg_vulnerabilities != NULL)
|
|
||||||
verify_signature_pkcs7(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
sha512_hash_init(void)
|
|
||||||
{
|
|
||||||
static SHA512_CTX hash_ctx;
|
|
||||||
|
|
||||||
SHA512_Init(&hash_ctx);
|
|
||||||
return &hash_ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sha512_hash_update(void *ctx, const void *data, size_t len)
|
|
||||||
{
|
|
||||||
SHA512_CTX *hash_ctx = ctx;
|
|
||||||
|
|
||||||
SHA512_Update(hash_ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
sha512_hash_finish(void *ctx)
|
|
||||||
{
|
|
||||||
static char hash[SHA512_DIGEST_STRING_LENGTH];
|
|
||||||
unsigned char digest[SHA512_DIGEST_LENGTH];
|
|
||||||
SHA512_CTX *hash_ctx = ctx;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
SHA512_Final(digest, hash_ctx);
|
|
||||||
for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) {
|
|
||||||
unsigned char c;
|
|
||||||
|
|
||||||
c = digest[i] / 16;
|
|
||||||
if (c < 10)
|
|
||||||
hash[2 * i] = '0' + c;
|
|
||||||
else
|
|
||||||
hash[2 * i] = 'a' - 10 + c;
|
|
||||||
|
|
||||||
c = digest[i] % 16;
|
|
||||||
if (c < 10)
|
|
||||||
hash[2 * i + 1] = '0' + c;
|
|
||||||
else
|
|
||||||
hash[2 * i + 1] = 'a' - 10 + c;
|
|
||||||
}
|
|
||||||
hash[2 * i] = '\0';
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
sha1_hash_init(void)
|
|
||||||
{
|
|
||||||
static SHA1_CTX hash_ctx;
|
|
||||||
|
|
||||||
SHA1Init(&hash_ctx);
|
|
||||||
return &hash_ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sha1_hash_update(void *ctx, const void *data, size_t len)
|
|
||||||
{
|
|
||||||
SHA1_CTX *hash_ctx = ctx;
|
|
||||||
|
|
||||||
SHA1Update(hash_ctx, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
sha1_hash_finish(void *ctx)
|
|
||||||
{
|
|
||||||
static char hash[SHA1_DIGEST_STRING_LENGTH];
|
|
||||||
SHA1_CTX *hash_ctx = ctx;
|
|
||||||
|
|
||||||
SHA1End(hash_ctx, hash);
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct hash_algorithm {
|
|
||||||
const char *name;
|
|
||||||
size_t name_len;
|
|
||||||
void * (*init)(void);
|
|
||||||
void (*update)(void *, const void *, size_t);
|
|
||||||
const char * (* finish)(void *);
|
|
||||||
} hash_algorithms[] = {
|
|
||||||
{ "SHA512", 6, sha512_hash_init, sha512_hash_update,
|
|
||||||
sha512_hash_finish },
|
|
||||||
{ "SHA1", 4, sha1_hash_init, sha1_hash_update,
|
|
||||||
sha1_hash_finish },
|
|
||||||
{ NULL, 0, NULL, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
verify_hash(const char *input, const char *hash_line)
|
|
||||||
{
|
|
||||||
const struct hash_algorithm *hash;
|
|
||||||
void *ctx;
|
|
||||||
const char *last_start, *next, *hash_value;
|
|
||||||
int in_pgp_msg;
|
|
||||||
|
|
||||||
for (hash = hash_algorithms; hash->name != NULL; ++hash) {
|
|
||||||
if (strncmp(hash_line, hash->name, hash->name_len))
|
|
||||||
continue;
|
|
||||||
if (isspace((unsigned char)hash_line[hash->name_len]))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (hash->name == NULL) {
|
|
||||||
const char *end_name;
|
|
||||||
for (end_name = hash_line; *end_name != '\0'; ++end_name) {
|
|
||||||
if (!isalnum((unsigned char)*end_name))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
warnx("Unsupported hash algorithm: %.*s",
|
|
||||||
(int)(end_name - hash_line), hash_line);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash_line += hash->name_len;
|
|
||||||
if (!isspace((unsigned char)*hash_line))
|
|
||||||
errx(EXIT_FAILURE, "Invalid #CHECKSUM");
|
|
||||||
while (isspace((unsigned char)*hash_line) && *hash_line != '\n')
|
|
||||||
++hash_line;
|
|
||||||
|
|
||||||
if (*hash_line == '\n')
|
|
||||||
errx(EXIT_FAILURE, "Invalid #CHECKSUM");
|
|
||||||
|
|
||||||
ctx = (*hash->init)();
|
|
||||||
if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) {
|
|
||||||
input += strlen(pgp_msg_start);
|
|
||||||
in_pgp_msg = 1;
|
|
||||||
} else {
|
|
||||||
in_pgp_msg = 0;
|
|
||||||
}
|
|
||||||
for (last_start = input; *input != '\0'; input = next) {
|
|
||||||
if ((next = strchr(input, '\n')) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities");
|
|
||||||
++next;
|
|
||||||
if (in_pgp_msg && strncmp(input, pgp_msg_end, strlen(pgp_msg_end)) == 0)
|
|
||||||
break;
|
|
||||||
if (!in_pgp_msg && strncmp(input, pkcs7_begin, strlen(pkcs7_begin)) == 0)
|
|
||||||
break;
|
|
||||||
if (*input == '\n' ||
|
|
||||||
strncmp(input, "Hash:", 5) == 0 ||
|
|
||||||
strncmp(input, "# $NetBSD", 9) == 0 ||
|
|
||||||
strncmp(input, "#CHECKSUM", 9) == 0) {
|
|
||||||
(*hash->update)(ctx, last_start, input - last_start);
|
|
||||||
last_start = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(*hash->update)(ctx, last_start, input - last_start);
|
|
||||||
hash_value = (*hash->finish)(ctx);
|
|
||||||
if (strncmp(hash_line, hash_value, strlen(hash_value)))
|
|
||||||
errx(EXIT_FAILURE, "%s hash doesn't match", hash->name);
|
|
||||||
hash_line += strlen(hash_value);
|
|
||||||
|
|
||||||
while (isspace((unsigned char)*hash_line) && *hash_line != '\n')
|
|
||||||
++hash_line;
|
|
||||||
|
|
||||||
if (!isspace((unsigned char)*hash_line))
|
|
||||||
errx(EXIT_FAILURE, "Invalid #CHECKSUM");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
add_vulnerability(struct pkg_vulnerabilities *pv, size_t *allocated, const char *line)
|
|
||||||
{
|
|
||||||
size_t len_pattern, len_class, len_url;
|
|
||||||
const char *start_pattern, *start_class, *start_url;
|
|
||||||
|
|
||||||
start_pattern = line;
|
|
||||||
|
|
||||||
start_class = line;
|
|
||||||
while (*start_class != '\0' && !isspace((unsigned char)*start_class))
|
|
||||||
++start_class;
|
|
||||||
len_pattern = start_class - line;
|
|
||||||
|
|
||||||
while (*start_class != '\n' && isspace((unsigned char)*start_class))
|
|
||||||
++start_class;
|
|
||||||
|
|
||||||
if (*start_class == '0' || *start_class == '\n')
|
|
||||||
errx(EXIT_FAILURE, "Input error: missing classification");
|
|
||||||
|
|
||||||
start_url = start_class;
|
|
||||||
while (*start_url != '\0' && !isspace((unsigned char)*start_url))
|
|
||||||
++start_url;
|
|
||||||
len_class = start_url - start_class;
|
|
||||||
|
|
||||||
while (*start_url != '\n' && isspace((unsigned char)*start_url))
|
|
||||||
++start_url;
|
|
||||||
|
|
||||||
if (*start_url == '0' || *start_url == '\n')
|
|
||||||
errx(EXIT_FAILURE, "Input error: missing URL");
|
|
||||||
|
|
||||||
line = start_url;
|
|
||||||
while (*line != '\0' && !isspace((unsigned char)*line))
|
|
||||||
++line;
|
|
||||||
len_url = line - start_url;
|
|
||||||
|
|
||||||
if (pv->entries == *allocated) {
|
|
||||||
if (*allocated == 0)
|
|
||||||
*allocated = 16;
|
|
||||||
else if (*allocated <= SSIZE_MAX / 2)
|
|
||||||
*allocated *= 2;
|
|
||||||
else
|
|
||||||
errx(EXIT_FAILURE, "Too many vulnerabilities");
|
|
||||||
pv->vulnerability = xrealloc(pv->vulnerability,
|
|
||||||
sizeof(char *) * *allocated);
|
|
||||||
pv->classification = xrealloc(pv->classification,
|
|
||||||
sizeof(char *) * *allocated);
|
|
||||||
pv->advisory = xrealloc(pv->advisory,
|
|
||||||
sizeof(char *) * *allocated);
|
|
||||||
}
|
|
||||||
|
|
||||||
pv->vulnerability[pv->entries] = xmalloc(len_pattern + 1);
|
|
||||||
memcpy(pv->vulnerability[pv->entries], start_pattern, len_pattern);
|
|
||||||
pv->vulnerability[pv->entries][len_pattern] = '\0';
|
|
||||||
pv->classification[pv->entries] = xmalloc(len_class + 1);
|
|
||||||
memcpy(pv->classification[pv->entries], start_class, len_class);
|
|
||||||
pv->classification[pv->entries][len_class] = '\0';
|
|
||||||
pv->advisory[pv->entries] = xmalloc(len_url + 1);
|
|
||||||
memcpy(pv->advisory[pv->entries], start_url, len_url);
|
|
||||||
pv->advisory[pv->entries][len_url] = '\0';
|
|
||||||
|
|
||||||
++pv->entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pkg_vulnerabilities *
|
|
||||||
read_pkg_vulnerabilities_memory(void *buf, size_t len, int check_sum)
|
|
||||||
{
|
|
||||||
#ifdef BOOTSTRAP
|
|
||||||
errx(EXIT_FAILURE, "Audit functions are unsupported during bootstrap");
|
|
||||||
#else
|
|
||||||
struct archive *a;
|
|
||||||
struct pkg_vulnerabilities *pv;
|
|
||||||
|
|
||||||
if ((a = archive_read_new()) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "memory allocation failed");
|
|
||||||
|
|
||||||
if (archive_read_support_compression_all(a) != ARCHIVE_OK ||
|
|
||||||
archive_read_support_format_raw(a) != ARCHIVE_OK ||
|
|
||||||
archive_read_open_memory(a, buf, len) != ARCHIVE_OK)
|
|
||||||
errx(EXIT_FAILURE, "Cannot open pkg_vulnerabilies buffer: %s",
|
|
||||||
archive_error_string(a));
|
|
||||||
|
|
||||||
pv = read_pkg_vulnerabilities_archive(a, check_sum);
|
|
||||||
|
|
||||||
return pv;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pkg_vulnerabilities *
|
|
||||||
read_pkg_vulnerabilities_file(const char *path, int ignore_missing, int check_sum)
|
|
||||||
{
|
|
||||||
#ifdef BOOTSTRAP
|
|
||||||
errx(EXIT_FAILURE, "Audit functions are unsupported during bootstrap");
|
|
||||||
#else
|
|
||||||
struct archive *a;
|
|
||||||
struct pkg_vulnerabilities *pv;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if ((fd = open(path, O_RDONLY)) == -1) {
|
|
||||||
if (errno == ENOENT && ignore_missing)
|
|
||||||
return NULL;
|
|
||||||
err(EXIT_FAILURE, "Cannot open %s", path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((a = archive_read_new()) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "memory allocation failed");
|
|
||||||
|
|
||||||
if (archive_read_support_compression_all(a) != ARCHIVE_OK ||
|
|
||||||
archive_read_support_format_raw(a) != ARCHIVE_OK ||
|
|
||||||
archive_read_open_fd(a, fd, 65536) != ARCHIVE_OK)
|
|
||||||
errx(EXIT_FAILURE, "Cannot open ``%s'': %s", path,
|
|
||||||
archive_error_string(a));
|
|
||||||
|
|
||||||
pv = read_pkg_vulnerabilities_archive(a, check_sum);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return pv;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BOOTSTRAP
|
|
||||||
static struct pkg_vulnerabilities *
|
|
||||||
read_pkg_vulnerabilities_archive(struct archive *a, int check_sum)
|
|
||||||
{
|
|
||||||
struct archive_entry *ae;
|
|
||||||
struct pkg_vulnerabilities *pv;
|
|
||||||
char *buf;
|
|
||||||
size_t buf_len, off;
|
|
||||||
ssize_t r;
|
|
||||||
|
|
||||||
if (archive_read_next_header(a, &ae) != ARCHIVE_OK)
|
|
||||||
errx(EXIT_FAILURE, "Cannot read pkg_vulnerabilities: %s",
|
|
||||||
archive_error_string(a));
|
|
||||||
|
|
||||||
off = 0;
|
|
||||||
buf_len = 65536;
|
|
||||||
buf = xmalloc(buf_len + 1);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
r = archive_read_data(a, buf + off, buf_len - off);
|
|
||||||
if (r <= 0)
|
|
||||||
break;
|
|
||||||
off += r;
|
|
||||||
if (off == buf_len) {
|
|
||||||
buf_len *= 2;
|
|
||||||
if (buf_len < off)
|
|
||||||
errx(EXIT_FAILURE, "pkg_vulnerabilties too large");
|
|
||||||
buf = xrealloc(buf, buf_len + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r != ARCHIVE_OK)
|
|
||||||
errx(EXIT_FAILURE, "Cannot read pkg_vulnerabilities: %s",
|
|
||||||
archive_error_string(a));
|
|
||||||
|
|
||||||
archive_read_close(a);
|
|
||||||
|
|
||||||
buf[off] = '\0';
|
|
||||||
pv = parse_pkg_vuln(buf, off, check_sum);
|
|
||||||
free(buf);
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pkg_vulnerabilities *
|
|
||||||
parse_pkg_vuln(const char *input, size_t input_len, int check_sum)
|
|
||||||
{
|
|
||||||
struct pkg_vulnerabilities *pv;
|
|
||||||
long version;
|
|
||||||
char *end;
|
|
||||||
const char *iter, *next;
|
|
||||||
size_t allocated_vulns;
|
|
||||||
int in_pgp_msg;
|
|
||||||
|
|
||||||
pv = xmalloc(sizeof(*pv));
|
|
||||||
|
|
||||||
allocated_vulns = pv->entries = 0;
|
|
||||||
pv->vulnerability = NULL;
|
|
||||||
pv->classification = NULL;
|
|
||||||
pv->advisory = NULL;
|
|
||||||
|
|
||||||
if (strlen(input) != input_len)
|
|
||||||
errx(1, "Invalid input (NUL character found)");
|
|
||||||
|
|
||||||
if (check_sum)
|
|
||||||
verify_signature(input, input_len);
|
|
||||||
|
|
||||||
if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) {
|
|
||||||
iter = input + strlen(pgp_msg_start);
|
|
||||||
in_pgp_msg = 1;
|
|
||||||
} else {
|
|
||||||
iter = input;
|
|
||||||
in_pgp_msg = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; *iter; iter = next) {
|
|
||||||
if ((next = strchr(iter, '\n')) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities");
|
|
||||||
++next;
|
|
||||||
if (*iter == '\0' || *iter == '\n')
|
|
||||||
continue;
|
|
||||||
if (strncmp(iter, "Hash:", 5) == 0)
|
|
||||||
continue;
|
|
||||||
if (strncmp(iter, "# $NetBSD", 9) == 0)
|
|
||||||
continue;
|
|
||||||
if (*iter == '#' && isspace((unsigned char)iter[1])) {
|
|
||||||
for (++iter; iter != next; ++iter) {
|
|
||||||
if (!isspace((unsigned char)*iter))
|
|
||||||
errx(EXIT_FAILURE, "Invalid header");
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(iter, "#FORMAT", 7) != 0)
|
|
||||||
errx(EXIT_FAILURE, "Input header is malformed");
|
|
||||||
|
|
||||||
iter += 7;
|
|
||||||
if (!isspace((unsigned char)*iter))
|
|
||||||
errx(EXIT_FAILURE, "Invalid #FORMAT");
|
|
||||||
++iter;
|
|
||||||
version = strtol(iter, &end, 10);
|
|
||||||
if (iter == end || version != 1 || *end != '.')
|
|
||||||
errx(EXIT_FAILURE, "Input #FORMAT");
|
|
||||||
iter = end + 1;
|
|
||||||
version = strtol(iter, &end, 10);
|
|
||||||
if (iter == end || version != 1 || *end != '.')
|
|
||||||
errx(EXIT_FAILURE, "Input #FORMAT");
|
|
||||||
iter = end + 1;
|
|
||||||
version = strtol(iter, &end, 10);
|
|
||||||
if (iter == end || version != 0)
|
|
||||||
errx(EXIT_FAILURE, "Input #FORMAT");
|
|
||||||
for (iter = end; iter != next; ++iter) {
|
|
||||||
if (!isspace((unsigned char)*iter))
|
|
||||||
errx(EXIT_FAILURE, "Input #FORMAT");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (*iter == '\0')
|
|
||||||
errx(EXIT_FAILURE, "Missing #CHECKSUM or content");
|
|
||||||
|
|
||||||
for (iter = next; *iter; iter = next) {
|
|
||||||
if ((next = strchr(iter, '\n')) == NULL)
|
|
||||||
errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities");
|
|
||||||
++next;
|
|
||||||
if (*iter == '\0' || *iter == '\n')
|
|
||||||
continue;
|
|
||||||
if (in_pgp_msg && strncmp(iter, pgp_msg_end, strlen(pgp_msg_end)) == 0)
|
|
||||||
break;
|
|
||||||
if (!in_pgp_msg && strncmp(iter, pkcs7_begin, strlen(pkcs7_begin)) == 0)
|
|
||||||
break;
|
|
||||||
if (*iter == '#' &&
|
|
||||||
(iter[1] == '\0' || iter[1] == '\n' || isspace((unsigned char)iter[1])))
|
|
||||||
continue;
|
|
||||||
if (strncmp(iter, "#CHECKSUM", 9) == 0) {
|
|
||||||
iter += 9;
|
|
||||||
if (!isspace((unsigned char)*iter))
|
|
||||||
errx(EXIT_FAILURE, "Invalid #CHECKSUM");
|
|
||||||
while (isspace((unsigned char)*iter))
|
|
||||||
++iter;
|
|
||||||
verify_hash(input, iter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (*iter == '#') {
|
|
||||||
/*
|
|
||||||
* This should really be an error,
|
|
||||||
* but it is still used.
|
|
||||||
*/
|
|
||||||
/* errx(EXIT_FAILURE, "Invalid data line starting with #"); */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
add_vulnerability(pv, &allocated_vulns, iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pv->entries != allocated_vulns) {
|
|
||||||
pv->vulnerability = xrealloc(pv->vulnerability,
|
|
||||||
sizeof(char *) * pv->entries);
|
|
||||||
pv->classification = xrealloc(pv->classification,
|
|
||||||
sizeof(char *) * pv->entries);
|
|
||||||
pv->advisory = xrealloc(pv->advisory,
|
|
||||||
sizeof(char *) * pv->entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
|
||||||
free_pkg_vulnerabilities(struct pkg_vulnerabilities *pv)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
for (i = 0; i < pv->entries; ++i) {
|
|
||||||
free(pv->vulnerability[i]);
|
|
||||||
free(pv->classification[i]);
|
|
||||||
free(pv->advisory[i]);
|
|
||||||
}
|
|
||||||
free(pv->vulnerability);
|
|
||||||
free(pv->classification);
|
|
||||||
free(pv->advisory);
|
|
||||||
free(pv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
check_ignored_entry(struct pkg_vulnerabilities *pv, size_t i)
|
|
||||||
{
|
|
||||||
const char *iter, *next;
|
|
||||||
size_t entry_len, url_len;
|
|
||||||
|
|
||||||
if (ignore_advisories == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
url_len = strlen(pv->advisory[i]);
|
|
||||||
|
|
||||||
for (iter = ignore_advisories; *iter; iter = next) {
|
|
||||||
if ((next = strchr(iter, '\n')) == NULL) {
|
|
||||||
entry_len = strlen(iter);
|
|
||||||
next = iter + entry_len;
|
|
||||||
} else {
|
|
||||||
entry_len = next - iter;
|
|
||||||
++next;
|
|
||||||
}
|
|
||||||
if (url_len != entry_len)
|
|
||||||
continue;
|
|
||||||
if (strncmp(pv->advisory[i], iter, entry_len) == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
audit_package(struct pkg_vulnerabilities *pv, const char *pkgname,
|
|
||||||
const char *limit_vul_types, int output_type)
|
|
||||||
{
|
|
||||||
FILE *output = output_type == 1 ? stdout : stderr;
|
|
||||||
size_t i;
|
|
||||||
int retval, do_eol;
|
|
||||||
|
|
||||||
retval = 0;
|
|
||||||
|
|
||||||
do_eol = (strcasecmp(check_eol, "yes") == 0);
|
|
||||||
|
|
||||||
for (i = 0; i < pv->entries; ++i) {
|
|
||||||
if (check_ignored_entry(pv, i))
|
|
||||||
continue;
|
|
||||||
if (limit_vul_types != NULL &&
|
|
||||||
strcmp(limit_vul_types, pv->classification[i]))
|
|
||||||
continue;
|
|
||||||
if (!pkg_match(pv->vulnerability[i], pkgname))
|
|
||||||
continue;
|
|
||||||
if (strcmp("eol", pv->classification[i]) == 0) {
|
|
||||||
if (!do_eol)
|
|
||||||
continue;
|
|
||||||
retval = 1;
|
|
||||||
if (output_type == 0) {
|
|
||||||
puts(pkgname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fprintf(output,
|
|
||||||
"Package %s has reached end-of-life (eol), "
|
|
||||||
"see %s/eol-packages\n", pkgname,
|
|
||||||
tnf_vulnerability_base);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
retval = 1;
|
|
||||||
if (output_type == 0) {
|
|
||||||
puts(pkgname);
|
|
||||||
} else {
|
|
||||||
fprintf(output,
|
|
||||||
"Package %s has a %s vulnerability, see %s\n",
|
|
||||||
pkgname, pv->classification[i], pv->advisory[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
|
@ -1,106 +0,0 @@
|
||||||
/* $NetBSD: xwrapper.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */
|
|
||||||
|
|
||||||
/*-
|
|
||||||
* Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
||||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
||||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
#include <nbcompat.h>
|
|
||||||
#endif
|
|
||||||
#if HAVE_SYS_CDEFS_H
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
#endif
|
|
||||||
#ifndef __minix
|
|
||||||
__RCSID("$NetBSD: xwrapper.c,v 1.2 2009/02/02 12:35:01 joerg Exp $");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HAVE_ERR_H
|
|
||||||
#include <err.h>
|
|
||||||
#endif
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
|
||||||
|
|
||||||
char *
|
|
||||||
xasprintf(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
if (vasprintf(&buf, fmt, ap) == -1)
|
|
||||||
err(1, "asprintf failed");
|
|
||||||
va_end(ap);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
xmalloc(size_t len)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if ((ptr = malloc(len)) == NULL)
|
|
||||||
err(1, "malloc failed");
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
xcalloc(size_t len, size_t n)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if ((ptr = calloc(len, n)) == NULL)
|
|
||||||
err(1, "calloc failed");
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
xrealloc(void *buf, size_t len)
|
|
||||||
{
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
if ((ptr = realloc(buf, len)) == NULL)
|
|
||||||
err(1, "realloc failed");
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
xstrdup(const char *str)
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
|
|
||||||
if ((buf = strdup(str)) == NULL)
|
|
||||||
err(1, "strdup failed");
|
|
||||||
return buf;
|
|
||||||
}
|
|
|
@ -1,152 +0,0 @@
|
||||||
#!/usr/pkg/bin/wish -f
|
|
||||||
# from FreeBSD Id: tkpkg,v 1.4 1997/02/22 16:09:13 peter Exp
|
|
||||||
#
|
|
||||||
set pkgname ""
|
|
||||||
wm title . "Package Installation"
|
|
||||||
#--------------------------------------------------------------
|
|
||||||
# The top level main window, consisting of a bar of buttons and a list
|
|
||||||
# of packages and a description of the current package.
|
|
||||||
#--------------------------------------------------------------
|
|
||||||
frame .menu -relief raised -borderwidth 1
|
|
||||||
frame .frame -borderwidth 4
|
|
||||||
|
|
||||||
scrollbar .frame.scroll -relief sunken -command ".frame.list yview"
|
|
||||||
listbox .frame.list -yscroll ".frame.scroll set" -relief sunken -setgrid 1
|
|
||||||
pack append .frame .frame.scroll {right filly} \
|
|
||||||
.frame.list {left expand fill}
|
|
||||||
|
|
||||||
# build the lower window shoing the complete description of a pacage
|
|
||||||
frame .f -borderwidth 4
|
|
||||||
text .f.t -width 80 -height 20 -yscrollcommand ".f.s set" -relief sunken
|
|
||||||
|
|
||||||
# Initially display instructions in this window. Erase the
|
|
||||||
# instructions and show the package description when the user clicks
|
|
||||||
# on a package.
|
|
||||||
#
|
|
||||||
.f.t insert end "Double click on a package above to see its
|
|
||||||
complete description here."
|
|
||||||
scrollbar .f.s -relief sunken -command ".f.t yview"
|
|
||||||
pack append .f .f.s {right filly} .f.t {left expand fill}
|
|
||||||
|
|
||||||
bind .frame.list <Double-Button-1> \
|
|
||||||
{ do_description [selection get] }
|
|
||||||
pack append . .menu {top fill} \
|
|
||||||
.f {bottom expand fill} \
|
|
||||||
.frame {bottom expand fill}
|
|
||||||
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
# Make menu bar:
|
|
||||||
#----------------------------------------------------------------
|
|
||||||
button .menu.inst -text "Install" \
|
|
||||||
-command "apply_to_pkg \"pkg_add -v\""
|
|
||||||
button .menu.dein -text "Deinstall" \
|
|
||||||
-command "apply_to_pkg \"pkg_delete -v\""
|
|
||||||
button .menu.installed -text "What is Installed?" \
|
|
||||||
-command "list_pkgs \"pkg_info -I -a |tr ' ' ' '\""
|
|
||||||
button .menu.available -text "What can I install?" \
|
|
||||||
-command "list_pkgs \"pkg_info -I -c [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}] |tr ' ' ' '\""
|
|
||||||
button .menu.cont -text "Contents?" \
|
|
||||||
-command "apply_to_pkg \"pkg_info -d -v\""
|
|
||||||
button .menu.quit -text "Quit" -command "destroy ."
|
|
||||||
button .menu.help -text "Help" -command "do_help"
|
|
||||||
|
|
||||||
pack append .menu \
|
|
||||||
.menu.inst left \
|
|
||||||
.menu.dein left \
|
|
||||||
.menu.installed left \
|
|
||||||
.menu.available left \
|
|
||||||
.menu.cont left \
|
|
||||||
.menu.quit left \
|
|
||||||
.menu.help right
|
|
||||||
#-------------------------------------------------------
|
|
||||||
# Display the package description.
|
|
||||||
#-------------------------------------------------------
|
|
||||||
proc list_pkgs {s} {
|
|
||||||
set line ""
|
|
||||||
set f [eval "open {| sh -c \"$s\" } r"]
|
|
||||||
.frame.list delete 0 end
|
|
||||||
while {[gets $f line] > 0} {
|
|
||||||
.frame.list insert end $line
|
|
||||||
}
|
|
||||||
close $f
|
|
||||||
}
|
|
||||||
|
|
||||||
# display the list of available packages
|
|
||||||
set archives [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}]
|
|
||||||
if {$archives == ""} {
|
|
||||||
.frame.list delete 0 end
|
|
||||||
.frame.list insert end "Warning: no compressed tar archives files found."
|
|
||||||
} else {
|
|
||||||
list_pkgs "pkg_info -I -c $archives |tr ' ' ' '"
|
|
||||||
}
|
|
||||||
|
|
||||||
#-------------------------------------------------------
|
|
||||||
# Display the package description.
|
|
||||||
#-------------------------------------------------------
|
|
||||||
proc do_description {s} {
|
|
||||||
global pkgname
|
|
||||||
regexp {[^ ]*} $s filename
|
|
||||||
set pkgname $filename
|
|
||||||
.f.t delete 0.0 end
|
|
||||||
set cmd "pkg_info -d $filename |tr -d ''"
|
|
||||||
set f [eval "open {| csh -c \"$cmd\" } r"]
|
|
||||||
while {![eof $f]} {
|
|
||||||
.f.t insert end [read $f]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#-------------------------------------------------------
|
|
||||||
# package install window.
|
|
||||||
#-------------------------------------------------------
|
|
||||||
proc do_help {{w .help}} {
|
|
||||||
catch {destroy $w}
|
|
||||||
toplevel $w
|
|
||||||
wm title $w "Help"
|
|
||||||
wm iconname $w "Help"
|
|
||||||
button $w.ok -text OK -command "destroy $w"
|
|
||||||
message $w.t -relief raised -bd 2 \
|
|
||||||
-text "You can install, deinstall and list info on the available packages. To select a package and see its complete description, press mouse button 1 over the package name. To install a selected package, press the Install button. To exit, press the \"Quit\" button."
|
|
||||||
pack append $w $w.ok {bottom fillx} $w.t {expand fill}
|
|
||||||
}
|
|
||||||
#-------------------------------------------------------
|
|
||||||
# Apply a command to a package.
|
|
||||||
#-------------------------------------------------------
|
|
||||||
proc apply_to_pkg {s} {
|
|
||||||
apply_to_pkg_err $s ""
|
|
||||||
}
|
|
||||||
#-------------------------------------------------------
|
|
||||||
# Apply a command to a package, with error stream redirection instructions.
|
|
||||||
#-------------------------------------------------------
|
|
||||||
proc apply_to_pkg_err {s errredir} {
|
|
||||||
global pkgname
|
|
||||||
.f.t delete 0.0 end
|
|
||||||
if {$pkgname == ""} {
|
|
||||||
.f.t insert end "You must double click on a package name first!"
|
|
||||||
} else {
|
|
||||||
apply_to_pkg_int "$s $pkgname" "2>&1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
proc apply_to_pkg_int {s errredir} {
|
|
||||||
.f.t delete 0.0 end
|
|
||||||
.f.t insert end "Running: $s\n"
|
|
||||||
set f [eval "open {| sh -c \"$s $errredir\" } r"]
|
|
||||||
while {![eof $f]} {
|
|
||||||
.f.t insert end [read $f 64]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#-------------------------------------------------------
|
|
||||||
# Invoke an arbitrary command.
|
|
||||||
#-------------------------------------------------------
|
|
||||||
proc do_command {s} {
|
|
||||||
.f.t delete 0.0 end
|
|
||||||
.f.t insert end "Running: $s\n"
|
|
||||||
set f [eval "open {| $s} r"]
|
|
||||||
while {![eof $f]} {
|
|
||||||
.f.t insert end [read $f 64]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# local variables:
|
|
||||||
# mode: csh
|
|
||||||
# compile-command: ""
|
|
||||||
# comment-start: "# "
|
|
||||||
# comment-start-skip: "# "
|
|
||||||
# end:
|
|
|
@ -1,35 +0,0 @@
|
||||||
# $NetBSD: Makefile.in,v 1.6 2008/03/10 12:14:32 wiz Exp $
|
|
||||||
|
|
||||||
prefix= @prefix@
|
|
||||||
exec_prefix= @exec_prefix@
|
|
||||||
sbindir= @sbindir@
|
|
||||||
mandir= @mandir@
|
|
||||||
datarootdir= @datarootdir@
|
|
||||||
|
|
||||||
man1dir= $(mandir)/man1
|
|
||||||
cat1dir= $(mandir)/cat1
|
|
||||||
|
|
||||||
INSTALL= @INSTALL@
|
|
||||||
|
|
||||||
SCRIPTS= linkfarm pkg_view
|
|
||||||
|
|
||||||
all:
|
|
||||||
@true # do nothing
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@true # do nothing
|
|
||||||
|
|
||||||
install:
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(sbindir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(man1dir)
|
|
||||||
$(INSTALL) -m 755 -d ${DESTDIR}$(cat1dir)
|
|
||||||
@for script in $(SCRIPTS); do \
|
|
||||||
echo "$(INSTALL) $$script.sh ${DESTDIR}$(sbindir)/$$script"; \
|
|
||||||
$(INSTALL) $$script.sh ${DESTDIR}$(sbindir)/$$script; \
|
|
||||||
done
|
|
||||||
@for script in $(SCRIPTS); do \
|
|
||||||
echo "$(INSTALL) -m 444 $$script.1 ${DESTDIR}$(man1dir)/$$script.1"; \
|
|
||||||
$(INSTALL) -m 444 $$script.1 ${DESTDIR}$(man1dir)/$$script.1; \
|
|
||||||
echo "$(INSTALL) -m 444 $$script.cat1 ${DESTDIR}$(cat1dir)/$$script.0"; \
|
|
||||||
$(INSTALL) -m 444 $$script.cat1 ${DESTDIR}$(cat1dir)/$$script.0; \
|
|
||||||
done
|
|
|
@ -1,67 +0,0 @@
|
||||||
LINKFARM(1) NetBSD General Commands Manual LINKFARM(1)
|
|
||||||
|
|
||||||
NNAAMMEE
|
|
||||||
lliinnkkffaarrmm -- manage symbolic links to package files
|
|
||||||
|
|
||||||
SSYYNNOOPPSSIISS
|
|
||||||
lliinnkkffaarrmm [--ccDDnnRRVVvv] [--dd _s_t_o_w_d_i_r] [--ss _s_u_b_d_i_r] [--tt _t_a_r_g_e_t] _p_a_c_k_a_g_e
|
|
||||||
|
|
||||||
DDEESSCCRRIIPPTTIIOONN
|
|
||||||
The lliinnkkffaarrmm command is used to manage a "linkfarm", a directory tree of
|
|
||||||
symbolic links in _t_a_r_g_e_t to the files in the _p_a_c_k_a_g_e sub-directory of
|
|
||||||
_s_t_o_w_d_i_r. The default action is to create a linkfarm to a package.
|
|
||||||
|
|
||||||
The following command-line options are supported:
|
|
||||||
|
|
||||||
--cc Check whether a package contains a linkfarm in _t_a_r_g_e_t. If
|
|
||||||
_p_a_c_k_a_g_e has no symbolic links in _t_a_r_g_e_t that correspond to its
|
|
||||||
files, then return 0, otherwise return 1.
|
|
||||||
|
|
||||||
--DD Delete the linkfarm for _p_a_c_k_a_g_e.
|
|
||||||
|
|
||||||
--dd _s_t_o_w_d_i_r
|
|
||||||
Set _s_t_o_w_d_i_r as the directory in which _p_a_c_k_a_g_e can be found. The
|
|
||||||
default _s_t_o_w_d_i_r is the _p_a_c_k_a_g_e_s sub-directory in the default
|
|
||||||
_t_a_r_g_e_t directory.
|
|
||||||
|
|
||||||
--nn Don't actually execute the commands for removing and creating the
|
|
||||||
symbolic links and directories.
|
|
||||||
|
|
||||||
--RR Delete and re-create the linkfarm for _p_a_c_k_a_g_e.
|
|
||||||
|
|
||||||
--ss _s_u_b_d_i_r
|
|
||||||
The root of the package hierarchy for the linkfarm is the _s_u_b_d_i_r
|
|
||||||
sub-directory in the package. By default, assume the root of the
|
|
||||||
package hierarchy is simply the _p_a_c_k_a_g_e directory.
|
|
||||||
|
|
||||||
--tt _t_a_r_g_e_t
|
|
||||||
Set _t_a_r_g_e_t as the directory in which to create and delete the
|
|
||||||
linkfarm for _p_a_c_k_a_g_e. The default _t_a_r_g_e_t directory is _/_u_s_r_/_p_k_g
|
|
||||||
but may be overridden by the LOCALBASE environment variable.
|
|
||||||
|
|
||||||
--VV Print version number and exit.
|
|
||||||
|
|
||||||
--vv Turn on verbose output. Specifying --vv multiple times increases
|
|
||||||
the level of verbosity.
|
|
||||||
|
|
||||||
EENNVVIIRROONNMMEENNTT
|
|
||||||
LOCALBASE
|
|
||||||
The standard packages directory, _/_u_s_r_/_p_k_g, can be overridden by
|
|
||||||
specifying an alternative directory in the LOCALBASE environment
|
|
||||||
variable. This affects the default _t_a_r_g_e_t and _s_t_o_w_d_i_r directo-
|
|
||||||
ries.
|
|
||||||
|
|
||||||
PLIST_IGNORE_FILES
|
|
||||||
This can be used to specify files in _p_a_c_k_a_g_e that should ignored
|
|
||||||
when creating and deleting symbolic links in _t_a_r_g_e_t.
|
|
||||||
PLIST_IGNORE_FILES is a space-separated list of shell glob pat-
|
|
||||||
terns that match files relative to the _p_a_c_k_a_g_e directory, and it
|
|
||||||
defaults to "info/dir *[~#] *.OLD *.orig *,v".
|
|
||||||
|
|
||||||
SSEEEE AALLSSOO
|
|
||||||
lndir(1), pkg_view(1)
|
|
||||||
|
|
||||||
AAUUTTHHOORRSS
|
|
||||||
The lliinnkkffaarrmm utility was written by Alistair G. Crooks <agc@NetBSD.org>.
|
|
||||||
|
|
||||||
NetBSD 5.0 September 2, 2003 NetBSD 5.0
|
|
|
@ -1,232 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
# $NetBSD: linkfarm.sh.in,v 1.4 2004/08/20 20:09:53 jlam Exp $
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2002 Alistair G. Crooks. All rights reserved.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by Alistair G. Crooks.
|
|
||||||
# 4. The name of the author may not be used to endorse or promote
|
|
||||||
# products derived from this software without specific prior written
|
|
||||||
# permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
||||||
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
prefix="@prefix@"
|
|
||||||
exec_prefix="@exec_prefix@"
|
|
||||||
sbindir="@sbindir@"
|
|
||||||
|
|
||||||
# set up program definitions
|
|
||||||
findprog="@FIND@"
|
|
||||||
grepprog="@GREP@"
|
|
||||||
lnprog="@LN@"
|
|
||||||
mkdirprog="@MKDIR@"
|
|
||||||
pkginfoprog="@sbindir@/pkg_info"
|
|
||||||
rmprog="@RM@"
|
|
||||||
rmdirprog="@RMDIR@"
|
|
||||||
sedprog="@SED@"
|
|
||||||
sortprog="@SORT@"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo 'Usage: linkfarm [options] package'
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
version() {
|
|
||||||
$pkginfoprog -V
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
checkdir() {
|
|
||||||
if [ ! -d "$1" ]; then
|
|
||||||
echo "linkfarm: \`$1' doesn't exist"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
ignorefiles=${PLIST_IGNORE_FILES:-"info/dir *[~#] *.OLD *.orig *,v"}
|
|
||||||
linktype=-s
|
|
||||||
|
|
||||||
# default action: create a linkfarm in $target from $stowdir/$1
|
|
||||||
# i.e. linkfarm --target=${prefix}/${view} --dir=${prefix}/packages $1
|
|
||||||
#
|
|
||||||
doit=""
|
|
||||||
target=${LOCALBASE:-/usr/pkg}
|
|
||||||
stowdir=${target}/packages
|
|
||||||
subdir=""
|
|
||||||
verbose=0
|
|
||||||
|
|
||||||
# default action is to create
|
|
||||||
check=no
|
|
||||||
delete=no
|
|
||||||
create=yes
|
|
||||||
|
|
||||||
# process args - can't use getopt(1) because of '--' style args
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
-D) delete=yes; create=no ;;
|
|
||||||
-R) delete=yes; create=yes ;;
|
|
||||||
-V) version ;;
|
|
||||||
-c) check=yes; doit=":" ;;
|
|
||||||
-d) stowdir=$2; shift ;;
|
|
||||||
-d*) stowdir=`echo $1 | $sedprog -e 's|-d||'` ;;
|
|
||||||
-s) subdir=$2; shift ;;
|
|
||||||
-s*) subdir=`echo $1 | $sedprog -e 's|-s||'` ;;
|
|
||||||
-t) target=$2; shift ;;
|
|
||||||
-t*) target=`echo $1 | $sedprog -e 's|-t||'` ;;
|
|
||||||
-n) doit=":" ;;
|
|
||||||
-v) verbose=`expr $verbose + 1` ;;
|
|
||||||
|
|
||||||
--delete) delete=yes; create=no ;;
|
|
||||||
--dir=*) stowdir=`echo $1 | $sedprog -e 's|--dir=||'` ;;
|
|
||||||
--restow) delete=yes; create=yes ;;
|
|
||||||
--subdir=*) subdir=`echo $1 | $sedprog -e 's|--subdir=||'` ;;
|
|
||||||
--target=*) target=`echo $1 | $sedprog -e 's|--target=||'` ;;
|
|
||||||
--version) version ;;
|
|
||||||
|
|
||||||
--) shift; break ;;
|
|
||||||
*) break ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
# set the package name
|
|
||||||
package=$1
|
|
||||||
|
|
||||||
# make sure stowdir has a full pathname
|
|
||||||
case $stowdir in
|
|
||||||
/*) ;;
|
|
||||||
*) stowdir=`pwd`/$stowdir ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Set the directory from which we symlink.
|
|
||||||
case $subdir in
|
|
||||||
"") fromdir=$stowdir/$package ;;
|
|
||||||
*) fromdir=$stowdir/$package/$subdir ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Set the directory to which we symlink.
|
|
||||||
case $target in
|
|
||||||
/*) todir=$target ;;
|
|
||||||
*) todir=`pwd`/$target ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# if we're checking the entries, check, then exit
|
|
||||||
case $check in
|
|
||||||
yes)
|
|
||||||
checkdir $fromdir
|
|
||||||
(cd $fromdir
|
|
||||||
ex=0
|
|
||||||
$findprog . ! -type d -print | \
|
|
||||||
$sedprog -e 's|^\./||' | \
|
|
||||||
while read f; do
|
|
||||||
if [ -e $todir/$f ]; then
|
|
||||||
ignore=no
|
|
||||||
for i in $ignorefiles; do
|
|
||||||
case $f in
|
|
||||||
$i) ignore=yes; break ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
case $ignore in
|
|
||||||
no)
|
|
||||||
echo "${f}"; ex=1 ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
exit $ex) || exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# if we need to get rid of old linkfarms, do it
|
|
||||||
case $delete in
|
|
||||||
yes)
|
|
||||||
checkdir $fromdir
|
|
||||||
(cd $fromdir
|
|
||||||
$findprog . ! -type d -print | \
|
|
||||||
$sedprog -e 's|^\./||' | \
|
|
||||||
while read f; do
|
|
||||||
ignore=no
|
|
||||||
for i in $ignorefiles; do
|
|
||||||
case $f in
|
|
||||||
$i) ignore=yes; break ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
case $ignore in
|
|
||||||
no)
|
|
||||||
if [ $verbose -gt 0 ]; then
|
|
||||||
echo "$rmprog -f $todir/$f"
|
|
||||||
fi
|
|
||||||
$doit $rmprog -f $todir/$f ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
$findprog . -type d -print | \
|
|
||||||
$sedprog -e 's|^\./||' | \
|
|
||||||
$sortprog -r | \
|
|
||||||
while read d; do
|
|
||||||
if [ $verbose -gt 0 ]; then
|
|
||||||
echo "$rmdirprog $todir/$d"
|
|
||||||
fi
|
|
||||||
$doit $rmdirprog $todir/$d > /dev/null 2>&1
|
|
||||||
done)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# if we need to create new linkfarms, do it
|
|
||||||
case $create in
|
|
||||||
yes)
|
|
||||||
checkdir $fromdir
|
|
||||||
(cd $fromdir
|
|
||||||
$findprog . -type d -print | \
|
|
||||||
$sedprog -e 's|^\./||' | \
|
|
||||||
while read d; do
|
|
||||||
case "$d" in
|
|
||||||
"") continue ;;
|
|
||||||
esac
|
|
||||||
if [ $verbose -gt 0 ]; then
|
|
||||||
echo "$mkdirprog -p $todir/$d"
|
|
||||||
fi
|
|
||||||
$doit $mkdirprog -p $todir/$d > /dev/null 2>&1
|
|
||||||
done
|
|
||||||
$findprog . ! -type d -print | \
|
|
||||||
$sedprog -e 's|^\./||' | \
|
|
||||||
while read f; do
|
|
||||||
ignore=no
|
|
||||||
for i in $ignorefiles; do
|
|
||||||
case $f in
|
|
||||||
$i) ignore=yes; break ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
case $ignore in
|
|
||||||
no)
|
|
||||||
if [ $verbose -gt 0 ]; then
|
|
||||||
echo "$lnprog ${linktype} $fromdir/$f $todir/$f"
|
|
||||||
fi
|
|
||||||
$doit $lnprog ${linktype} $fromdir/$f $todir/$f ;;
|
|
||||||
esac
|
|
||||||
done)
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,276 +0,0 @@
|
||||||
#! /bin/sh
|
|
||||||
|
|
||||||
# $NetBSD: pkg_view.sh.in,v 1.7 2006/06/27 23:36:14 hubertf Exp $
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2001 Alistair G. Crooks. All rights reserved.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
# 3. All advertising materials mentioning features or use of this software
|
|
||||||
# must display the following acknowledgement:
|
|
||||||
# This product includes software developed by Alistair G. Crooks.
|
|
||||||
# 4. The name of the author may not be used to endorse or promote
|
|
||||||
# products derived from this software without specific prior written
|
|
||||||
# permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
||||||
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
||||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
|
||||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
||||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
prefix="@prefix@"
|
|
||||||
exec_prefix="@exec_prefix@"
|
|
||||||
sbindir="@sbindir@"
|
|
||||||
|
|
||||||
# set up program definitions
|
|
||||||
chmodprog="@CHMOD@"
|
|
||||||
cmpprog="@CMP@"
|
|
||||||
cpprog="@CP@"
|
|
||||||
envprog="@ENV@"
|
|
||||||
findprog="@FIND@"
|
|
||||||
grepprog="@GREP@"
|
|
||||||
linkfarmprog="@sbindir@/linkfarm"
|
|
||||||
lnprog="@LN@"
|
|
||||||
mkdirprog="@MKDIR@"
|
|
||||||
paxprog="@pax@"
|
|
||||||
pkgadminprog="@sbindir@/pkg_admin"
|
|
||||||
pkginfoprog="@sbindir@/pkg_info"
|
|
||||||
rmprog="@RM@"
|
|
||||||
rmdirprog="@RMDIR@"
|
|
||||||
sedprog="@SED@"
|
|
||||||
touchprog="@TOUCH@"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo 'Usage: pkg_view [-nVv] [-d stowdir] [-i ignore] [-k pkg_dbdir] [-W viewbase]'
|
|
||||||
echo ' [-w viewname] add|check|delete pkgname...'
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
version() {
|
|
||||||
$pkginfoprog -V
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
checkpkg() {
|
|
||||||
if [ ! -d "$2/$1" ]; then
|
|
||||||
echo "pkg_view: \`$1' doesn't exist in \`$2'" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#########################################
|
|
||||||
# Initialization and Options Processing #
|
|
||||||
#########################################
|
|
||||||
|
|
||||||
doit=""
|
|
||||||
stowdir=""
|
|
||||||
viewbase=${LOCALBASE:-/usr/pkg}
|
|
||||||
view=${PKG_VIEW:-""}
|
|
||||||
dflt_ignorefiles=${PLIST_IGNORE_FILES:-"info/dir *[~#] *.OLD *.orig *,v"}
|
|
||||||
dflt_pkg_dbdir=${PKG_DBDIR:-/usr/db/pkg}
|
|
||||||
ignorefiles=""
|
|
||||||
verbose=0
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case "$1" in
|
|
||||||
-d) stowdir=$2; shift ;;
|
|
||||||
-d*) stowdir=`echo $1 | $sedprog -e 's|^-d||'` ;;
|
|
||||||
-i) ignorefiles="$ignorefiles $2"; shift ;;
|
|
||||||
-i*) ignorefiles="$ignorefiles `echo $1 | $sedprog -e 's|^-i||'`" ;;
|
|
||||||
-k) dflt_pkg_dbdir="$2"; shift ;;
|
|
||||||
-k*) dflt_pkg_dbdir=`echo $1 | $sedprog -e 's|^-k||'` ;;
|
|
||||||
-n) doit=":" ;;
|
|
||||||
-V) version ;;
|
|
||||||
-v) verbose=`expr $verbose + 1` ;;
|
|
||||||
-W) viewbase=$2; shift ;;
|
|
||||||
-W*) viewbase=`echo $1 | $sedprog -e 's|^-p||'` ;;
|
|
||||||
-w) view=$2; shift ;;
|
|
||||||
--view=*) view=`echo $1 | $sedprog -e 's|--view=||'` ;;
|
|
||||||
--) shift; break ;;
|
|
||||||
*) break ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $# -lt 1 ]; then
|
|
||||||
usage
|
|
||||||
fi
|
|
||||||
|
|
||||||
# echoN will actually give output if ${verbose} > N.
|
|
||||||
echo1=":"
|
|
||||||
echo2=":"
|
|
||||||
if [ ${verbose} -gt 0 ]; then echo1=echo; fi
|
|
||||||
if [ ${verbose} -gt 1 ]; then echo2=echo; fi
|
|
||||||
|
|
||||||
action=""
|
|
||||||
case "$1" in
|
|
||||||
add) action=add ;;
|
|
||||||
check) action=check ;;
|
|
||||||
delete|rm) action=delete ;;
|
|
||||||
*) usage ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
|
|
||||||
# if standard view, put package info into ${dflt_pkg_dbdir}
|
|
||||||
# if not standard view, put package info into view's pkgdb
|
|
||||||
case "$view" in
|
|
||||||
"")
|
|
||||||
pkg_dbdir=${dflt_pkg_dbdir}
|
|
||||||
targetdir=${viewbase}
|
|
||||||
viewstr="the standard view"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
pkg_dbdir=${viewbase}/${view}/.pkgdb
|
|
||||||
targetdir=${viewbase}/${view}
|
|
||||||
viewstr="view \"${view}\""
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Use stowdir if it's given, else fall back to ${DEPOTBASE} or else
|
|
||||||
# default to ${viewbase}/packages.
|
|
||||||
#
|
|
||||||
depot_pkg_dbdir=${stowdir:-${DEPOTBASE:-${viewbase}/packages}}
|
|
||||||
|
|
||||||
case "${depot_pkg_dbdir}" in
|
|
||||||
${pkg_dbdir})
|
|
||||||
echo "pkg_view: the depot and the view package database directories are the same" 1>&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
##########################
|
|
||||||
# Shell helper functions #
|
|
||||||
##########################
|
|
||||||
|
|
||||||
# symlinks check|add|delete <pkg>
|
|
||||||
#
|
|
||||||
# Calls linkfarm(1) to check, add or delete the symlink farm in
|
|
||||||
# ${targetdir}. We also ignore the right set of files when doing the
|
|
||||||
# linkfarm operations.
|
|
||||||
#
|
|
||||||
symlinks() {
|
|
||||||
pkg=$2
|
|
||||||
case "$1" in
|
|
||||||
add) linkfarmflags="" ;;
|
|
||||||
check) linkfarmflags="-c" ;;
|
|
||||||
delete) linkfarmflags="-D" ;;
|
|
||||||
esac
|
|
||||||
if [ -f ${depot_pkg_dbdir}/$pkg/+BUILD_INFO ]; then
|
|
||||||
ignore=`$grepprog "^_PLIST_IGNORE_FILES=" ${depot_pkg_dbdir}/$pkg/+BUILD_INFO | $sedprog -e 's|^_PLIST_IGNORE_FILES=[ ]*||'`
|
|
||||||
fi
|
|
||||||
case "$ignore" in
|
|
||||||
"") ignore="${dflt_ignorefiles}" ;;
|
|
||||||
esac
|
|
||||||
dbs=`(cd ${depot_pkg_dbdir}/$pkg; echo +*)`
|
|
||||||
ignore="${ignore} ${ignorefiles} $dbs"
|
|
||||||
$doit $envprog PLIST_IGNORE_FILES="${ignore}" $linkfarmprog $linkfarmflags --target=${targetdir} --dir=${depot_pkg_dbdir} $pkg
|
|
||||||
}
|
|
||||||
|
|
||||||
#############
|
|
||||||
# Main Loop #
|
|
||||||
#############
|
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
|
||||||
case $action in
|
|
||||||
add)
|
|
||||||
checkpkg $1 ${depot_pkg_dbdir}
|
|
||||||
if [ -f ${pkg_dbdir}/$1/+DEPOT ]; then
|
|
||||||
echo "pkg_view: \`$1' already exists in $viewstr" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
$echo1 "Adding $1 to ${targetdir}."
|
|
||||||
symlinks add $1
|
|
||||||
$doit $mkdirprog -p ${depot_pkg_dbdir}/$1
|
|
||||||
temp=${depot_pkg_dbdir}/$1/+VIEWS.$$
|
|
||||||
$doit $touchprog ${depot_pkg_dbdir}/$1/+VIEWS
|
|
||||||
$doit $cpprog ${depot_pkg_dbdir}/$1/+VIEWS ${temp}
|
|
||||||
case "$doit" in
|
|
||||||
"") ($grepprog -v '^'${pkg_dbdir}'$' ${temp} || true; echo ${pkg_dbdir}) > ${depot_pkg_dbdir}/$1/+VIEWS ;;
|
|
||||||
esac
|
|
||||||
$doit $rmprog ${temp}
|
|
||||||
$doit $mkdirprog -p ${pkg_dbdir}/$1
|
|
||||||
#
|
|
||||||
# Copy all of the metadata files except for +VIEWS,
|
|
||||||
# which is only for the depoted package, and
|
|
||||||
# +REQUIRED_BY, which is irrelevant for a package in
|
|
||||||
# a view.
|
|
||||||
#
|
|
||||||
case "$doit" in
|
|
||||||
"") (cd ${depot_pkg_dbdir}/$1; $paxprog -rwpe '-s|\./+VIEWS$||' '-s|\./+REQUIRED_BY$||' ./+* ${pkg_dbdir}/$1)
|
|
||||||
$sedprog -e 's|'${depot_pkg_dbdir}/$1'|'${targetdir}'|g' < ${depot_pkg_dbdir}/$1/+CONTENTS > ${pkg_dbdir}/$1/+CONTENTS
|
|
||||||
echo "${depot_pkg_dbdir}/$1" > ${pkg_dbdir}/$1/+DEPOT
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
$doit $pkgadminprog -K ${pkg_dbdir} add $1
|
|
||||||
if [ -f ${pkg_dbdir}/$1/+INSTALL ]; then
|
|
||||||
$doit $chmodprog +x ${pkg_dbdir}/$1/+INSTALL
|
|
||||||
$doit $envprog -i PKG_PREFIX=${targetdir} ${pkg_dbdir}/$1/+INSTALL $1 VIEW-INSTALL
|
|
||||||
ec=$?
|
|
||||||
if [ $ec != 0 ]; then
|
|
||||||
echo "pkg_view: install script returned an error." 1>&2
|
|
||||||
exit $ec
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
check)
|
|
||||||
checkpkg $1 ${depot_pkg_dbdir}
|
|
||||||
$echo1 "Checking $1 in ${targetdir}."
|
|
||||||
symlinks check $1
|
|
||||||
exit $?
|
|
||||||
;;
|
|
||||||
delete)
|
|
||||||
checkpkg $1 ${depot_pkg_dbdir}
|
|
||||||
if [ ! -f ${pkg_dbdir}/$1/+DEPOT ]; then
|
|
||||||
echo "pkg_view: \`$1' doesn't exist in $viewstr" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
$echo1 "Deleting $1 from ${targetdir}."
|
|
||||||
if [ -f ${pkg_dbdir}/$1/+REQUIRED_BY ]; then
|
|
||||||
if $cmpprog -s ${pkg_dbdir}/$1/+REQUIRED_BY /dev/null; then
|
|
||||||
: # not really required by another pkg
|
|
||||||
else
|
|
||||||
(echo "pkg_view: \`$1' is required by other packages:"
|
|
||||||
$sedprog -e 's|^| |' ${pkg_dbdir}/$1/+REQUIRED_BY) 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ -f ${pkg_dbdir}/$1/+DEINSTALL ]; then
|
|
||||||
$doit $chmodprog +x ${pkg_dbdir}/$1/+DEINSTALL
|
|
||||||
$doit $envprog -i PKG_PREFIX=${targetdir} ${pkg_dbdir}/$1/+DEINSTALL $1 VIEW-DEINSTALL
|
|
||||||
ec=$?
|
|
||||||
if [ $ec != 0 ]; then
|
|
||||||
echo "pkg_view: de-install script returned an error." 1>&2
|
|
||||||
exit $ec
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
symlinks delete $1
|
|
||||||
temp=${depot_pkg_dbdir}/$1/+VIEWS.$$
|
|
||||||
$doit $cpprog ${depot_pkg_dbdir}/$1/+VIEWS ${temp}
|
|
||||||
case "$doit" in
|
|
||||||
"") ($grepprog -v '^'${pkg_dbdir}'$' ${temp} || true) > ${depot_pkg_dbdir}/$1/+VIEWS ;;
|
|
||||||
esac
|
|
||||||
$doit $rmprog ${temp}
|
|
||||||
$doit $rmprog -rf ${pkg_dbdir}/$1
|
|
||||||
$doit $pkgadminprog -K ${pkg_dbdir} delete $1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,136 +0,0 @@
|
||||||
# $NetBSD: pkgsrc.cnf,v 1.2 2009/02/02 12:49:16 joerg Exp $
|
|
||||||
#
|
|
||||||
# OpenSSL sample configuration file for use by pkgsrc.sh
|
|
||||||
#
|
|
||||||
|
|
||||||
# This definition stops the following lines choking if HOME isn't
|
|
||||||
# defined.
|
|
||||||
HOME = .
|
|
||||||
RANDFILE = $ENV::HOME/.rnd
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
[ ca ]
|
|
||||||
default_ca = CA_default # The default ca section
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
[ CA_default ]
|
|
||||||
|
|
||||||
dir = ./pkgsrc # Where everything is kept
|
|
||||||
certs = $dir/certs # Where the issued certs are kept
|
|
||||||
crl_dir = $dir/crl # Where the issued crl are kept
|
|
||||||
database = $dir/index.txt # database index file.
|
|
||||||
#unique_subject = no # Set to 'no' to allow creation of
|
|
||||||
# several ctificates with same subject.
|
|
||||||
new_certs_dir = $dir/newcerts # default place for new certs.
|
|
||||||
|
|
||||||
certificate = $dir/cacert.pem # The CA certificate
|
|
||||||
serial = $dir/serial # The current serial number
|
|
||||||
crlnumber = $dir/crlnumber # the current crl number
|
|
||||||
# must be commented out to leave a V1 CRL
|
|
||||||
crl = $dir/crl.pem # The current CRL
|
|
||||||
private_key = $dir/private/cakey.pem# The private key
|
|
||||||
RANDFILE = $dir/private/.rand # private random number file
|
|
||||||
|
|
||||||
# Comment out the following two lines for the "traditional"
|
|
||||||
# (and highly broken) format.
|
|
||||||
name_opt = ca_default # Subject Name options
|
|
||||||
cert_opt = ca_default # Certificate field options
|
|
||||||
|
|
||||||
# Extension copying option: use with caution.
|
|
||||||
# copy_extensions = copy
|
|
||||||
|
|
||||||
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
|
||||||
# so this is commented out by default to leave a V1 CRL.
|
|
||||||
# crlnumber must also be commented out to leave a V1 CRL.
|
|
||||||
# crl_extensions = crl_ext
|
|
||||||
|
|
||||||
default_days = 365 # how long to certify for
|
|
||||||
default_crl_days= 30 # how long before next CRL
|
|
||||||
default_md = default # use public key default MD
|
|
||||||
preserve = no # keep passed DN ordering
|
|
||||||
|
|
||||||
# A few difference way of specifying how similar the request should look
|
|
||||||
# For type CA, the listed attributes must be the same, and the optional
|
|
||||||
# and supplied fields are just that :-)
|
|
||||||
policy = policy_match
|
|
||||||
|
|
||||||
# For the CA policy
|
|
||||||
[ policy_match ]
|
|
||||||
countryName = match
|
|
||||||
stateOrProvinceName = match
|
|
||||||
organizationName = match
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
# For the 'anything' policy
|
|
||||||
# At this point in time, you must list all acceptable 'object'
|
|
||||||
# types.
|
|
||||||
[ policy_anything ]
|
|
||||||
countryName = optional
|
|
||||||
stateOrProvinceName = optional
|
|
||||||
localityName = optional
|
|
||||||
organizationName = optional
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
####################################################################
|
|
||||||
[ req ]
|
|
||||||
default_bits = 2048
|
|
||||||
default_keyfile = privkey.pem
|
|
||||||
default_md = sha1
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
|
||||||
|
|
||||||
string_mask = utf8only
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = Country Name (2 letter code)
|
|
||||||
countryName_default = AU
|
|
||||||
countryName_min = 2
|
|
||||||
countryName_max = 2
|
|
||||||
|
|
||||||
stateOrProvinceName = State or Province Name (full name)
|
|
||||||
stateOrProvinceName_default = Some-State
|
|
||||||
|
|
||||||
localityName = Locality Name (eg, city)
|
|
||||||
|
|
||||||
0.organizationName = Organization Name (eg, company)
|
|
||||||
0.organizationName_default = Internet Widgits Pty Ltd
|
|
||||||
|
|
||||||
# we can do this but it is not needed normally :-)
|
|
||||||
#1.organizationName = Second Organization Name (eg, company)
|
|
||||||
#1.organizationName_default = World Wide Web Pty Ltd
|
|
||||||
|
|
||||||
organizationalUnitName = Organizational Unit Name (eg, section)
|
|
||||||
#organizationalUnitName_default =
|
|
||||||
|
|
||||||
commonName = Common Name (eg, YOUR name)
|
|
||||||
commonName_max = 64
|
|
||||||
|
|
||||||
emailAddress = Email Address
|
|
||||||
emailAddress_max = 64
|
|
||||||
|
|
||||||
[ pkgkey ]
|
|
||||||
nsComment = "Certificate for binary pkgsrc packages"
|
|
||||||
|
|
||||||
subjectKeyIdentifier=hash
|
|
||||||
authorityKeyIdentifier=keyid,issuer
|
|
||||||
|
|
||||||
subjectAltName=email:move
|
|
||||||
|
|
||||||
extendedKeyUsage = codeSigning, emailProtection
|
|
||||||
|
|
||||||
[ pkgsec ]
|
|
||||||
nsComment = "Certificate for pkg-vulnerabilities"
|
|
||||||
|
|
||||||
subjectKeyIdentifier=hash
|
|
||||||
authorityKeyIdentifier=keyid,issuer
|
|
||||||
|
|
||||||
subjectAltName=email:move
|
|
||||||
|
|
||||||
[ v3_ca ]
|
|
||||||
subjectKeyIdentifier=hash
|
|
||||||
authorityKeyIdentifier=keyid:always,issuer:always
|
|
||||||
basicConstraints = critical,CA:true
|
|
|
@ -1,63 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# $NetBSD: pkgsrc.sh,v 1.2 2009/02/02 12:49:16 joerg Exp $
|
|
||||||
#
|
|
||||||
|
|
||||||
CA="openssl ca -config pkgsrc.cnf"
|
|
||||||
REQ="openssl req -config pkgsrc.cnf"
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
new_ca() {
|
|
||||||
if [ -f $1/serial ]; then
|
|
||||||
echo "CA already exists, exiting" >& 2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p $1/certs $1/crl $1/newcerts $1/private
|
|
||||||
echo "00" > $1/serial
|
|
||||||
touch $1/index.txt
|
|
||||||
|
|
||||||
echo "Making CA certificate ..."
|
|
||||||
$REQ -new -keyout $1/private/cakey.pem \
|
|
||||||
-out $1/careq.pem
|
|
||||||
$CA -out $1/cacert.pem -batch \
|
|
||||||
-keyfile $1/private/cakey.pem -selfsign \
|
|
||||||
-infiles $1/careq.pem
|
|
||||||
}
|
|
||||||
|
|
||||||
new_pkgkey() {
|
|
||||||
$REQ -new -keyout pkgkey_key.pem -out pkgkey_req.pem
|
|
||||||
$CA -extensions pkgkey -policy policy_match -out pkgkey_cert.pem -infiles pkgkey_req.pem
|
|
||||||
rm pkgkey_req.pem
|
|
||||||
echo "Signed certificate is in pkgkey_cert.pem, key in pkgkey_key.pem"
|
|
||||||
}
|
|
||||||
|
|
||||||
new_pkgsec() {
|
|
||||||
$REQ -new -keyout pkgsec_key.pem -out pkgsec_req.pem
|
|
||||||
$CA -extensions pkgsec -policy policy_match -out pkgsec_cert.pem -infiles pkgsec_req.pem
|
|
||||||
rm pkgsec_req.pem
|
|
||||||
echo "Signed certificate is in pkgsec_cert.pem, key in pkgsec_key.pem"
|
|
||||||
}
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
echo "$0:"
|
|
||||||
echo "setup - create new CA in ./pkgsrc for use by pkg_install"
|
|
||||||
echo "pkgkey - create and sign a certificate for binary packages"
|
|
||||||
echo "pkgsec - create and sign a certificate for pkg-vulnerabilities"
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
setup)
|
|
||||||
new_ca ./pkgsrc
|
|
||||||
;;
|
|
||||||
pkgkey)
|
|
||||||
new_pkgkey
|
|
||||||
;;
|
|
||||||
pkgsec)
|
|
||||||
new_pkgsec
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
;;
|
|
||||||
esac
|
|
|
@ -1,59 +0,0 @@
|
||||||
Use of digital signatures in pkg_install
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
(1) pkg_vulnerabilities: list of known vulnerabilities, provided by
|
|
||||||
the pkgsrc security team and updated regulary
|
|
||||||
(2) binary packages: check who provided binary packages
|
|
||||||
|
|
||||||
For (1) gpg is currently the only choice. After pkgsrcCon (?) a PKCS7
|
|
||||||
signature will be added as well. With the pkg_install-renovation branch,
|
|
||||||
PKCS7 is the only supported verification mechanism for (2) and preferred
|
|
||||||
for (1) once the infrastructure exists.
|
|
||||||
|
|
||||||
PKCS7 is a format to use RSA public key cryptography with X509
|
|
||||||
certificates. Those are commonly used for SSL. X509 implements a
|
|
||||||
hierachical trust model. For this purpose it means that one or more
|
|
||||||
certificates are installed and marked as trusted. A certificate used for
|
|
||||||
signing a binary package or pkg_vulnerabilities will have to be included
|
|
||||||
in the list to be trusted OR it must be itself signed by a trusted
|
|
||||||
certificate. The original list is called the TRUST ANCHOR.
|
|
||||||
|
|
||||||
Optionally, a second list of certificates can be provided to fill gaps.
|
|
||||||
Let's assume A is a trust anchor and C is used to sign a package. C
|
|
||||||
itself is not signed by A, so it won't be trusted. Instead, there's a
|
|
||||||
third certificate B; and C includes a signature with B. The certificate
|
|
||||||
chain file can now provide B signed by A. This gives a certificate chain
|
|
||||||
of C -> B (included in the package) -> A (with the chain file) and the
|
|
||||||
signature is valid and trusted.
|
|
||||||
|
|
||||||
|
|
||||||
Practical implications for pkgsrc users:
|
|
||||||
- get the pkgsrc-security certificate and point CERTIFICATE_ANCHOR_PKGVULN to it
|
|
||||||
- get the certificate used by your bulk builder and point
|
|
||||||
CERTIFICATE_ANCHOR_PKGS to it
|
|
||||||
- at some later point a CA for pkgsrc might be created, in that case it
|
|
||||||
will serve as certificate for both purposes; a list of all certificates
|
|
||||||
will be provided in that case to point CERTIFICATE_CHAIN to.
|
|
||||||
|
|
||||||
|
|
||||||
How to create your own keys:
|
|
||||||
|
|
||||||
The pkgsrc.sh script and the corresponding pkgsrc.cnf file provide a working
|
|
||||||
wrapper around the OpenSSL command line tool.
|
|
||||||
|
|
||||||
The root certificate can be created by running "sh pkgsrc.sh setup",
|
|
||||||
the output can found in the pkgsrc subdirectory of the current directory.
|
|
||||||
The meta data is for human beings and displayed e.g. by pkg_add, but not
|
|
||||||
relevant for cryptographic purposes. pkgsrc/newcerts/00.pem is the
|
|
||||||
public key and can be used as trust anchor.
|
|
||||||
A certificate for signing packages can be created by running
|
|
||||||
"sh pkgsrc.sh pkgkey". The private key can be found in pkgkey_key.pem
|
|
||||||
and the certificate in pkgkey_cert.pem.
|
|
||||||
Similary, "sh pkgsrc.sh pkgsec" will create a certificate/key pair for
|
|
||||||
signing pkg-vulnerabilities.
|
|
||||||
|
|
||||||
How to verify a certificate:
|
|
||||||
- decode the data with "openssl x509 -text -noout -in newcert.pem"
|
|
||||||
- "Issuer" is vouching for the identity (and reliability) of "Subject"
|
|
||||||
- "X509v3 Basic Constraints" should list "CA:FALSE" for all keys that are not allowed
|
|
||||||
to sign further keys.
|
|
|
@ -9,7 +9,9 @@ PKGSRC_COMPILER= gcc
|
||||||
PKG_DBDIR= /usr/var/db/pkg
|
PKG_DBDIR= /usr/var/db/pkg
|
||||||
LOCALBASE= /usr/pkg
|
LOCALBASE= /usr/pkg
|
||||||
VARBASE= /usr/var
|
VARBASE= /usr/var
|
||||||
|
.if exists(/usr/sbin/pkg_add)
|
||||||
PKG_TOOLS_BIN= /usr/sbin
|
PKG_TOOLS_BIN= /usr/sbin
|
||||||
|
.endif
|
||||||
PKGMANDIR= man
|
PKGMANDIR= man
|
||||||
|
|
||||||
FETCH_USING?= fetch
|
FETCH_USING?= fetch
|
||||||
|
|
|
@ -12,7 +12,7 @@ secs=`expr 32 '*' 64`
|
||||||
export SHELL=/bin/sh
|
export SHELL=/bin/sh
|
||||||
|
|
||||||
# Packages we have to pre-install, and url to use
|
# Packages we have to pre-install, and url to use
|
||||||
PREINSTALLED_PACKAGES=pkgin-0.3.3.1nb1
|
PREINSTALLED_PACKAGES="pkgin-0.3.3.4.tgz pkg_install-20101212"
|
||||||
PACKAGEURL=ftp://ftp.minix3.org/pub/minix/packages/`uname -r`/`uname -m`/All/
|
PACKAGEURL=ftp://ftp.minix3.org/pub/minix/packages/`uname -r`/`uname -m`/All/
|
||||||
|
|
||||||
RELEASERC=$HOME/.releaserc
|
RELEASERC=$HOME/.releaserc
|
||||||
|
|
Loading…
Reference in a new issue