/*
* 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
*/
/*
*/
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <pkgdev.h>
#include <pkginfo.h>
#include <pkglocs.h>
#include <locale.h>
#include <libintl.h>
#include <instzones_api.h>
#include <pkglib.h>
#include <install.h>
#include <libinst.h>
#include <libadm.h>
#include <messages.h>
/* commands to execute */
#define GLOBALZONE_ONLY_PACKAGE_FILE_PATH \
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
/*
* forward declarations
*/
static struct pkginfo *_pkginfoFactory(void);
static char **thisZonePackages;
static int numThisZonePackages;
/*
* *****************************************************************************
* global external (public) functions
* *****************************************************************************
*/
/*
* Name: pkginfoFree
* Description: free pkginfo structure returned from various functions
* Arguments: r_info - pointer to pointer to pkginfo structure to free
* Returns: void
*/
void
{
/* entry assertions */
/* localize reference to info structure to free */
/* reset callers handle to info structure */
/* free up contents of the structure */
/* free up structure itself */
}
/*
* Name: pkginfoIsPkgInstalled
* Description: determine if specified package is installed, return pkginfo
* structure describing package if package is installed
* Arguments: r_pinfo - pointer to pointer to pkginfo structure
* If this pointer is NOT null:
* -On success, this handle is filled in with a pointer
* --to a newly allocated pkginfo structure describing
* --the package discovered
* -On failure, this handle is filled with NULL
* If this pointer is NULL:
* -no pkginfo structure is returned on success.
* a_pkgInst - package instance (name) to lookup
* Returns: boolean_t
* B_TRUE - package installed, pkginfo returned
* B_FALSE - package not installed, no pkginfo returned
* NOTE: This function returns the first instance of package that
* is installed - see pkginfo() function for details
* NOTE: Any pkginfo structure returned is placed in new storage for the
* calling function. The caller must use 'pkginfoFree' to dispose
* of the storage once the pkginfo structure is no longer needed.
*/
{
int r;
/* entry assertions */
/* reset returned pkginfo structure handle */
}
/* allocate a new pinfo structure for use in the call to pkginfo */
pinf = _pkginfoFactory();
/* lookup the specified package */
/* NOTE: required 'pkgdir' set to spool directory or NULL */
} else {
/* free pkginfo structure */
pkginfoFree(&pinf);
}
}
/*
* Name: pkgOpenInGzOnlyFile
* Description: Open the global zone only package list file
* Arguments: a_rootPath - pointer to string representing the root path
* where the global zone only package list file is
* located - NULL is the same as "/"
* Returns: FILE *
* == NULL - failure - file not open
* != NULL - success - file pointer returned
* NOTE: This function will create the file if it does not exist.
*/
FILE *
{
int len;
/* normalize root path */
if (a_rootPath == (char *)NULL) {
a_rootPath = "";
}
/* generate path to glocal zone only list file */
if (len > sizeof (pkgingzonlyPath)) {
}
/* open global zone only list file */
}
}
/* success - return FILE pointer open on global zone only list file */
return (pkgingzonlyFP);
}
/*
* Name: pkgIsPkgInGzOnly
* Description: determine if package is recorded as "in global zone only"
* by opening the appropriate files and searching for the
* specified package
* Arguments: a_rootPath - pointer to string representing the root path
* where the global zone only package list file is
* located - NULL is the same as "/"
* a_pkgInst - pointer to string representing the package instance
* (name) of the package to lookup
* Returns: boolean_t
* B_TRUE - package is recorded as "in global zone only"
* B_FALSE - package is NOT recorded as "in gz only"
* NOTE: This function will create the file if it does not exist.
*/
{
/* normalize root path */
if (a_rootPath == (char *)NULL) {
a_rootPath = "";
}
/* open the global zone only package list file */
return (B_FALSE);
}
/* is the package recorded as "in global zone only" ? */
/* close the global zone only package list file */
/* return results */
return (in_gz_only);
}
/*
* Name: pkgIsPkgInGzOnly
* Description: determine if package is recorded as "in global zone only"
* by searching the specified open FILE for the specified package
* Arguments: a_fp - pointer to FILE handle open on file to search
* a_pkgInst - pointer to string representing the package instance
* (name) of the package to lookup
* Returns: boolean_t
* B_TRUE - package is recorded as "in global zone only"
* B_FALSE - package is NOT recorded as "in gz only"
*/
{
/* entry assertions */
/* rewind the file to the beginning */
/* read the file line by line searching for the specified package */
int len;
/* strip off trailing newlines */
}
/* ignore blank and comment lines */
continue;
}
/* return true if this is the package we are looking for */
return (B_TRUE);
}
}
/* end of file - package not found */
return (B_FALSE);
}
/*
* Name: pkgRemovePackageFromGzonlyList
* Description: Remove specified package from the global zone only package list
* file located at a specified root path
* Arguments: a_rootPath - pointer to string representing the root path
* where the global zone only package list file is
* located - NULL is the same as "/"
* a_pkgInst - pointer to string representing the package instance
* (name) of the package to remove
* Returns: boolean_t
* B_TRUE - package is successfully removed
* B_FALSE - failed to remove package from file
* NOTE: This function will create the file if it does not exist.
*/
{
int len;
/* entry assertions */
/* normalize root path */
if (a_rootPath == (char *)NULL) {
a_rootPath = "";
}
/*
* calculate paths to various objects
*/
/* path to current "source" ingzonly file */
return (B_FALSE);
}
/* path to new "destination" ingzonly file */
return (B_FALSE);
}
/* path to temporary "saved" ingzonly file */
return (B_FALSE);
}
/* open source file, creating if necessary */
}
return (B_FALSE);
}
}
return (B_FALSE);
}
/* add standard comment to beginning of file */
/* put standard header at the beginning of the file */
int len;
/* strip off trailing newlines */
}
/* ignore blank and comment lines */
continue;
}
/* add pkg if yet to add and pkg <= line */
pkgremoved = B_TRUE;
} else {
}
}
/* close both files */
/*
* if package not found there is no need to update the original file
*/
if (pkgremoved == B_FALSE) {
return (B_TRUE);
}
/*
* Now we want to make a copy of the old gzonly file as a
* fail-safe.
*/
return (B_FALSE);
}
return (B_FALSE);
}
}
return (B_FALSE);
}
}
/* successfully removed package */
return (B_TRUE);
}
/*
* Name: pkgAddPackageFromGzonlyList
* Description: Add specified package to the global zone only package list
* file located at a specified root path
* Arguments: a_rootPath - pointer to string representing the root path
* where the global zone only package list file is
* located - NULL is the same as "/"
* a_pkgInst - pointer to string representing the package instance
* (name) of the package to add
* Returns: boolean_t
* B_TRUE - package is successfully added
* B_FALSE - failed to add package to the file
* NOTE: This function will create the file if it does not exist.
*/
{
int len;
/* entry assertions */
/* normalize root path */
if (a_rootPath == (char *)NULL) {
a_rootPath = "";
}
/* entry debugging info */
/*
* calculate paths to various objects
*/
/* path to current "source" ingzonly file */
return (B_FALSE);
}
/* path to new "destination" ingzonly file */
return (B_FALSE);
}
/* path to temporary "saved" ingzonly file */
return (B_FALSE);
}
/* open source file, creating if necessary */
}
return (B_FALSE);
}
}
return (B_FALSE);
}
/* add standard comment to beginning of file */
/* put standard header at the beginning of the file */
int len;
/* strip off trailing newlines */
}
/* ignore blank and comment lines */
continue;
}
/* add pkg if yet to add and pkg <= line */
}
}
}
/* if package not added yet, add to end of the file */
}
/* close both files */
/*
* Now we want to make a copy of the old gzonly file as a
* fail-safe.
*/
return (B_FALSE);
}
return (B_FALSE);
}
}
return (B_FALSE);
}
}
/* successfully added package */
return (B_TRUE);
}
/*
* Name: pkginfoParamTruth
* Arguments: a_fp - Pointer to FILE handle open on pkginfo file to search
* a_param - Pointer to string representing the parameter name
* to search for
* a_value - Pointer to string representing the "success" value
* being searched for
* a_default - determine results if parameter NOT found
* B_TRUE - parameter is TRUE if not found
* B_FALSE - parameter is FALSE if not found
* Returns: boolean_t
* B_TRUE - the parameter was found and matched the specified value
* OR the paramter was not found and a_default == B_TRUE
* B_FALSE - the parameter was found and did NOT match the value
* OR the paramter was not found and a_default == B_FALSE
*/
{
char *param;
/* entry assertions */
/* rewind the file to the beginning */
/* search pkginfo file for the specified parameter */
/* parameter not found - return default */
} else if (*param == '\0') {
/* parameter found but no value - return default */
/* paramter found - matches value */
} else {
/* parameter found - does not match value */
}
/* exit debugging info */
/* if parameter value found, free results */
}
/* return results of search */
return (result);
}
/*
* Name: pkgGetPackageList
* Description: Determine list of packages based on list of packages that are
* available, category of packages to select, and list of packages
* to select.
* Arguments: r_pkgList - pointer to pointer to string array where the list
* of selected packages will be returned
* a_argv - pointer to string array containing list of packages
* to select
* a_optind - index into string array of first package to select
* a_categories - pointer to string representing the categories of
* packages to select
* a_categoryList - pointer to string array representing a list
* of categories to select
* a_pkgdev - package dev containing packages that can be selected
* Returns: int
* == 0 - packages found r_pkgList contains results package list retrieved
* == -1 - no packages found (errno == ENOPKG)
* != 0 - "quit" value entered by user
* NOTE: If both a category and a list of packages to select are provided
* the category is used over the list of packages provided
* NOTE: If neither a category nor a list of packages to select are
* provided, an error is returned
*/
int
{
/* entry assertions */
/* entry debugging info */
/* reset returned package list handle */
/*
* generate list of packages to be removed: if removing by category,
* then generate package list based on all packages by category,
* else generate package list based on all packages specified.
*/
if (a_categories != NULL) {
/* generate package list from all packages in given category */
return (1);
}
return (0);
}
/* generate package list from specified packages */
/* if list generated return results */
return (0);
}
/* handle error from gpkglist */
switch (errno) {
case ENOPKG: /* no packages */
return (-1);
case ESRCH:
return (1);
case EINTR:
return (3);
default:
return (99);
}
}
/*
* return string representing path to "global zone only file"
*/
char *
pkgGetGzOnlyPath(void)
{
return (GLOBALZONE_ONLY_PACKAGE_FILE_PATH);
}
/*
* Name: pkgAddThisZonePackage
* Description: Add specified package to internal list of "this zone only" pkgs
* Arguments: a_pkgInst - name of package to add to list
* Returns: void
*/
void
{
/* entry assertions */
/* do not duplicate entries */
return;
}
/* add package name to internal list */
if (thisZonePackages == (char **)NULL) {
(char **)calloc(2, sizeof (char **));
} else {
(char **)realloc(thisZonePackages,
sizeof (char **)*(numThisZonePackages+2));
}
/* handle out of memory error */
if (thisZonePackages == (char **)NULL) {
quit(99);
}
/* add this entry to the end of the list */
quit(99);
}
/* make sure end of the list is properly terminated */
/* exit debugging info */
}
/*
* Name: pkgPackageIsThisZone
* Description: Determine if the specified package is marked to be installed
* in this zone only
* Arguments: a_pkgInst - pointer to string representing package name to check
* Returns: boolean_t
* B_TRUE - the package IS "this zone only"
* B_FALSE - the paackage is NOT "this zone only"
*/
{
int n;
/* entry assertions */
/*
* see if this package is in the "this zone only" list
*/
for (n = 0; n < numThisZonePackages; n++) {
return (B_TRUE);
}
}
/* path is not in "this zone only" list */
return (B_FALSE);
}
/*
* Name: pkgLocateHighestInst
* Description: Locate the highest installed instance of a package
* Arguments: r_path - [RO, *RW] - (char *)
* Pointer to buffer where the full path to the top level
* directory containing the latest instance of the
* specified package is located is placed.
* r_pathLen - [RO, *RO] - (int)
* Integer representing the size of r_path in bytes.
* r_pkgInst - [RO, *RW] - (char *)
* Pointer to buffer where the package instance name of the
* latest instance of the specified package is placed.
* r_pkgInstLen - [RO, *RO] - (int)
* Integer representing the size of r_pkgInst in bytes.
* a_rootPath - [RO, *RO] - (char *)
* Pointer to string representing the root path to look
* for the latest instance of the specified package.
* a_pkgInst - [RO, *RO] - (char *)
* Pointer to string representing the name of the package
* to locate the latest installed instance of.
*/
void
{
int npkgs;
/* entry assertions */
assert(r_pkgInstLen > 0);
/* normalize root path */
a_rootPath = "";
}
PKGLOC);
/* entry debugging info */
*r_path = '\0';
*r_pkgInst = '\0';
/* remove any architecture extension */
/* make sure that the package name is valid and can be wild carded */
quit(99);
}
/* create wild card specification for this package instance */
/*
* inspect the system to determine if any instances of the
* package being installed already exist on the system
*/
char *savePkgdir;
int r;
/* allocate new pinfo structure for use in the pkginfo call */
pinf = _pkginfoFactory();
/*
* lookup the specified package; the first call will cause the
* pkgdir directory to be opened - it will be closed when the
* end of directory is read and pkginfo() returns != 0. You must
* cycle through all instances until pkginfo() returns != 0.
* NOTE: pkginfo() requires the global variable 'pkgdir' be set
*/
savePkgdir = pkgdir;
pkgdir = savePkgdir;
/* break out of loop of no package found */
if (r != 0) {
pkginfoFree(&pinf);
break;
}
pkginfoFree(&pinf);
}
}
/*
* Name: pkgTestInstalled
* Description: determine if package is installed at specified root path
* Arguments: a_packageName - name of package to test
* a_rootPath - root path of alternative root to test
* Returns: B_TRUE - package is installed
* B_FALSE - package is not installed
*/
{
int rc;
/* entry assertions */
/* entry debugging info */
/*
* create pkginfo command to execute:
*/
/* execute command */
/* return success if pkginfo returns "0" */
if (rc == 0) {
return (B_TRUE);
}
/* package not installed */
return (B_FALSE);
}
/*
* *****************************************************************************
* static internal (private) functions
* *****************************************************************************
*/
static void
{
/* entry assertions */
/* free previously allocated space */
}
}
static struct pkginfo *
_pkginfoFactory(void)
{
exit(1);
}
return (pinf);
}