17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate *
267c478bd9Sstevel@tonic-gate * Device policy specific subroutines. We cannot merge them with
277c478bd9Sstevel@tonic-gate * drvsubr.c because of static linking requirements.
287c478bd9Sstevel@tonic-gate */
297c478bd9Sstevel@tonic-gate
30*e4a991ebSAndy Fiddaman /*
31*e4a991ebSAndy Fiddaman * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
32*e4a991ebSAndy Fiddaman */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #include <stdio.h>
357c478bd9Sstevel@tonic-gate #include <stdlib.h>
367c478bd9Sstevel@tonic-gate #include <unistd.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate #include <priv.h>
407c478bd9Sstevel@tonic-gate #include <string.h>
417c478bd9Sstevel@tonic-gate #include <libgen.h>
427c478bd9Sstevel@tonic-gate #include <libintl.h>
437c478bd9Sstevel@tonic-gate #include <errno.h>
447c478bd9Sstevel@tonic-gate #include <alloca.h>
457c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
467c478bd9Sstevel@tonic-gate #include <sys/devpolicy.h>
477c478bd9Sstevel@tonic-gate #include <sys/stat.h>
487c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate #include "addrem.h"
517c478bd9Sstevel@tonic-gate #include "errmsg.h"
527c478bd9Sstevel@tonic-gate #include "plcysubr.h"
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate size_t devplcysys_sz;
557c478bd9Sstevel@tonic-gate const priv_impl_info_t *privimplinfo;
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate * New token types should be parsed in parse_plcy_entry.
597c478bd9Sstevel@tonic-gate */
607c478bd9Sstevel@tonic-gate #define PSET 0
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate typedef struct token {
637c478bd9Sstevel@tonic-gate const char *token;
647c478bd9Sstevel@tonic-gate int type;
657c478bd9Sstevel@tonic-gate ptrdiff_t off;
667c478bd9Sstevel@tonic-gate } token_t;
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate static token_t toktab[] = {
697c478bd9Sstevel@tonic-gate { DEVPLCY_TKN_RDP, PSET /* offsetof(devplcysys_t, dps_rdp) */ },
707c478bd9Sstevel@tonic-gate { DEVPLCY_TKN_WRP, PSET /* offsetof(devplcysys_t, dps_wrp) */ },
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate #define RDPOL 0
747c478bd9Sstevel@tonic-gate #define WRPOL 1
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate #define NTOK (sizeof (toktab)/sizeof (token_t))
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate * Compute the size of the datastructures needed.
807c478bd9Sstevel@tonic-gate */
817c478bd9Sstevel@tonic-gate void
devplcy_init(void)827c478bd9Sstevel@tonic-gate devplcy_init(void)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate if ((privimplinfo = getprivimplinfo()) == NULL) {
857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_PRIVIMPL));
867c478bd9Sstevel@tonic-gate exit(1);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate devplcysys_sz = DEVPLCYSYS_SZ(privimplinfo);
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate toktab[RDPOL].off =
92*e4a991ebSAndy Fiddaman (char *)DEVPLCYSYS_RDP((devplcysys_t *)0, privimplinfo) - (char *)0;
937c478bd9Sstevel@tonic-gate toktab[WRPOL].off =
94*e4a991ebSAndy Fiddaman (char *)DEVPLCYSYS_WRP((devplcysys_t *)0, privimplinfo) - (char *)0;
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * Read a configuration file line and return a static buffer pointing to it.
997c478bd9Sstevel@tonic-gate * It returns a static struct fileentry which has several fields:
1007c478bd9Sstevel@tonic-gate * - rawbuf, which includes the lines including empty lines and comments
101*e4a991ebSAndy Fiddaman * leading up to the file and the entry as found in the file
1027c478bd9Sstevel@tonic-gate * - orgentry, pointer in rawbuf to the start of the entry proper.
1037c478bd9Sstevel@tonic-gate * - entry, a pre-parsed entry, escaped newlines removed.
1047c478bd9Sstevel@tonic-gate * - startline, the line number of the first line in the file
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate fileentry_t *
fgetline(FILE * fp)1077c478bd9Sstevel@tonic-gate fgetline(FILE *fp)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate static size_t sz = BUFSIZ;
1107c478bd9Sstevel@tonic-gate static struct fileentry fe;
1117c478bd9Sstevel@tonic-gate static int linecnt = 1;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate char *buf = fe.rawbuf;
1147c478bd9Sstevel@tonic-gate ptrdiff_t off;
1157c478bd9Sstevel@tonic-gate char *p;
1167c478bd9Sstevel@tonic-gate int c, lastc, i;
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate if (buf == NULL) {
1197c478bd9Sstevel@tonic-gate fe.rawbuf = buf = malloc(sz);
1207c478bd9Sstevel@tonic-gate if (buf == NULL)
1217c478bd9Sstevel@tonic-gate return (NULL);
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate if (fe.entry != NULL) {
1247c478bd9Sstevel@tonic-gate free(fe.entry);
1257c478bd9Sstevel@tonic-gate fe.orgentry = fe.entry = NULL;
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate i = 0;
1297c478bd9Sstevel@tonic-gate off = -1;
1307c478bd9Sstevel@tonic-gate c = '\n';
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate while (lastc = c, (c = getc(fp)) != EOF) {
1337c478bd9Sstevel@tonic-gate buf[i++] = c;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate if (i == sz) {
1367c478bd9Sstevel@tonic-gate sz *= 2;
1377c478bd9Sstevel@tonic-gate fe.rawbuf = buf = realloc(buf, sz);
1387c478bd9Sstevel@tonic-gate if (buf == NULL)
1397c478bd9Sstevel@tonic-gate return (NULL);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate if (c == '\n') {
1437c478bd9Sstevel@tonic-gate linecnt++;
1447c478bd9Sstevel@tonic-gate /* Newline, escaped or not yet processing an entry */
1457c478bd9Sstevel@tonic-gate if (off == -1 || lastc == '\\')
1467c478bd9Sstevel@tonic-gate continue;
1477c478bd9Sstevel@tonic-gate } else if (lastc == '\n' && off == -1) {
1487c478bd9Sstevel@tonic-gate /* Start of more comments */
1497c478bd9Sstevel@tonic-gate if (c == '#')
1507c478bd9Sstevel@tonic-gate continue;
1517c478bd9Sstevel@tonic-gate /* Found start of entry */
1527c478bd9Sstevel@tonic-gate off = i - 1;
1537c478bd9Sstevel@tonic-gate fe.startline = linecnt;
1547c478bd9Sstevel@tonic-gate continue;
1557c478bd9Sstevel@tonic-gate } else
1567c478bd9Sstevel@tonic-gate continue;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate buf[i] = '\0';
1597c478bd9Sstevel@tonic-gate fe.orgentry = buf + off;
1607c478bd9Sstevel@tonic-gate p = fe.entry = strdup(fe.orgentry);
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate if (p == NULL)
1637c478bd9Sstevel@tonic-gate return (NULL);
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate /* Remove <backslash><newline> */
1667c478bd9Sstevel@tonic-gate if ((p = strchr(p, '\\')) != NULL) {
1677c478bd9Sstevel@tonic-gate for (off = 0; (p[-off] = p[0]) != '\0'; p++)
1687c478bd9Sstevel@tonic-gate if (p[0] == '\\' && p[1] == '\n') {
1697c478bd9Sstevel@tonic-gate off += 2;
1707c478bd9Sstevel@tonic-gate p++;
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate return (&fe);
1747c478bd9Sstevel@tonic-gate }
1757c478bd9Sstevel@tonic-gate if (lastc != '\n' || off != -1)
1767c478bd9Sstevel@tonic-gate return (NULL);
1777c478bd9Sstevel@tonic-gate buf[i] = '\0';
1787c478bd9Sstevel@tonic-gate linecnt = 1;
1797c478bd9Sstevel@tonic-gate return (&fe);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate * Parse minor number ranges:
1847c478bd9Sstevel@tonic-gate * (minor) or (lowminor-highminor)
1857c478bd9Sstevel@tonic-gate * Return 0 for success, -1 for failure.
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate int
parse_minor_range(const char * range,minor_t * lo,minor_t * hi,char * type)1887c478bd9Sstevel@tonic-gate parse_minor_range(const char *range, minor_t *lo, minor_t *hi, char *type)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate unsigned long tmp;
1917c478bd9Sstevel@tonic-gate char *p;
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate if (*range++ != '(')
1947c478bd9Sstevel@tonic-gate return (-1);
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate errno = 0;
1977c478bd9Sstevel@tonic-gate tmp = strtoul(range, &p, 0);
1987c478bd9Sstevel@tonic-gate if (tmp > L_MAXMIN32 || (tmp == 0 && errno != 0) ||
1997c478bd9Sstevel@tonic-gate (*p != '-' && *p != ')'))
2007c478bd9Sstevel@tonic-gate return (-1);
2017c478bd9Sstevel@tonic-gate *lo = tmp;
2027c478bd9Sstevel@tonic-gate if (*p == '-') {
2037c478bd9Sstevel@tonic-gate errno = 0;
2047c478bd9Sstevel@tonic-gate tmp = strtoul(p + 1, &p, 0);
2057c478bd9Sstevel@tonic-gate if (tmp > L_MAXMIN32 || (tmp == 0 && errno != 0) || *p != ')')
2067c478bd9Sstevel@tonic-gate return (-1);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate *hi = tmp;
2097c478bd9Sstevel@tonic-gate if (*lo > *hi)
2107c478bd9Sstevel@tonic-gate return (-1);
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate switch (p[1]) {
2137c478bd9Sstevel@tonic-gate case '\0':
2147c478bd9Sstevel@tonic-gate *type = '\0';
2157c478bd9Sstevel@tonic-gate break;
2167c478bd9Sstevel@tonic-gate case 'c':
2177c478bd9Sstevel@tonic-gate case 'C':
2187c478bd9Sstevel@tonic-gate *type = 'c';
2197c478bd9Sstevel@tonic-gate break;
2207c478bd9Sstevel@tonic-gate case 'b':
2217c478bd9Sstevel@tonic-gate case 'B':
2227c478bd9Sstevel@tonic-gate *type = 'b';
2237c478bd9Sstevel@tonic-gate break;
2247c478bd9Sstevel@tonic-gate default:
2257c478bd9Sstevel@tonic-gate return (-1);
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate return (0);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate static void
put_minor_range(FILE * fp,fileentry_t * old,const char * devn,const char * tail,minor_t lo,minor_t hi,char type)2317c478bd9Sstevel@tonic-gate put_minor_range(FILE *fp, fileentry_t *old, const char *devn, const char *tail,
2327c478bd9Sstevel@tonic-gate minor_t lo, minor_t hi, char type)
2337c478bd9Sstevel@tonic-gate {
2347c478bd9Sstevel@tonic-gate /* Preserve preceeding comments */
2357c478bd9Sstevel@tonic-gate if (old != NULL && old->rawbuf != old->orgentry)
2367c478bd9Sstevel@tonic-gate (void) fwrite(old->rawbuf, 1, old->orgentry - old->rawbuf, fp);
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate if (type == '\0') {
2397c478bd9Sstevel@tonic-gate put_minor_range(fp, NULL, devn, tail, lo, hi, 'b');
2407c478bd9Sstevel@tonic-gate put_minor_range(fp, NULL, devn, tail, lo, hi, 'c');
2417c478bd9Sstevel@tonic-gate } else if (lo == hi) {
2427c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:(%d)%c%s", devn, (int)lo, type, tail);
2437c478bd9Sstevel@tonic-gate } else {
2447c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%s:(%d-%d)%c%s", devn, (int)lo, (int)hi,
2457c478bd9Sstevel@tonic-gate type, tail);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate static int
delete_one_entry(const char * filename,const char * entry)2507c478bd9Sstevel@tonic-gate delete_one_entry(const char *filename, const char *entry)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate char tfile[MAXPATHLEN];
2537c478bd9Sstevel@tonic-gate char ofile[MAXPATHLEN];
2547c478bd9Sstevel@tonic-gate char *nfile;
2557c478bd9Sstevel@tonic-gate FILE *old, *new;
2567c478bd9Sstevel@tonic-gate fileentry_t *fep;
2577c478bd9Sstevel@tonic-gate struct stat buf;
2587c478bd9Sstevel@tonic-gate int newfd;
2597c478bd9Sstevel@tonic-gate char *mpart;
2607c478bd9Sstevel@tonic-gate boolean_t delall;
2617c478bd9Sstevel@tonic-gate boolean_t delrange;
2627c478bd9Sstevel@tonic-gate minor_t rlo, rhi;
2637c478bd9Sstevel@tonic-gate char rtype;
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate mpart = strchr(entry, ':');
2667c478bd9Sstevel@tonic-gate if (mpart == NULL) {
2677c478bd9Sstevel@tonic-gate delall = B_TRUE;
2687c478bd9Sstevel@tonic-gate delrange = B_FALSE;
2697c478bd9Sstevel@tonic-gate } else {
2707c478bd9Sstevel@tonic-gate delall = B_FALSE;
2717c478bd9Sstevel@tonic-gate mpart++;
2727c478bd9Sstevel@tonic-gate if (*mpart == '(') {
2737c478bd9Sstevel@tonic-gate if (parse_minor_range(mpart, &rlo, &rhi, &rtype) != 0)
2747c478bd9Sstevel@tonic-gate return (-1);
2757c478bd9Sstevel@tonic-gate delrange = B_TRUE;
2767c478bd9Sstevel@tonic-gate } else {
2777c478bd9Sstevel@tonic-gate delrange = B_FALSE;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate if (strlen(filename) + sizeof (XEND) > sizeof (tfile))
2827c478bd9Sstevel@tonic-gate return (-1);
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate old = fopen(filename, "r");
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate if (old == NULL)
2877c478bd9Sstevel@tonic-gate return (-1);
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate (void) snprintf(tfile, sizeof (tfile), "%s%s", filename, XEND);
2907c478bd9Sstevel@tonic-gate (void) snprintf(ofile, sizeof (ofile), "%s%s", filename, ".old");
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate nfile = mktemp(tfile);
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate new = fopen(nfile, "w");
2957c478bd9Sstevel@tonic-gate if (new == NULL) {
2967c478bd9Sstevel@tonic-gate (void) fclose(old);
2977c478bd9Sstevel@tonic-gate return (ERROR);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate newfd = fileno(new);
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /* Copy permissions, ownership */
3037c478bd9Sstevel@tonic-gate if (fstat(fileno(old), &buf) == 0) {
3047c478bd9Sstevel@tonic-gate (void) fchown(newfd, buf.st_uid, buf.st_gid);
3057c478bd9Sstevel@tonic-gate (void) fchmod(newfd, buf.st_mode);
3067c478bd9Sstevel@tonic-gate } else {
3077c478bd9Sstevel@tonic-gate (void) fchown(newfd, 0, 3); /* root:sys */
3087c478bd9Sstevel@tonic-gate (void) fchmod(newfd, 0644);
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate while ((fep = fgetline(old))) {
3127c478bd9Sstevel@tonic-gate char *tok;
3137c478bd9Sstevel@tonic-gate char *min;
3147c478bd9Sstevel@tonic-gate char *tail;
3157c478bd9Sstevel@tonic-gate char tc;
3167c478bd9Sstevel@tonic-gate int len;
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate /* Trailing comments */
3197c478bd9Sstevel@tonic-gate if (fep->entry == NULL) {
3207c478bd9Sstevel@tonic-gate (void) fputs(fep->rawbuf, new);
3217c478bd9Sstevel@tonic-gate break;
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate tok = fep->entry;
3257c478bd9Sstevel@tonic-gate while (*tok && isspace(*tok))
3267c478bd9Sstevel@tonic-gate tok++;
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate if (*tok == '\0') {
3297c478bd9Sstevel@tonic-gate (void) fputs(fep->rawbuf, new);
3307c478bd9Sstevel@tonic-gate break;
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /* Make sure we can recover the remainder incl. whitespace */
3347c478bd9Sstevel@tonic-gate tail = strpbrk(tok, "\t\n ");
3357c478bd9Sstevel@tonic-gate if (tail == NULL)
3367c478bd9Sstevel@tonic-gate tail = tok + strlen(tok);
3377c478bd9Sstevel@tonic-gate tc = *tail;
3387c478bd9Sstevel@tonic-gate *tail = '\0';
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate if (delall || delrange) {
3417c478bd9Sstevel@tonic-gate min = strchr(tok, ':');
3427c478bd9Sstevel@tonic-gate if (min)
3437c478bd9Sstevel@tonic-gate *min++ = '\0';
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate len = strlen(tok);
3477c478bd9Sstevel@tonic-gate if (delrange) {
3487c478bd9Sstevel@tonic-gate minor_t lo, hi;
3497c478bd9Sstevel@tonic-gate char type;
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate /*
3527c478bd9Sstevel@tonic-gate * Delete or shrink overlapping ranges.
3537c478bd9Sstevel@tonic-gate */
3547c478bd9Sstevel@tonic-gate if (strncmp(entry, tok, len) == 0 &&
3557c478bd9Sstevel@tonic-gate entry[len] == ':' &&
3567c478bd9Sstevel@tonic-gate min != NULL &&
3577c478bd9Sstevel@tonic-gate parse_minor_range(min, &lo, &hi, &type) == 0 &&
3587c478bd9Sstevel@tonic-gate (type == rtype || rtype == '\0') &&
3597c478bd9Sstevel@tonic-gate lo <= rhi && hi >= rlo) {
3607c478bd9Sstevel@tonic-gate minor_t newlo, newhi;
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate /* Complete overlap, then drop it. */
3637c478bd9Sstevel@tonic-gate if (lo >= rlo && hi <= rhi)
3647c478bd9Sstevel@tonic-gate continue;
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate /* Partial overlap, shrink range */
3677c478bd9Sstevel@tonic-gate if (lo < rlo)
3687c478bd9Sstevel@tonic-gate newhi = rlo - 1;
3697c478bd9Sstevel@tonic-gate else
3707c478bd9Sstevel@tonic-gate newhi = hi;
3717c478bd9Sstevel@tonic-gate if (hi > rhi)
3727c478bd9Sstevel@tonic-gate newlo = rhi + 1;
3737c478bd9Sstevel@tonic-gate else
3747c478bd9Sstevel@tonic-gate newlo = lo;
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /* restore NULed character */
3777c478bd9Sstevel@tonic-gate *tail = tc;
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate /* Split range? */
3807c478bd9Sstevel@tonic-gate if (newlo > newhi) {
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate * We have two ranges:
3837c478bd9Sstevel@tonic-gate * lo ... newhi (== rlo - 1)
3847c478bd9Sstevel@tonic-gate * newlo (== rhi + 1) .. hi
3857c478bd9Sstevel@tonic-gate */
3867c478bd9Sstevel@tonic-gate put_minor_range(new, fep, tok, tail,
3877c478bd9Sstevel@tonic-gate lo, newhi, type);
3887c478bd9Sstevel@tonic-gate put_minor_range(new, NULL, tok, tail,
3897c478bd9Sstevel@tonic-gate newlo, hi, type);
3907c478bd9Sstevel@tonic-gate } else {
3917c478bd9Sstevel@tonic-gate put_minor_range(new, fep, tok, tail,
3927c478bd9Sstevel@tonic-gate newlo, newhi, type);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate continue;
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate } else if (strcmp(entry, tok) == 0 ||
3977c478bd9Sstevel@tonic-gate (strncmp(entry, tok, len) == 0 &&
3987c478bd9Sstevel@tonic-gate entry[len] == ':' &&
3997c478bd9Sstevel@tonic-gate entry[len+1] == '*' &&
4007c478bd9Sstevel@tonic-gate entry[len+2] == '\0')) {
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate * Delete exact match.
4037c478bd9Sstevel@tonic-gate */
4047c478bd9Sstevel@tonic-gate continue;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate /* Copy unaffected entry. */
4087c478bd9Sstevel@tonic-gate (void) fputs(fep->rawbuf, new);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate (void) fclose(old);
4117c478bd9Sstevel@tonic-gate (void) fflush(new);
4127c478bd9Sstevel@tonic-gate (void) fsync(newfd);
4137c478bd9Sstevel@tonic-gate if (ferror(new) == 0 && fclose(new) == 0 && fep != NULL) {
4147c478bd9Sstevel@tonic-gate if (rename(filename, ofile) != 0) {
4157c478bd9Sstevel@tonic-gate perror(NULL);
4167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), ofile);
4177c478bd9Sstevel@tonic-gate (void) unlink(ofile);
4187c478bd9Sstevel@tonic-gate (void) unlink(nfile);
4197c478bd9Sstevel@tonic-gate return (ERROR);
4207c478bd9Sstevel@tonic-gate } else if (rename(nfile, filename) != 0) {
4217c478bd9Sstevel@tonic-gate perror(NULL);
4227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), ofile);
4237c478bd9Sstevel@tonic-gate (void) rename(ofile, filename);
4247c478bd9Sstevel@tonic-gate (void) unlink(nfile);
4257c478bd9Sstevel@tonic-gate return (ERROR);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate (void) unlink(ofile);
4287c478bd9Sstevel@tonic-gate } else
4297c478bd9Sstevel@tonic-gate (void) unlink(nfile);
4307c478bd9Sstevel@tonic-gate return (0);
4317c478bd9Sstevel@tonic-gate }
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate int
delete_plcy_entry(const char * filename,const char * entry)4357c478bd9Sstevel@tonic-gate delete_plcy_entry(const char *filename, const char *entry)
4367c478bd9Sstevel@tonic-gate {
4377c478bd9Sstevel@tonic-gate char *p, *single;
4387c478bd9Sstevel@tonic-gate char *copy;
4397c478bd9Sstevel@tonic-gate int ret = 0;
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate copy = strdup(entry);
4427c478bd9Sstevel@tonic-gate if (copy == NULL)
4437c478bd9Sstevel@tonic-gate return (ERROR);
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate for (single = strtok_r(copy, " \t\n", &p);
4467c478bd9Sstevel@tonic-gate single != NULL;
4477c478bd9Sstevel@tonic-gate single = strtok_r(NULL, " \t\n", &p)) {
4487c478bd9Sstevel@tonic-gate if ((ret = delete_one_entry(filename, single)) != 0) {
4497c478bd9Sstevel@tonic-gate free(copy);
4507c478bd9Sstevel@tonic-gate return (ret);
4517c478bd9Sstevel@tonic-gate }
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate free(copy);
4547c478bd9Sstevel@tonic-gate return (0);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate * Analyze the device policy token; new tokens should be added to
4597c478bd9Sstevel@tonic-gate * toktab; new token types should be coded here.
4607c478bd9Sstevel@tonic-gate */
4617c478bd9Sstevel@tonic-gate int
parse_plcy_token(char * token,devplcysys_t * dp)4627c478bd9Sstevel@tonic-gate parse_plcy_token(char *token, devplcysys_t *dp)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate char *val = strchr(token, '=');
4657c478bd9Sstevel@tonic-gate const char *perr;
4667c478bd9Sstevel@tonic-gate int i;
4677c478bd9Sstevel@tonic-gate priv_set_t *pset;
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate if (val == NULL) {
4707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_EQUALS), token);
4717c478bd9Sstevel@tonic-gate return (1);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate *val++ = '\0';
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate for (i = 0; i < NTOK; i++) {
4767c478bd9Sstevel@tonic-gate if (strcmp(token, toktab[i].token) == 0) {
4777c478bd9Sstevel@tonic-gate /* standard pointer computation for tokens */
4787c478bd9Sstevel@tonic-gate void *item = (char *)dp + toktab[i].off;
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate switch (toktab[i].type) {
4817c478bd9Sstevel@tonic-gate case PSET:
4827c478bd9Sstevel@tonic-gate pset = priv_str_to_set(val, ",", &perr);
4837c478bd9Sstevel@tonic-gate if (pset == NULL) {
484*e4a991ebSAndy Fiddaman if (perr == NULL) {
485*e4a991ebSAndy Fiddaman (void) fprintf(stderr,
486*e4a991ebSAndy Fiddaman gettext(ERR_NO_MEM));
487*e4a991ebSAndy Fiddaman } else {
488*e4a991ebSAndy Fiddaman (void) fprintf(stderr,
489*e4a991ebSAndy Fiddaman gettext(ERR_BAD_PRIVS),
490*e4a991ebSAndy Fiddaman perr - val, val, perr);
491*e4a991ebSAndy Fiddaman }
4927c478bd9Sstevel@tonic-gate return (1);
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate priv_copyset(pset, item);
4957c478bd9Sstevel@tonic-gate priv_freeset(pset);
4967c478bd9Sstevel@tonic-gate break;
4977c478bd9Sstevel@tonic-gate default:
4987c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
499*e4a991ebSAndy Fiddaman "Internal Error: bad token type: %d\n",
500*e4a991ebSAndy Fiddaman toktab[i].type);
5017c478bd9Sstevel@tonic-gate return (1);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate /* Standard cleanup & return for good tokens */
5047c478bd9Sstevel@tonic-gate val[-1] = '=';
5057c478bd9Sstevel@tonic-gate return (0);
5067c478bd9Sstevel@tonic-gate }
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_TOKEN), token);
5097c478bd9Sstevel@tonic-gate return (1);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate static int
add2str(char ** dstp,const char * str,size_t * sz)5137c478bd9Sstevel@tonic-gate add2str(char **dstp, const char *str, size_t *sz)
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate char *p = *dstp;
5167c478bd9Sstevel@tonic-gate size_t len = strlen(p) + strlen(str) + 1;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate if (len > *sz) {
5197c478bd9Sstevel@tonic-gate *sz *= 2;
5207c478bd9Sstevel@tonic-gate if (*sz < len)
5217c478bd9Sstevel@tonic-gate *sz = len;
5227c478bd9Sstevel@tonic-gate *dstp = p = realloc(p, *sz);
5237c478bd9Sstevel@tonic-gate if (p == NULL) {
5247c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
5257c478bd9Sstevel@tonic-gate return (-1);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate (void) strcat(p, str);
5297c478bd9Sstevel@tonic-gate return (0);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate * Verify that the policy entry is valid and return the canonical entry.
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate char *
check_plcy_entry(char * entry,const char * driver,boolean_t todel)5367c478bd9Sstevel@tonic-gate check_plcy_entry(char *entry, const char *driver, boolean_t todel)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate char *res;
5397c478bd9Sstevel@tonic-gate devplcysys_t *ds;
5407c478bd9Sstevel@tonic-gate char *tok;
5417c478bd9Sstevel@tonic-gate size_t sz = strlen(entry) * 2 + strlen(driver) + 3;
5427c478bd9Sstevel@tonic-gate boolean_t tokseen = B_FALSE;
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate devplcy_init();
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate res = malloc(sz);
5477c478bd9Sstevel@tonic-gate ds = alloca(devplcysys_sz);
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate if (res == NULL || ds == NULL) {
5507c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
551*e4a991ebSAndy Fiddaman free(res);
5527c478bd9Sstevel@tonic-gate return (NULL);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate *res = '\0';
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate while ((tok = strtok(entry, " \t\n")) != NULL) {
5587c478bd9Sstevel@tonic-gate entry = NULL;
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate /* It's not a token */
5617c478bd9Sstevel@tonic-gate if (strchr(tok, '=') == NULL) {
5627c478bd9Sstevel@tonic-gate if (strchr(tok, ':') != NULL) {
5637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_MINOR));
5647c478bd9Sstevel@tonic-gate free(res);
5657c478bd9Sstevel@tonic-gate return (NULL);
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate if (*res != '\0' && add2str(&res, "\n", &sz) != 0)
5687c478bd9Sstevel@tonic-gate return (NULL);
5697c478bd9Sstevel@tonic-gate
5707c478bd9Sstevel@tonic-gate if (*tok == '(') {
5717c478bd9Sstevel@tonic-gate char type;
5727c478bd9Sstevel@tonic-gate if (parse_minor_range(tok, &ds->dps_lomin,
5737c478bd9Sstevel@tonic-gate &ds->dps_himin, &type) != 0 ||
5747c478bd9Sstevel@tonic-gate (!todel && type == '\0')) {
5757c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
5767c478bd9Sstevel@tonic-gate gettext(ERR_BAD_MINOR));
5777c478bd9Sstevel@tonic-gate free(res);
5787c478bd9Sstevel@tonic-gate return (NULL);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate } else {
5817c478bd9Sstevel@tonic-gate char *tmp = strchr(tok, '*');
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate if (tmp != NULL &&
5847c478bd9Sstevel@tonic-gate strchr(tmp + 1, '*') != NULL) {
5857c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
5867c478bd9Sstevel@tonic-gate gettext(ERR_BAD_MINOR));
5877c478bd9Sstevel@tonic-gate free(res);
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if (add2str(&res, driver, &sz) != 0)
5927c478bd9Sstevel@tonic-gate return (NULL);
5937c478bd9Sstevel@tonic-gate if (add2str(&res, ":", &sz) != 0)
5947c478bd9Sstevel@tonic-gate return (NULL);
5957c478bd9Sstevel@tonic-gate if (add2str(&res, tok, &sz) != 0)
5967c478bd9Sstevel@tonic-gate return (NULL);
5977c478bd9Sstevel@tonic-gate tokseen = B_FALSE;
5987c478bd9Sstevel@tonic-gate } else {
5997c478bd9Sstevel@tonic-gate if (*res == '\0') {
6007c478bd9Sstevel@tonic-gate if (add2str(&res, driver, &sz) != 0)
6017c478bd9Sstevel@tonic-gate return (NULL);
6027c478bd9Sstevel@tonic-gate if (add2str(&res, ":*", &sz) != 0)
6037c478bd9Sstevel@tonic-gate return (NULL);
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate if (parse_plcy_token(tok, ds) != 0) {
6067c478bd9Sstevel@tonic-gate free(res);
6077c478bd9Sstevel@tonic-gate return (NULL);
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate
6107c478bd9Sstevel@tonic-gate if (add2str(&res, "\t", &sz) != 0)
6117c478bd9Sstevel@tonic-gate return (NULL);
6127c478bd9Sstevel@tonic-gate if (add2str(&res, tok, &sz) != 0)
6137c478bd9Sstevel@tonic-gate return (NULL);
6147c478bd9Sstevel@tonic-gate tokseen = B_TRUE;
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate }
617*e4a991ebSAndy Fiddaman if ((todel && tokseen) || *res == '\0' || (!todel && !tokseen)) {
6187c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_INVALID_PLCY));
6197c478bd9Sstevel@tonic-gate free(res);
6207c478bd9Sstevel@tonic-gate return (NULL);
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate if (!todel)
6237c478bd9Sstevel@tonic-gate if (add2str(&res, "\n", &sz) != 0)
6247c478bd9Sstevel@tonic-gate return (NULL);
6257c478bd9Sstevel@tonic-gate return (res);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate int
update_device_policy(const char * filename,const char * entry,boolean_t repl)6297c478bd9Sstevel@tonic-gate update_device_policy(const char *filename, const char *entry, boolean_t repl)
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate FILE *fp;
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate if (repl) {
6347c478bd9Sstevel@tonic-gate char *dup, *tok, *s1;
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate dup = strdup(entry);
6377c478bd9Sstevel@tonic-gate if (dup == NULL) {
6387c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
6397c478bd9Sstevel@tonic-gate return (ERROR);
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate /*
6437c478bd9Sstevel@tonic-gate * Split the entry in lines; then get the first token
6447c478bd9Sstevel@tonic-gate * of each line.
6457c478bd9Sstevel@tonic-gate */
6467c478bd9Sstevel@tonic-gate for (tok = strtok_r(dup, "\n", &s1); tok != NULL;
6477c478bd9Sstevel@tonic-gate tok = strtok_r(NULL, "\n", &s1)) {
6487c478bd9Sstevel@tonic-gate
6497c478bd9Sstevel@tonic-gate tok = strtok(tok, " \n\t");
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate if (delete_one_entry(filename, tok) != 0) {
6527c478bd9Sstevel@tonic-gate free(dup);
6537c478bd9Sstevel@tonic-gate return (ERROR);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate free(dup);
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate fp = fopen(filename, "a");
6617c478bd9Sstevel@tonic-gate if (fp == NULL)
6627c478bd9Sstevel@tonic-gate return (ERROR);
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate (void) fputs(entry, fp);
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate if (fflush(fp) != 0 || fsync(fileno(fp)) != 0 || fclose(fp) != 0)
6677c478bd9Sstevel@tonic-gate return (ERROR);
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate return (NOERR);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate /*
6747c478bd9Sstevel@tonic-gate * We need to allocate the privileges now or the privilege set
6757c478bd9Sstevel@tonic-gate * parsing code will not allow them.
6767c478bd9Sstevel@tonic-gate */
6777c478bd9Sstevel@tonic-gate int
check_priv_entry(const char * privlist,boolean_t add)6787c478bd9Sstevel@tonic-gate check_priv_entry(const char *privlist, boolean_t add)
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate char *l = strdup(privlist);
6817c478bd9Sstevel@tonic-gate char *pr;
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate if (l == NULL) {
6847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
6857c478bd9Sstevel@tonic-gate return (ERROR);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate while ((pr = strtok_r(l, ",", &l)) != NULL) {
6897c478bd9Sstevel@tonic-gate /* Privilege already exists */
6907c478bd9Sstevel@tonic-gate if (priv_getbyname(pr) != -1)
6917c478bd9Sstevel@tonic-gate continue;
6927c478bd9Sstevel@tonic-gate
6937c478bd9Sstevel@tonic-gate if (add && modctl(MODALLOCPRIV, pr) != 0) {
6947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_PRIV), pr,
695*e4a991ebSAndy Fiddaman strerror(errno));
6967c478bd9Sstevel@tonic-gate return (ERROR);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate }
6997c478bd9Sstevel@tonic-gate return (NOERR);
7007c478bd9Sstevel@tonic-gate }
701