summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorPeter Tribble <peter.tribble@gmail.com>2018-09-09 20:20:46 +0100
committerRichard Lowe <richlowe@richlowe.net>2018-09-11 19:28:33 +0000
commit2eeda98682960c32b47af773fc6db343bb6b588f (patch)
tree9eb87c2c202caca64db7a0d2f0d823b365b7038c /usr/src
parent01add34a714b536617e7bb35fa9dd6c1f4430827 (diff)
downloadillumos-gate-2eeda98682960c32b47af773fc6db343bb6b588f.tar.gz
9828 svr4pkg: pkgremove/special.c is unused
Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Yuri Pankov <yuripv@yuripv.net> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/svr4pkg/hdrs/messages.h5
-rw-r--r--usr/src/cmd/svr4pkg/pkginstall/pkginstall.h7
-rw-r--r--usr/src/cmd/svr4pkg/pkgremove/Makefile4
-rw-r--r--usr/src/cmd/svr4pkg/pkgremove/main.c176
-rw-r--r--usr/src/cmd/svr4pkg/pkgremove/special.c711
5 files changed, 90 insertions, 813 deletions
diff --git a/usr/src/cmd/svr4pkg/hdrs/messages.h b/usr/src/cmd/svr4pkg/hdrs/messages.h
index a7f2de9637..d9e7085cc7 100644
--- a/usr/src/cmd/svr4pkg/hdrs/messages.h
+++ b/usr/src/cmd/svr4pkg/hdrs/messages.h
@@ -794,11 +794,6 @@ extern "C" {
#define MSG_VERIFYING gettext("Verifying signer <%s>")
#define MSG_VERIFYING_CLASS gettext("[ verifying class <%s> ]")
-#define SPECIAL_ACCESS gettext("unable to maintain package contents text due to an access failure: %s")
-#define SPECIAL_INPUT gettext("unable to maintain package contents text: alternate root path too long")
-#define SPECIAL_MALLOC gettext("unable to maintain package contents text due to insufficient memory: %s")
-#define SPECIAL_MAP gettext("unable to maintain package contents text due to a failure to map the database into memory: %S")
-
#define WRN_BAD_FORK gettext("WARNING: bad fork(), errno=%d: %s")
#define WRN_BAD_WAIT gettext("WARNING: wait for process %ld failed, pid <%ld> status <0x%08lx> errno <%d> (%s)")
#define WRN_CHKINSTALL gettext("checkinstall script suspends")
diff --git a/usr/src/cmd/svr4pkg/pkginstall/pkginstall.h b/usr/src/cmd/svr4pkg/pkginstall/pkginstall.h
index bae74966ed..55792e6008 100644
--- a/usr/src/cmd/svr4pkg/pkginstall/pkginstall.h
+++ b/usr/src/cmd/svr4pkg/pkginstall/pkginstall.h
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2018 Peter Tribble.
+ */
+
+/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -95,9 +99,6 @@ extern char *getinst __P((int *updatingExisting, struct pkginfo *info,
extern int is_samepkg __P((void));
extern int dockspace __P((char *spacefile));
-extern int special_contents_add(int, struct cfextra **, const char *);
-extern boolean_t rm_all_pkg_entries(char *, char *);
-
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/svr4pkg/pkgremove/Makefile b/usr/src/cmd/svr4pkg/pkgremove/Makefile
index 497532c776..f8819e80f2 100644
--- a/usr/src/cmd/svr4pkg/pkgremove/Makefile
+++ b/usr/src/cmd/svr4pkg/pkgremove/Makefile
@@ -20,6 +20,7 @@
#
#
+# Copyright (c) 2018 Peter Tribble.
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -29,8 +30,7 @@ PROG= pkgremove
OBJS= check.o \
delmap.o \
main.o \
- quit.o \
- special.o
+ quit.o
include $(SRC)/cmd/svr4pkg/Makefile.svr4pkg
diff --git a/usr/src/cmd/svr4pkg/pkgremove/main.c b/usr/src/cmd/svr4pkg/pkgremove/main.c
index cfff491e47..ea7bd03600 100644
--- a/usr/src/cmd/svr4pkg/pkgremove/main.c
+++ b/usr/src/cmd/svr4pkg/pkgremove/main.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright (c) 2017 Peter Tribble.
+ * Copyright (c) 2018 Peter Tribble.
*/
/*
@@ -224,8 +224,8 @@ main(int argc, char *argv[])
* a shared area from a reference client.
*/
case 'A':
- pkgrmremote++;
- break;
+ pkgrmremote++;
+ break;
/*
* Same as pkgrm: Use the installation
@@ -238,8 +238,8 @@ main(int argc, char *argv[])
* administration file.
*/
case 'a':
- admnfile = flex_device(optarg, 0);
- break;
+ admnfile = flex_device(optarg, 0);
+ break;
/*
* Same as pkgrm: location where package executables
@@ -267,8 +267,8 @@ main(int argc, char *argv[])
* upgrade process.
*/
case 'F':
- nodelete++;
- break;
+ nodelete++;
+ break;
/*
* Same as pkgrm: Instruct pkgrm not to use the
@@ -279,16 +279,16 @@ main(int argc, char *argv[])
* releases.
*/
case 'M':
- map_client = 0;
- break;
+ map_client = 0;
+ break;
/*
* Different from pkgrm: specify program name to use
* for messages.
*/
case 'N':
- (void) set_prog_name(optarg);
- break;
+ (void) set_prog_name(optarg);
+ break;
/*
* Same as pkgrm: package removal occurs in
@@ -296,9 +296,9 @@ main(int argc, char *argv[])
* removed files. The default mode is interactive.
*/
case 'n':
- nointeract++;
- (void) echoSetFlag(B_FALSE);
- break;
+ nointeract++;
+ (void) echoSetFlag(B_FALSE);
+ break;
/*
* Almost same as pkgrm: the -O option allows the behavior
@@ -323,7 +323,7 @@ main(int argc, char *argv[])
*/
case 'O':
for (p = strtok(optarg, ","); p != (char *)NULL;
- p = strtok(NULL, ",")) {
+ p = strtok(NULL, ",")) {
/* process debug option */
@@ -343,7 +343,7 @@ main(int argc, char *argv[])
/* process enable-hollow-package-support opt */
if (strcmp(p,
- "enable-hollow-package-support") == 0) {
+ "enable-hollow-package-support") == 0) {
set_depend_pkginfo_DB(B_TRUE);
continue;
}
@@ -369,7 +369,7 @@ main(int argc, char *argv[])
/* process parent-zone-name option */
if (strncmp(p, PARENTZONENAME,
- PARENTZONENAME_LEN) == 0) {
+ PARENTZONENAME_LEN) == 0) {
parentZoneName = p+PARENTZONENAME_LEN;
continue;
}
@@ -377,7 +377,7 @@ main(int argc, char *argv[])
/* process parent-zone-type option */
if (strncmp(p, PARENTZONETYPE,
- PARENTZONETYPE_LEN) == 0) {
+ PARENTZONETYPE_LEN) == 0) {
parentZoneType = p+PARENTZONETYPE_LEN;
continue;
}
@@ -400,8 +400,8 @@ main(int argc, char *argv[])
*/
case 'o':
- script_in = PROC_XSTDIN;
- break;
+ script_in = PROC_XSTDIN;
+ break;
/*
* Same as pkgrm: defines the full path name of a
@@ -411,20 +411,20 @@ main(int argc, char *argv[])
* specified root_path.
*/
case 'R':
- if (!set_inst_root(optarg)) {
- progerr(ERR_ROOT_CMD);
- exit(1);
- }
- break;
+ if (!set_inst_root(optarg)) {
+ progerr(ERR_ROOT_CMD);
+ exit(1);
+ }
+ break;
/*
* Same as pkgrm: allow admin to establish the client
* filesystem using a vfstab-like file of stable format.
*/
case 'V':
- vfstab_file = flex_device(optarg, 2);
- map_client = 1;
- break;
+ vfstab_file = flex_device(optarg, 2);
+ map_client = 1;
+ break;
/*
* Same as pkgrm: trace all of the scripts that
@@ -434,27 +434,27 @@ main(int argc, char *argv[])
* scripts.
*/
case 'v':
- pkgverbose++;
- break;
+ pkgverbose++;
+ break;
/*
* Different from pkgrm: process this package using
* old non-ABI symlinks
*/
case 'y':
- set_nonABI_symlinks();
- break;
+ set_nonABI_symlinks();
+ 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);
+ 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);
}
}
@@ -471,7 +471,7 @@ main(int argc, char *argv[])
echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
} else {
echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
- z_get_zonename());
+ z_get_zonename());
}
/* establish cmdbin path */
@@ -591,13 +591,13 @@ main(int argc, char *argv[])
if (preremoveCheck == B_TRUE) {
(void) echoSetFlag(B_FALSE);
echoDebug(DBG_PKGREMOVE_PRERMCHK, pkginst ? pkginst : "",
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
rcksetPreremoveCheck(B_TRUE);
rcksetZoneName(zoneName);
}
(void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s", get_PKGLOC(),
- pkginst);
+ pkginst);
(void) snprintf(pkgbin, sizeof (pkgbin), "%s/install", pkgloc);
(void) snprintf(rlockfile, sizeof (rlockfile), "%s/!R-Lock!", pkgloc);
@@ -616,7 +616,7 @@ main(int argc, char *argv[])
if (access(rlockfile, F_OK) == 0) {
echo(ERR_UNSUCC);
echoDebug(DBG_PKGINSTALL_HAS_LOCKFILE, pkginst, rlockfile,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
}
/*
@@ -910,7 +910,7 @@ main(int argc, char *argv[])
} else {
echo(MSG_PKGREMOVE_PROCPKG_LZ, zoneName);
echoDebug(DBG_PKGREMOVE_PROCPKG_LZ, pkginst, rlockfile,
- zoneName);
+ zoneName);
}
if (delmap(0, pkginst, &pkgserver, &tmpfp) != 0) {
progerr(ERR_DB_QUERY, pkginst);
@@ -931,15 +931,15 @@ main(int argc, char *argv[])
if (access(script, F_OK) != 0) {
/* no script present */
echoDebug(DBG_PKGREMOVE_POC_NONE, pkginst,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else if (nodelete) {
/* not deleting files: skip preremove script */
echoDebug(DBG_PKGREMOVE_POC_NODEL, pkginst, script,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else if (is_depend_pkginfo_DB()) {
/* updating db only: skip preremove script */
echoDebug(DBG_PKGREMOVE_POC_DBUPD, pkginst, script,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else {
/* script present and ok to run: run the script */
set_ulimit("preremove", ERR_PREREMOVE);
@@ -949,17 +949,17 @@ main(int argc, char *argv[])
} else {
echo(MSG_PKGREMOVE_EXEPOC_LZ, zoneName);
echoDebug(DBG_PKGREMOVE_EXEPOC_LZ, pkginst, script,
- zoneName);
+ zoneName);
}
putparam("PKG_PROC_SCRIPT", "preremove");
if (pkgverbose) {
ckreturn(pkgexecl(script_in, PROC_STDOUT,
- PROC_USER, PROC_GRP, SHELL, "-x",
- script, NULL), ERR_PREREMOVE);
+ PROC_USER, PROC_GRP, SHELL, "-x",
+ script, NULL), ERR_PREREMOVE);
} else {
ckreturn(pkgexecl(script_in, PROC_STDOUT,
- PROC_USER, PROC_GRP, SHELL, script,
- NULL), ERR_PREREMOVE);
+ PROC_USER, PROC_GRP, SHELL, script,
+ NULL), ERR_PREREMOVE);
}
clr_ulimit();
}
@@ -969,14 +969,6 @@ main(int argc, char *argv[])
lockupd("remove");
/*
- * Ensure that the contents file is updated even if the db has
- * been upgraded, in the case that there are relevant entries
- * in a special_contents file. The return value is ignored
- * since we do not want special_contents operation to prevent
- * pkgremove from succeeding. We do report errors to stderr.
- */
-
- /*
* Remove all components belonging to this package.
* Don't remove components if only updating the DB.
* Don't remove components if files are not being deleted.
@@ -984,13 +976,13 @@ main(int argc, char *argv[])
if (nodelete) {
echoDebug(DBG_PKGREMOVE_REM_NODEL, pkginst,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else if (is_depend_pkginfo_DB()) {
echoDebug(DBG_PKGREMOVE_REM_DBUPD, pkginst,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else {
echoDebug(DBG_PKGREMOVE_REM, pkginst,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
/*
* remove package one class at a time
*/
@@ -1019,15 +1011,15 @@ main(int argc, char *argv[])
if (access(script, F_OK) != 0) {
/* no script present */
echoDebug(DBG_PKGREMOVE_PIC_NONE, pkginst,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else if (nodelete) {
/* not deleting files: skip postremove script */
echoDebug(DBG_PKGREMOVE_PIC_NODEL, pkginst, script,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else if (is_depend_pkginfo_DB()) {
/* updating db only: skip postremove script */
echoDebug(DBG_PKGREMOVE_PIC_DBUPD, pkginst, script,
- zoneName ? zoneName : "global");
+ zoneName ? zoneName : "global");
} else {
/* script present and ok to run: run the script */
set_ulimit("postremove", ERR_POSTREMOVE);
@@ -1037,7 +1029,7 @@ main(int argc, char *argv[])
} else {
echo(MSG_PKGREMOVE_EXEPIC_LZ, zoneName);
echoDebug(DBG_PKGREMOVE_EXEPIC_LZ, pkginst, script,
- zoneName);
+ zoneName);
}
putparam("PKG_PROC_SCRIPT", "postremove");
putparam("TMPDIR", tmpdir);
@@ -1071,7 +1063,7 @@ main(int argc, char *argv[])
}
if ((z_running_in_global_zone() == B_TRUE) &&
- (pkgIsPkgInGzOnly(get_inst_root(), pkginst) == B_TRUE)) {
+ (pkgIsPkgInGzOnly(get_inst_root(), pkginst) == B_TRUE)) {
boolean_t b;
b = pkgRemovePackageFromGzonlyList(get_inst_root(), pkginst);
@@ -1135,7 +1127,7 @@ rmclass(char *aclass, int rm_remote, char *a_zoneName)
for (i = 0; i < eptnum; i++) {
if (eptlist[i] != NULL) {
rmclass(eptlist[i]->pkg_class,
- rm_remote, a_zoneName);
+ rm_remote, a_zoneName);
}
}
return;
@@ -1303,45 +1295,45 @@ static void
ckreturn(int retcode, char *msg)
{
switch (retcode) {
- case 2:
- case 12:
- case 22:
+ case 2:
+ case 12:
+ case 22:
warnflag++;
if (msg)
progerr(msg);
/* FALLTHROUGH */
- case 10:
- case 20:
+ case 10:
+ case 20:
if (retcode >= 10)
dreboot++;
if (retcode >= 20)
ireboot++;
/* FALLTHROUGH */
- case 0:
+ case 0:
break; /* okay */
- case -1:
+ case -1:
retcode = 99;
/* FALLTHROUGH */
- case 99:
- case 1:
- case 11:
- case 21:
- case 4:
- case 14:
- case 24:
- case 5:
- case 15:
- case 25:
+ case 99:
+ case 1:
+ case 11:
+ case 21:
+ case 4:
+ case 14:
+ case 24:
+ case 5:
+ case 15:
+ case 25:
if (msg)
progerr(msg);
/* FALLTHROUGH */
- case 3:
- case 13:
- case 23:
+ case 3:
+ case 13:
+ case 23:
quit(retcode);
/* NOT REACHED */
- default:
+ default:
if (msg)
progerr(msg);
quit(1);
diff --git a/usr/src/cmd/svr4pkg/pkgremove/special.c b/usr/src/cmd/svr4pkg/pkgremove/special.c
deleted file mode 100644
index 2412386c44..0000000000
--- a/usr/src/cmd/svr4pkg/pkgremove/special.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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 2017 Gary Mills
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-
-/*
- * special.c
- *
- * This module contains code required to remove special contents from
- * the contents file when a pkgrm is done on a system upgraded to use
- * the new database.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-#include <limits.h>
-#include <fnmatch.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <pkgstrct.h>
-#include "pkglib.h"
-#include <libintl.h>
-
-/* This specifies the maximum length of a contents file line read in. */
-#define LINESZ 8192
-
-#define SPECIAL_MALLOC "unable to maintain package contents text due to "\
- "insufficient memory."
-#define SPECIAL_ACCESS "unable to maintain package contents text due to "\
- "an access failure."
-#define SPECIAL_INPUT "unable to maintain package contents text: alternate "\
- "root path too long"
-
-/*
- * strcompare
- *
- * This function is used by qsort to sort an array of special contents
- * rule strings. This array must be sorted to facilitate efficient
- * rule processing. See qsort(3c) regarding qsort compare functions.
- */
-static int
-strcompare(const void *pv1, const void *pv2)
-{
- char **ppc1 = (char **) pv1;
- char **ppc2 = (char **) pv2;
- int i = strcmp(*ppc1, *ppc2);
- if (i < 0)
- return (-1);
- if (i > 0)
- return (1);
- return (0);
-}
-
-/*
- * match
- *
- * This function determines whether a file name (pc) matches a rule
- * from the special contents file (pcrule). We assume that neither
- * string is ever NULL.
- *
- * Return: 1 on match, 0 on no match.
- * Side effects: none.
- */
-static int
-match(const char *pc, char *pcrule)
-{
- int n = strlen(pcrule);
- int wild = 0;
- if (pcrule[n - 1] == '*') {
- wild = 1;
- pcrule[n - 1] = '\0';
- }
-
- if (!wild) {
- if (fnmatch(pc, pcrule, FNM_PATHNAME) == 0 ||
- fnmatch(pc, pcrule, 0) == 0)
- return (1);
- } else {
- int j;
- j = strncmp(pc, pcrule, n - 1);
- pcrule[n - 1] = '*';
- if (j == 0)
- return (1);
- }
- return (0);
-}
-
-/*
- * search_special_contents
- *
- * This function assumes that a series of calls will be made requesting
- * whether a given path matches the special contents rules or not. We
- * assume that
- *
- * a) the special_contents array is sorted
- * b) the calls will be made with paths in a sorted order
- *
- * Given that, we can keep track of where the last search ended and
- * begin the new search at that point. This reduces the cost of a
- * special contents matching search to O(n) from O(n^2).
- *
- * ppcSC A pointer to an array of special contents obtained via
- * get_special_contents().
- * path A path: determine whether it matches the special
- * contents rules or not.
- * piX The position in the special_contents array we have already
- * arrived at through searching. This must be initialized to
- * zero before initiating a series of search_special_contents
- * operations.
- *
- * Example:
- * {
- * int i = 0, j, max;
- * char **ppSC = NULL;
- * if (get_special_contents(NULL, &ppcSC, &max) != 0) exit(1);
- * for (j = 0; paths != NULL && paths[j] != NULL; j++) {
- * if (search_special_contents(ppcSC, path[j], &i)) {
- * do_something_with_special_path(path[j]);
- * }
- * }
- * }
- *
- * Return: 1 if there is a match, 0 otherwise.
- * Side effects: The value of *piX will be set between calls to this
- * function. To make this function thread safe, use search arrays.
- * Also: Nonmatching entries are eliminated, set to NULL.
- */
-static int
-search_special_contents(char **ppcSC, const char *pcpath, int *piX, int max)
-{
- int wild;
- if (ppcSC == NULL || *piX == max)
- return (0);
-
- while (*piX < max) {
-
- int j, k;
- if (ppcSC[*piX] == NULL) {
- (*piX)++;
- continue;
- }
-
- j = strlen(ppcSC[*piX]);
- k = strcmp(pcpath, ppcSC[*piX]);
- wild = (ppcSC[*piX][j - 1] == '*');
-
- /*
- * Depending on whether the path string compared with the
- * rule, we take different actions. If the path is less
- * than the rule, we keep the rule. If the path equals
- * the rule, we advance the rule (as long as the rule is
- * not a wild card). If the path is greater than the rule,
- * we have to advance the rule list until we are less or equal
- * again. This way we only have to make one pass through the
- * rules, as we make one pass through the path strings. We
- * assume that the rules and the path strings are sorted.
- */
- if (k < 0) {
-
- if (wild == 0)
- return (0);
-
- if (match(pcpath, ppcSC[*piX]))
- return (1);
- break;
-
- } else if (k == 0) {
-
- int x = match(pcpath, ppcSC[*piX]);
- if (wild == 0) (*piX)++;
- return (x);
-
- } else {
- /* One last try. */
- if (match(pcpath, ppcSC[*piX]))
- return (1);
-
- /*
- * As pcpath > ppcSC[*piX] we have passed up this
- * rule - it cannot apply. Therefore, we do not
- * need to retain it. Removing the rule will make
- * subsequent searching more efficient.
- */
- free(ppcSC[*piX]);
- ppcSC[*piX] = NULL;
-
- (*piX)++;
- }
- }
- return (0);
-}
-
-/*
- * get_special_contents
- *
- * Retrieves the special contents file entries, if they exist. These
- * are sorted. We do not assume the special_contents file is in sorted
- * order.
- *
- * pcroot The root of the install database. If NULL assume '/'.
- * pppcSC A pointer to a char **. This pointer will be set to
- * point at NULL if there is no special_contents file or
- * to a sorted array of strings, NULL terminated, otherwise.
- * piMax The # of entries in the special contents result.
- *
- * Returns: 0 on no error, nonzero on error.
- * Side effects: the pppcSC pointer is set to point at a newly
- * allocated array of pointers to strings.. The caller must
- * free this buffer. The value of *piMax is set to the # of
- * entries in ppcSC.
- */
-static int
-get_special_contents(const char *pcroot, char ***pppcSC, int *piMax)
-{
- int e, i;
- FILE *fp;
- char line[2048];
- char **ppc;
- char *pc = "var/sadm/install/special_contents";
- char path[PATH_MAX];
- struct stat s;
-
- /* Initialize the return values. */
- *piMax = 0;
- *pppcSC = NULL;
-
- if (pcroot == NULL) {
- pcroot = "/";
- }
-
- if (pcroot[strlen(pcroot) - 1] == '/') {
- if (snprintf(path, PATH_MAX, "%s%s", pcroot, pc) >= PATH_MAX) {
- progerr(gettext(SPECIAL_INPUT));
- return (1);
- }
- } else {
- if (snprintf(path, PATH_MAX, "%s/%s", pcroot, pc)
- >= PATH_MAX) {
- progerr(gettext(SPECIAL_INPUT));
- return (1);
- }
- }
-
- errno = 0;
- e = stat(path, &s);
- if (e != 0 && errno == ENOENT)
- return (0); /* No special contents file. Do nothing. */
-
- if (access(path, R_OK) != 0 || (fp = fopen(path, "r")) == NULL) {
- /* Could not open special contents which exists */
- progerr(gettext(SPECIAL_ACCESS));
- return (1);
- }
-
- for (i = 0; fgets(line, 2048, fp) != NULL; i++);
- rewind(fp);
- if ((ppc = (char **) calloc(i + 1, sizeof (char *))) == NULL) {
- progerr(gettext(SPECIAL_MALLOC));
- return (1);
- }
-
- for (i = 0; fgets(line, 2048, fp) != NULL; ) {
- int n;
- if (line[0] == '#' || line[0] == ' ' || line[0] == '\n' ||
- line[0] == '\t' || line[0] == '\r')
- continue;
- n = strlen(line);
- if (line[n - 1] == '\n')
- line[n - 1] = '\0';
- ppc[i++] = strdup(line);
- }
-
- qsort(ppc, i, sizeof (char *), strcompare);
-
- *pppcSC = ppc;
- *piMax = i;
- return (0);
-}
-
-/*
- * free_special_contents
- *
- * This function frees special_contents which have been allocated using
- * get_special_contents.
- *
- * pppcSC A pointer to a buffer allocated using get_special_contents.
- * max The number of entries allocated.
- *
- * Result: None.
- * Side effects: Frees memory allocated using get_special_contents and
- * sets the pointer passed in to NULL.
- */
-static void
-free_special_contents(char ***pppcSC, int max)
-{
- int i;
- char **ppc = NULL;
- if (*pppcSC == NULL)
- return;
-
- ppc = *pppcSC;
- for (i = 0; ppc != NULL && i < max; i++)
- if (ppc[i] == NULL)
- free(ppc[i]);
-
- if (ppc != NULL)
- free(ppc);
-
- *pppcSC = NULL;
-}
-
-/*
- * get_path
- *
- * Return the first field of a string delimited by a space.
- *
- * pcline A line from the contents file.
- *
- * Return: NULL if an error. Otherwise a string allocated by this
- * function. The caller must free the string.
- * Side effects: none.
- */
-static char *
-get_path(const char *pcline)
-{
- int i = strcspn(pcline, " ");
- char *pc = NULL;
- if (i <= 1 || (pc = (char *) calloc(i + 1, 1)) == NULL)
- return (NULL);
- (void) memcpy(pc, pcline, i);
- return (pc);
-}
-
-/*
- * generate_special_contents_rules
- *
- * This procedure will generate an array of integers which will be a mask
- * to apply to the ppcfextra array. If set to 1, then the content must be
- * added to the contents file. Otherwise it will not be: The old contents
- * file will be used for this path value, if one even exists.
- *
- * ient The number of ppcfextra contents installed.
- * ppcfent The contents installed.
- * ppcSC The rules (special contents)
- * max The number of special contents rules.
- * ppiIndex The array of integer values, determining whether
- * individual ppcfextra items match special contents rules.
- * This array will be created and set in this function and
- * returned.
- *
- * Return: 0 success, nonzero failure
- * Side effects: allocates an array of integers that the caller must free.
- */
-static int
-generate_special_contents_rules(int ient, struct cfent **ppcfent,
- char **ppcSC, int max, int **ppiIndex)
-{
- int i, j;
- int *pi = (int *) calloc(ient, sizeof (int));
- if (pi == NULL) {
- progerr(gettext(SPECIAL_MALLOC));
- return (1);
- }
-
- /*
- * For each entry in ppcfextra, check if it matches a rule.
- * If it does not, set the entry in the index to -1.
- */
- for (i = 0, j = 0; i < ient && j < max; i++) {
- if (search_special_contents(ppcSC, ppcfent[i]->path,
- &j, max) == 1) {
- pi[i] = 1;
-
- } else {
- pi[i] = 0;
- }
- }
-
- /*
- * In case we ran out of rules before contents, we will not use
- * those contents. Make sure these contents are set to 0 and
- * will not be copied from the ppcfent array into the contents
- * file.
- */
- for (i = i; i < ient; i++)
- pi[i] = 0;
-
- *ppiIndex = pi;
- return (0);
-}
-
-
-/*
- * pathcmp
- *
- * Compare a path to a cfent. It will match either if the path is
- * equal to the cfent path, or if the cfent is a symbolic or link
- * and *that* matches.
- *
- * path a path
- * pent a contents entry
- *
- * Returns: as per strcmp
- * Side effects: none.
- */
-static int
-pathcmp(const char *pc, const struct cfent *pent)
-{
- int i;
- if ((pent->ftype == 's' || pent->ftype == 'l') &&
- pent->ainfo.local) {
- char *p, *q;
- if ((p = strstr(pc, "=")) == NULL) {
-
- i = strcmp(pc, pent->path);
-
- /* A path without additional chars strcmp's to less */
- if (i == 0)
- i = -1;
-
- } else {
- /* Break the link path into two pieces. */
- *p = '\0';
-
- /* Compare the first piece. */
- i = strcmp(pc, pent->path);
-
- /* If equal we must compare the second piece. */
- if (i == 0) {
- q = p + 1;
- i = strcmp(q, pent->ainfo.local);
- }
-
- /* Restore the link path. */
- *p = '=';
- }
- } else {
- i = strcmp(pc, pent->path);
- }
-
- return (i);
-}
-
-/*
- * -----------------------------------------------------------------------
- * Externally visible function.
- */
-
-/*
- * special_contents_remove
- *
- * Given a set of entries to remove and an alternate root, this function
- * will do everything required to ensure that the entries are removed
- * from the contents file if they are listed in the special_contents
- * file. The contents file will get changed only in the case that the
- * entire operation has succeeded.
- *
- * ient The number of entries.
- * ppcfent The entries to remove.
- * pcroot The alternate install root. Could be NULL. In this
- * case, assume root is '/'
- *
- * Result: 0 on success, nonzero on failure. If an error occurs, an
- * error string will get output to standard error alerting the user.
- * Side effects: The contents file may change as a result of this call,
- * such that lines in the in the file will be changed or removed.
- * If the call fails, a t.contents file may be left behind. This
- * temporary file should be removed subsequently.
- */
-int
-special_contents_remove(int ient, struct cfent **ppcfent, const char *pcroot)
-{
- int result = 0; /* Assume we will succeed. Return result. */
- char **ppcSC = NULL; /* The special contents rules, sorted. */
- int i; /* Index into contents & special contents */
- FILE *fpi = NULL, /* Input of contents file */
- *fpo = NULL; /* Output to temp contents file */
- char cpath[PATH_MAX], /* Contents file path */
- tcpath[PATH_MAX]; /* Temp contents file path */
- const char *pccontents = "var/sadm/install/contents";
- const char *pctcontents = "var/sadm/install/t.contents";
- char line[LINESZ]; /* Reads in and writes out contents lines. */
- time_t t; /* Used to create a timestamp comment. */
- int max; /* Max number of special contents entries. */
- int *piIndex; /* An index to ppcfents to remove from cfile */
-
- cpath[0] = tcpath[0] = '\0';
-
- if (ient == 0 || ppcfent == NULL || ppcfent[0] == NULL) {
- goto remove_done;
- }
-
- if ((get_special_contents(pcroot, &ppcSC, &max)) != 0) {
- result = 1;
- goto remove_done;
- }
-
- /* Check if there are no special contents actions to take. */
- if (ppcSC == NULL) {
- goto remove_done;
- }
-
- if (pcroot == NULL) pcroot = "/";
- if (pcroot[strlen(pcroot) - 1] == '/') {
- if (snprintf(cpath, PATH_MAX, "%s%s", pcroot, pccontents)
- >= PATH_MAX ||
- snprintf(tcpath, PATH_MAX, "%s%s", pcroot, pctcontents)
- >= PATH_MAX) {
- progerr(gettext(SPECIAL_INPUT));
- result = -1;
- goto remove_done;
- }
- } else {
- if (snprintf(cpath, PATH_MAX, "%s/%s", pcroot, pccontents)
- >= PATH_MAX ||
- snprintf(tcpath, PATH_MAX, "%s/%s", pcroot, pctcontents)
- >= PATH_MAX) {
- progerr(gettext(SPECIAL_INPUT));
- result = -1;
- goto remove_done;
- }
- }
-
- /* Open the temporary contents file to write, contents to read. */
- if (access(cpath, F_OK | R_OK) != 0) {
- /*
- * This is not a problem since no contents means nothing
- * to remove due to special contents rules.
- */
- result = 0;
- cpath[0] = '\0'; /* This signals omission of 'rename cleanup' */
- goto remove_done;
- }
-
- if (access(cpath, W_OK) != 0) {
- /* can't write contents file, something is wrong. */
- progerr(gettext(SPECIAL_ACCESS));
- result = 1;
- goto remove_done;
-
- }
-
- if ((fpi = fopen(cpath, "r")) == NULL) {
- /* Given the access test above, this should not happen. */
- progerr(gettext(SPECIAL_ACCESS));
- result = 1;
- goto remove_done;
- }
-
- if ((fpo = fopen(tcpath, "w")) == NULL) {
- /* open t.contents failed */
- progerr(gettext(SPECIAL_ACCESS));
- result = 1;
- goto remove_done;
- }
-
- if (generate_special_contents_rules(ient, ppcfent, ppcSC, max, &piIndex)
- != 0) {
- result = 1;
- goto remove_done;
- }
-
- /*
- * Copy contents to t.contents unless there is an entry in
- * the ppcfent array which corresponds to an index set to 1.
- *
- * These items are the removed package contents which matche an
- * entry in ppcSC (the special_contents rules).
- *
- * Since both the contents and rules are sorted, we can
- * make a single efficient pass.
- */
- (void) memset(line, 0, LINESZ);
-
- for (i = 0; fgets(line, LINESZ, fpi) != NULL; ) {
-
- char *pcpath = NULL;
-
- /*
- * Note: This could be done better: We should figure out
- * which are the last 2 lines and only trim those off.
- * This will suffice to do this and will only be done as
- * part of special_contents handling.
- */
- if (line[0] == '#')
- continue; /* Do not copy the final 2 comment lines */
-
- pcpath = get_path(line);
-
- if (pcpath != NULL && i < ient) {
- int k;
- while (piIndex[i] == 0)
- i++;
-
- if (i < ient)
- k = pathcmp(pcpath, ppcfent[i]);
-
- if (k < 0 || i >= ient) {
- /* Just copy contents -> t.contents */
- /*EMPTY*/
- } else if (k == 0) {
- /* We have a match. Do not copy the content. */
- i++;
- free(pcpath);
- (void) memset(line, 0, LINESZ);
- continue;
- } else while (i < ient) {
-
- /*
- * This is a complex case: The content
- * entry is further along alphabetically
- * than the rule. Skip over all rules which
- * apply until we come to a rule which is
- * greater than the current entry, or equal
- * to it. If equal, do not copy, otherwise
- * do copy the entry.
- */
- if (piIndex[i] == 0) {
- i++;
- continue;
- } else if ((k = pathcmp(pcpath, ppcfent[i]))
- >= 0) {
- i++;
- if (k == 0) {
- free(pcpath);
- (void) memset(line, 0, LINESZ);
- break;
- }
- } else {
- /* path < rule, end special case */
- break;
- }
- }
-
- /*
- * Avoid copying the old content when path == rule
- * This occurs when the complex case ends on a match.
- */
- if (k == 0)
- continue;
- }
-
- if (fprintf(fpo, "%s", line) < 0) {
- /* Failing to write output would be catastrophic. */
- progerr(gettext(SPECIAL_ACCESS));
- result = 1;
- break;
- }
- (void) memset(line, 0, LINESZ);
- }
-
- t = time(NULL);
- (void) fprintf(fpo, "# Last modified by pkgremove\n");
- (void) fprintf(fpo, "# %s", ctime(&t));
-
-remove_done:
- free_special_contents(&ppcSC, max);
-
- if (fpi != NULL)
- (void) fclose(fpi);
-
- if (fpo != NULL)
- (void) fclose(fpo);
-
- if (result == 0) {
- if (tcpath[0] != '\0' && cpath[0] != '\0' &&
- rename(tcpath, cpath) != 0) {
- progerr(gettext(SPECIAL_ACCESS));
- result = 1;
- }
- } else {
- if (tcpath[0] != '\0' && remove(tcpath) != 0) {
- /*
- * Do not output a diagnostic message. This condition
- * occurs only when we are unable to clean up after
- * a failure. A temporary file will linger.
- */
- result = 1;
- }
- }
-
- return (result);
-}