diff options
author | Peter Tribble <peter.tribble@gmail.com> | 2018-09-09 20:20:46 +0100 |
---|---|---|
committer | Richard Lowe <richlowe@richlowe.net> | 2018-09-11 19:28:33 +0000 |
commit | 2eeda98682960c32b47af773fc6db343bb6b588f (patch) | |
tree | 9eb87c2c202caca64db7a0d2f0d823b365b7038c /usr/src | |
parent | 01add34a714b536617e7bb35fa9dd6c1f4430827 (diff) | |
download | illumos-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.h | 5 | ||||
-rw-r--r-- | usr/src/cmd/svr4pkg/pkginstall/pkginstall.h | 7 | ||||
-rw-r--r-- | usr/src/cmd/svr4pkg/pkgremove/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/svr4pkg/pkgremove/main.c | 176 | ||||
-rw-r--r-- | usr/src/cmd/svr4pkg/pkgremove/special.c | 711 |
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); -} |