main.c revision fbde34ed705bd3e0be54fb73ceb0e689cba71312
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/sysmacros.h>
#include <strings.h>
#include <pkgstrct.h>
#include <pkgdev.h>
#include <pkginfo.h>
#include <pkglocs.h>
#include <locale.h>
#include <libintl.h>
#include <instzones_api.h>
#include <pkglib.h>
#include <libadm.h>
#include <libinst.h>
/* mkpkgmap.c */
/* splpkgmap.c */
/* scriptvfy.c */
extern void setmapmode(int mode_no);
#define MALSIZ 16
#define NROOT 8
#define SPOOLDEV "spool"
#define MSG_PROTOTYPE "## Building pkgmap from package prototype file.\n"
#define MSG_PKGINFO "## Processing pkginfo file.\n"
#define MSG_VOLUMIZE "## Attempting to volumize %d entries in pkgmap.\n"
#define MSG_PACKAGE1 "## Packaging one part.\n"
#define MSG_PACKAGEM "## Packaging %d parts.\n"
#define MSG_VALSCRIPTS "## Validating control scripts.\n"
/* Other problems */
#define ERR_MEMORY "memory allocation failure, errno=%d"
#define ERR_NROOT "too many paths listed with -r option, limit is %d"
#define ERR_PKGINST "invalid package instance identifier <%s>"
#define ERR_PKGABRV "invalid package abbreviation <%s>"
#define ERR_BADDEV "unknown or invalid device specified <%s>"
#define ERR_TEMP "unable to obtain temporary file resources, errno=%d"
#define ERR_DSTREAM "invalid device specified (datastream) <%s>"
#define ERR_SPLIT "unable to volumize package"
#define ERR_MKDIR "unable to make directory <%s>"
#define ERR_SYMLINK "unable to create symbolic link for <%s>"
#define ERR_OVERWRITE "must use -o option to overwrite <%s>"
#define ERR_UMOUNT "unable to unmount device <%s>"
#define ERR_NOPKGINFO "required pkginfo file is not specified in prototype " \
"file"
#define ERR_RDPKGINFO "unable to process pkginfo file <%s>"
#define ERR_PROTOTYPE "unable to locate prototype file"
#define ERR_STATVFS "unable to stat filesystem <%s>"
#define ERR_WHATVFS "unable to determine or access output filesystem for " \
"device <%s>"
#define ERR_DEVICE "unable to find info for device <%s>"
#define ERR_BUILD "unable to build pkgmap from prototype file"
#define ERR_ONEVOL "other packages found - package must fit on a single " \
"volume"
#define ERR_NOPARAM "parameter <%s> is not defined in <%s>"
#define ERR_PKGMTCH "PKG parameter <%s> does not match instance <%s>"
#define ERR_NO_PKG_INFOFILE "unable to open pkginfo file <%s>: %s"
#define ERR_ALLZONES_AND_THISZONE "The package <%s> has <%s> = true " \
"and <%s> = true: the package may " \
"set either parameter to true, but " \
"may not set both parameters to " \
"true. NOTE: if the package " \
"contains a request script, it is " \
"treated as though it has " \
"<SUNW_PKG_THISZONE> = true"
#define ERR_NO_ALLZONES_AND_HOLLOW "The package <%s> has <%s> = false " \
"and <%s> = true: a hollow package " \
"must also be set to install in all " \
"zones"
#define ERR_PKGINFO_INVALID_OPTION_COMB "Invalid combinations of zone " \
"parameters in pkginfo file"
#define ERR_USAGE "usage: %s [options] [VAR=value [VAR=value]] " \
"[pkginst]\n" \
" where options may include:\n" \
"\t-o\n" \
"\t-a arch\n" \
"\t-v version\n" \
"\t-p pstamp\n" \
"\t-l limit\n" \
"\t-r rootpath\n" \
"\t-b basedir\n" \
"\t-d device\n" \
"\t-f protofile\n"
#define WRN_MISSINGDIR "WARNING: missing directory entry for <%s>"
#define WRN_SETPARAM "WARNING: parameter <%s> set to \"%s\""
#define WRN_CLASSES "WARNING: unreferenced class <%s> in prototype file"
#define LINK 1
int started;
char *basedir;
char *root;
char *t_pkgmap;
char *t_pkginfo;
static char *protofile,
*device;
static fsblkcnt_t limit = 0;
static fsblkcnt_t llimit = 0;
static fsfilcnt_t ilimit = 0;
static int overwrite,
int nparts);
static void trap(int n);
static void usage(void);
int
{
int c, n, found;
char buf[MAX_PKG_PARAM_LENGTH];
char temp[MAX_PKG_PARAM_LENGTH];
char param[MAX_PKG_PARAM_LENGTH];
**cmdparam;
char *pkgname;
char *pkgvers;
char *pkgarch;
char *pkgcat;
void (*func)();
unsigned int eptnum, i;
/* initialize locale environment */
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
/* initialize program name */
(void) set_prog_name(argv[0]);
/* tell spmi zones interface how to access package output functions */
switch (c) {
case 'n':
nflag++;
break;
case 's':
sflag++;
break;
case 'o':
overwrite++;
break;
case 'p':
break;
case 'l':
break;
case 'r':
n = 0;
do {
if (n >= NROOT) {
quit(1);
}
break;
case 'b':
break;
case 'f':
break;
case 'd':
break;
case 'a':
break;
case 'v':
break;
default:
usage();
/*NOTREACHED*/
/*
* Although usage() calls a noreturn function,
* needed to add return (1); so that main() would
* pass compilation checks. The statement below
* should never be executed.
*/
return (1);
}
}
/*
* Store command line variable assignments for later
* incorporation into the environment.
*/
/* Skip past equates. */
optind++;
/* Confirm that the instance name is valid */
quit(1);
}
}
usage();
/* bug id 4244631, not ABI compliant */
}
exit(99);
}
}
if (access("prototype", 0) == 0)
protofile = "prototype";
else if (access("Prototype", 0) == 0)
protofile = "Prototype";
else {
quit(1);
}
}
quit(1);
}
/* initialize datastream */
quit(1);
}
quit(n);
}
/*
* convert prototype file to a pkgmap, while locating
* package objects in the current environment
*/
exit(99);
}
quit(1);
}
quit(99);
}
quit(1);
}
/* Validate the zone attributes in pkginfo, before creation */
if (!valid_zone_attr(eptlist)) {
quit(1);
}
for (i = 0; eptlist[i]; i++) {
continue;
}
quit(99);
}
eptnum = i;
/*
* process all parameters from the pkginfo file
* and place them in the execution environment
*/
quit(99);
}
param[0] = '\0';
param[0] = '\0';
}
/* add command line variables */
value++; /* value is now the value (not '=') */
}
/* make sure parameters are valid */
quit(1);
}
} else {
quit(1);
}
/*
* verify consistency between PKG parameter and pkginst
*/
quit(1);
}
/*
* *********************************************************************
* this feature is removed starting with Solaris 10 - there is no built
* in list of packages that should be run "the old way"
* *********************************************************************
*/
#ifdef ALLOW_EXCEPTION_PKG_LIST
/* Until 2.9, set it from the execption list */
#endif
quit(1);
}
quit(1);
/* XXX - I18n */
/* LINTED do not use cftime(); use strftime instead */
}
quit(1);
}
quit(1);
/* use octal value of '%' to fight sccs expansion */
/* XXX - I18n */
/* LINTED do not use cftime(); use strftime instead */
}
quit(1);
}
quit(1);
/*
* warn user of classes listed in package which do
* not appear in CLASSES variable in pkginfo file
*/
objects = 0;
for (i = 0; eptlist[i]; i++) {
objects++;
}
}
getenv("CLASSES"));
}
} else {
for (i = 0; allclass[i]; i++) {
found = 0;
found++;
break;
}
if (!found) {
(char *)allclass[i]);
}
}
}
}
}
/* stat the intended output filesystem to get blocking information */
quit(99);
}
quit(99);
}
if (bsize == 0) {
}
if (frsize == 0) {
}
if (limit == 0)
/*
* bavail is in terms of fragment size blocks - change
* to 512 byte blocks
*/
if (ilimit == 0) {
}
if (nparts <= 0) {
quit(1);
}
if (nflag) {
for (i = 0; eptlist[i]; i++)
exit(0);
/*NOTREACHED*/
}
quit(1);
}
/* output all environment install parameters */
exit(99);
}
for (i = 0; environ[i]; i++) {
}
}
started++;
quit(1);
}
/* determine how many packages already reside on the medium */
npkgs = 0;
npkgs++;
if (nparts > 1) {
quit(1);
}
}
/*
* update pkgmap entry for pkginfo file, since it may
* have changed due to command line or failure to
* specify all neccessary parameters
*/
for (i = 0; eptlist[i]; i++) {
continue;
break;
}
}
if (nparts > 1)
else
quit(99);
}
quit(n);
quit(99);
}
}
/* Validate (as much as possible) the control scripts. */
if (part == 1) {
checkscripts(inst_path, 0);
}
}
quit(0);
/* LINTED: no return */
}
static void
trap(int n)
{
if (n == SIGINT)
quit(3);
else {
get_prog_name(), n);
quit(99);
}
}
static void
{
unsigned int i;
if (nparts > 1)
if (part == 1) {
/* re-write pkgmap, but exclude local pathnames */
quit(99);
}
for (i = 0; eptlist[i]; i++) {
quit(99);
}
}
}
quit(1);
for (i = 0; i < eptnum; i++) {
continue;
continue;
continue; /* don't copy pkginfo file */
} else
if (sflag) {
quit(1);
quit(1);
}
/*
* If the package file attributes can be sync'd up with
* the pkgmap, we fix the attributes here.
*/
/* Clear dangerous bits. */
/*
* Make sure it can be read by the world and written
* by the owner.
*/
/* Set the safe attributes. */
}
}
}
}
static void
{
static char **dir;
static int ndir;
char *pt;
int i, found;
quit(99);
}
}
quit(99);
}
}
}
if (*pt == '/')
pt++;
*pt = '\0';
found = 0;
for (i = 0; i < ndir; i++) {
found++;
break;
}
}
if (!found) {
}
*pt++ = '/';
}
}
static int
{
char *pt;
*pt = '\0';
*pt = '/';
return (-1);
}
*pt = '/';
}
return (-1);
}
return (0);
}
static void
usage(void)
{
exit(1);
/*NOTREACHED*/
}
/*
* valid_zone_attr: Validates the zone attributes specified in
* pkginfo file for this package. The package
* can not be created with certain combinations
* of the attributes.
*/
static boolean_t
{
char *pkgInst;
int i;
/* Path to pkginfo file within the package to be installed */
for (i = 0; eptlist[i]; i++) {
continue;
/*
* Check to see if this package has a request script. If this
* package does have a request script, then mark the package
* for installation in this zone only. Any package with a
* request script cannot be installed outside of the zone the
* pkgadd command is being run in, nor can such a package be
* installed as part of a new zone install. A new zone install
* must be non-interactive, which is required by all packages
* integrated into the Solaris WOS.
* If request file is set in prototype, then this_zone is TRUE.
*/
}
/* Gather information from the pkginfo file */
return (B_FALSE);
}
return (B_FALSE);
}
/* Determine "HOLLOW" setting for this package */
"true", B_FALSE);
/* Determine "ALLZONES" setting for this package */
"true", B_FALSE);
/* Determine "THISZONE" setting for this package, if no request file */
if (!this_zone)
"true", B_FALSE);
/* Close pkginfo file */
/*
* Validate zone attributes based on information gathered,
* and validate the three SUNW_PKG_ options:
*
* -----------------------------|---------------|
* <ALLZONES><HOLLOW><THISZONE> | If Allowed |
* ----1------------------------|---------------|
* F F F | OK |
* F F T | OK |
* F T * | NO |
* ----2------------------------|---------------|
* T F F | OK |
* T T F | OK |
* T * T | NO |
* -----------------------------|---------------|
*/
/* pkg "all zones" && "this zone" (#2) */
return (B_FALSE);
}
/* pkg "!all zones" && "hollow" (#1) */
return (B_FALSE);
}
return (B_TRUE);
}