10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52805Seota * Common Development and Distribution License (the "License").
62805Seota * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
228831SJerry.Gilliam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stdlib.h>
282805Seota #include <ctype.h>
290Sstevel@tonic-gate #include <unistd.h>
300Sstevel@tonic-gate #include <sys/sysmacros.h>
310Sstevel@tonic-gate #include <libintl.h>
320Sstevel@tonic-gate #include <wait.h>
330Sstevel@tonic-gate #include <string.h>
348331SJerry.Gilliam@Sun.COM #include <strings.h>
350Sstevel@tonic-gate #include <errno.h>
360Sstevel@tonic-gate #include <fcntl.h>
370Sstevel@tonic-gate #include <signal.h>
380Sstevel@tonic-gate #include <sys/buf.h>
390Sstevel@tonic-gate #include <sys/stat.h>
400Sstevel@tonic-gate #include <grp.h>
410Sstevel@tonic-gate #include "addrem.h"
420Sstevel@tonic-gate #include "errmsg.h"
430Sstevel@tonic-gate #include "plcysubr.h"
440Sstevel@tonic-gate
4510599SJerry.Gilliam@Sun.COM /*
4610599SJerry.Gilliam@Sun.COM * Macros to produce a quoted string containing the value of a
4710599SJerry.Gilliam@Sun.COM * preprocessor macro. For example, if SIZE is defined to be 256,
4810599SJerry.Gilliam@Sun.COM * VAL2STR(SIZE) is "256". This is used to construct format
4910599SJerry.Gilliam@Sun.COM * strings for scanf-family functions below.
5010599SJerry.Gilliam@Sun.COM * Note: For format string use, the argument to VAL2STR() must
5110599SJerry.Gilliam@Sun.COM * be a numeric constant that is one less than the size of the
5210599SJerry.Gilliam@Sun.COM * corresponding data buffer.
5310599SJerry.Gilliam@Sun.COM */
5410599SJerry.Gilliam@Sun.COM #define VAL2STR_QUOTE(x) #x
5510599SJerry.Gilliam@Sun.COM #define VAL2STR(x) VAL2STR_QUOTE(x)
5610599SJerry.Gilliam@Sun.COM
5710599SJerry.Gilliam@Sun.COM /*
5810599SJerry.Gilliam@Sun.COM * Convenience macro to determine if a character is a quote
5910599SJerry.Gilliam@Sun.COM */
6010599SJerry.Gilliam@Sun.COM #define isquote(c) (((c) == '"') || ((c) == '\''))
6110599SJerry.Gilliam@Sun.COM
6210599SJerry.Gilliam@Sun.COM
630Sstevel@tonic-gate static char *add_rem_lock; /* lock file */
6410599SJerry.Gilliam@Sun.COM static char *tmphold; /* temporary file for updating */
653442Svikram static int add_rem_lock_fd = -1;
660Sstevel@tonic-gate
670Sstevel@tonic-gate static int get_cached_n_to_m_file(char *filename, char ***cache);
680Sstevel@tonic-gate static int get_name_to_major_entry(int *major_no, char *driver_name,
690Sstevel@tonic-gate char *file_name);
700Sstevel@tonic-gate
712805Seota static int is_blank(char *);
722805Seota
730Sstevel@tonic-gate /*ARGSUSED*/
740Sstevel@tonic-gate void
log_minorperm_error(minorperm_err_t err,int key)750Sstevel@tonic-gate log_minorperm_error(minorperm_err_t err, int key)
760Sstevel@tonic-gate {
770Sstevel@tonic-gate switch (err) {
780Sstevel@tonic-gate case MP_FOPEN_ERR:
790Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
808331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
810Sstevel@tonic-gate break;
820Sstevel@tonic-gate case MP_FCLOSE_ERR:
830Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
848331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
850Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
860Sstevel@tonic-gate break;
870Sstevel@tonic-gate case MP_IGNORING_LINE_ERR:
880Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
898331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
900Sstevel@tonic-gate break;
910Sstevel@tonic-gate case MP_ALLOC_ERR:
920Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
938331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
940Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
950Sstevel@tonic-gate break;
960Sstevel@tonic-gate case MP_NVLIST_ERR:
970Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
988331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
990Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
1000Sstevel@tonic-gate break;
1010Sstevel@tonic-gate case MP_CANT_FIND_USER_ERR:
1020Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
1038331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
1040Sstevel@tonic-gate break;
1050Sstevel@tonic-gate case MP_CANT_FIND_GROUP_ERR:
1060Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
1078331SJerry.Gilliam@Sun.COM MINOR_PERM_FILE);
1080Sstevel@tonic-gate break;
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * open file
1140Sstevel@tonic-gate * for each entry in list
1150Sstevel@tonic-gate * where list entries are separated by <list_separator>
1160Sstevel@tonic-gate * append entry : driver_name <entry_separator> entry
1170Sstevel@tonic-gate * close file
1180Sstevel@tonic-gate * return error/noerr
1190Sstevel@tonic-gate */
1200Sstevel@tonic-gate int
append_to_file(char * driver_name,char * entry_list,char * filename,char list_separator,char * entry_separator,int quoted)1210Sstevel@tonic-gate append_to_file(
1220Sstevel@tonic-gate char *driver_name,
1230Sstevel@tonic-gate char *entry_list,
1240Sstevel@tonic-gate char *filename,
1250Sstevel@tonic-gate char list_separator,
1264145Scth char *entry_separator,
1274145Scth int quoted)
1280Sstevel@tonic-gate {
12910599SJerry.Gilliam@Sun.COM int len, line_len;
1300Sstevel@tonic-gate int fpint;
1310Sstevel@tonic-gate char *current_head, *previous_head;
1320Sstevel@tonic-gate char *line, *one_entry;
1330Sstevel@tonic-gate FILE *fp;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate if ((fp = fopen(filename, "a")) == NULL) {
1360Sstevel@tonic-gate perror(NULL);
1370Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
1380Sstevel@tonic-gate filename);
1390Sstevel@tonic-gate return (ERROR);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate len = strlen(entry_list);
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate one_entry = calloc(len + 1, 1);
1450Sstevel@tonic-gate if (one_entry == NULL) {
1460Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), filename);
1470Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
1480Sstevel@tonic-gate (void) fclose(fp);
1490Sstevel@tonic-gate return (ERROR);
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate previous_head = entry_list;
1530Sstevel@tonic-gate
15410354SEdward.Pilatowicz@Sun.COM line_len = strlen(driver_name) + len + 4;
15510354SEdward.Pilatowicz@Sun.COM if (quoted)
15610354SEdward.Pilatowicz@Sun.COM line_len += 2;
15710354SEdward.Pilatowicz@Sun.COM
15810354SEdward.Pilatowicz@Sun.COM line = calloc(line_len, 1);
1590Sstevel@tonic-gate if (line == NULL) {
1600Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
1610Sstevel@tonic-gate (void) fclose(fp);
1620Sstevel@tonic-gate err_exit();
1630Sstevel@tonic-gate }
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate * get one entry at a time from list and append to <filename> file
1670Sstevel@tonic-gate */
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate do {
17010599SJerry.Gilliam@Sun.COM bzero(one_entry, len + 1);
17110354SEdward.Pilatowicz@Sun.COM bzero(line, line_len);
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate current_head = get_entry(previous_head, one_entry,
1744145Scth list_separator, quoted);
1750Sstevel@tonic-gate previous_head = current_head;
1760Sstevel@tonic-gate
17710599SJerry.Gilliam@Sun.COM (void) snprintf(line, line_len,
17810599SJerry.Gilliam@Sun.COM quoted ? "%s%s\"%s\"\n" : "%s%s%s\n",
17910599SJerry.Gilliam@Sun.COM driver_name, entry_separator, one_entry);
18010599SJerry.Gilliam@Sun.COM
18110599SJerry.Gilliam@Sun.COM if ((fputs(line, fp)) == EOF) {
18210599SJerry.Gilliam@Sun.COM perror(NULL);
18310599SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
18410599SJerry.Gilliam@Sun.COM filename);
18510599SJerry.Gilliam@Sun.COM }
18610599SJerry.Gilliam@Sun.COM
18710599SJerry.Gilliam@Sun.COM } while (*current_head != '\0');
18810599SJerry.Gilliam@Sun.COM
18910599SJerry.Gilliam@Sun.COM
19010599SJerry.Gilliam@Sun.COM (void) fflush(fp);
19110599SJerry.Gilliam@Sun.COM
19210599SJerry.Gilliam@Sun.COM fpint = fileno(fp);
19310599SJerry.Gilliam@Sun.COM (void) fsync(fpint);
19410599SJerry.Gilliam@Sun.COM
19510599SJerry.Gilliam@Sun.COM (void) fclose(fp);
19610599SJerry.Gilliam@Sun.COM
19710599SJerry.Gilliam@Sun.COM free(one_entry);
19810599SJerry.Gilliam@Sun.COM free(line);
19910599SJerry.Gilliam@Sun.COM
20010599SJerry.Gilliam@Sun.COM return (NOERR);
20110599SJerry.Gilliam@Sun.COM }
20210599SJerry.Gilliam@Sun.COM
20310599SJerry.Gilliam@Sun.COM /*
20410599SJerry.Gilliam@Sun.COM * open file
20510599SJerry.Gilliam@Sun.COM * for each entry in list
20610599SJerry.Gilliam@Sun.COM * where list entries are separated by <list_separator>
20710599SJerry.Gilliam@Sun.COM * append entry : driver_name <entry_separator> entry
20810599SJerry.Gilliam@Sun.COM * close file
20910599SJerry.Gilliam@Sun.COM * return error/noerr
21010599SJerry.Gilliam@Sun.COM */
21110599SJerry.Gilliam@Sun.COM int
append_to_minor_perm(char * driver_name,char * entry_list,char * filename)21210599SJerry.Gilliam@Sun.COM append_to_minor_perm(
21310599SJerry.Gilliam@Sun.COM char *driver_name,
21410599SJerry.Gilliam@Sun.COM char *entry_list,
21510599SJerry.Gilliam@Sun.COM char *filename)
21610599SJerry.Gilliam@Sun.COM {
21710599SJerry.Gilliam@Sun.COM int len, line_len;
21810599SJerry.Gilliam@Sun.COM int fpint;
21910599SJerry.Gilliam@Sun.COM char *current_head, *previous_head;
22010599SJerry.Gilliam@Sun.COM char *line, *one_entry;
22110599SJerry.Gilliam@Sun.COM FILE *fp;
22210599SJerry.Gilliam@Sun.COM
22310599SJerry.Gilliam@Sun.COM if ((fp = fopen(filename, "a")) == NULL) {
22410599SJerry.Gilliam@Sun.COM perror(NULL);
22510599SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
22610599SJerry.Gilliam@Sun.COM filename);
22710599SJerry.Gilliam@Sun.COM return (ERROR);
22810599SJerry.Gilliam@Sun.COM }
22910599SJerry.Gilliam@Sun.COM
23010599SJerry.Gilliam@Sun.COM len = strlen(entry_list);
23110599SJerry.Gilliam@Sun.COM
23210599SJerry.Gilliam@Sun.COM one_entry = calloc(len + 1, 1);
23310599SJerry.Gilliam@Sun.COM if (one_entry == NULL) {
23410599SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_UPDATE), filename);
23510599SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_MEM));
23610599SJerry.Gilliam@Sun.COM (void) fclose(fp);
23710599SJerry.Gilliam@Sun.COM return (ERROR);
23810599SJerry.Gilliam@Sun.COM }
23910599SJerry.Gilliam@Sun.COM
24010599SJerry.Gilliam@Sun.COM previous_head = entry_list;
24110599SJerry.Gilliam@Sun.COM
24210599SJerry.Gilliam@Sun.COM line_len = strlen(driver_name) + len + 4;
24310599SJerry.Gilliam@Sun.COM line = calloc(line_len, 1);
24410599SJerry.Gilliam@Sun.COM if (line == NULL) {
24510599SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_MEM));
24610599SJerry.Gilliam@Sun.COM (void) fclose(fp);
24710599SJerry.Gilliam@Sun.COM err_exit();
24810599SJerry.Gilliam@Sun.COM }
24910599SJerry.Gilliam@Sun.COM
25010599SJerry.Gilliam@Sun.COM /*
25110599SJerry.Gilliam@Sun.COM * get one entry at a time from list and append to <filename> file
25210599SJerry.Gilliam@Sun.COM */
25310599SJerry.Gilliam@Sun.COM do {
25410599SJerry.Gilliam@Sun.COM bzero(one_entry, len + 1);
25510599SJerry.Gilliam@Sun.COM bzero(line, line_len);
25610599SJerry.Gilliam@Sun.COM
25710599SJerry.Gilliam@Sun.COM current_head = get_perm_entry(previous_head, one_entry);
25810599SJerry.Gilliam@Sun.COM previous_head = current_head;
25910599SJerry.Gilliam@Sun.COM
26010599SJerry.Gilliam@Sun.COM (void) snprintf(line, line_len, "%s:%s\n",
26110599SJerry.Gilliam@Sun.COM driver_name, one_entry);
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate if ((fputs(line, fp)) == EOF) {
2640Sstevel@tonic-gate perror(NULL);
2650Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE),
2660Sstevel@tonic-gate filename);
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate } while (*current_head != '\0');
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate (void) fflush(fp);
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate fpint = fileno(fp);
2750Sstevel@tonic-gate (void) fsync(fpint);
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate (void) fclose(fp);
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate free(one_entry);
2800Sstevel@tonic-gate free(line);
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate return (NOERR);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
2858456SJerry.Gilliam@Sun.COM /*
2868456SJerry.Gilliam@Sun.COM * Require exact match to delete a driver alias/permission entry.
2878456SJerry.Gilliam@Sun.COM * Note line argument does not remain unchanged. Return 1 if matched.
2888456SJerry.Gilliam@Sun.COM */
2898456SJerry.Gilliam@Sun.COM static int
match_entry(char * line,char * match)2908456SJerry.Gilliam@Sun.COM match_entry(char *line, char *match)
2918456SJerry.Gilliam@Sun.COM {
2928456SJerry.Gilliam@Sun.COM char *token, *p;
2938456SJerry.Gilliam@Sun.COM int n;
2948456SJerry.Gilliam@Sun.COM
2958456SJerry.Gilliam@Sun.COM /* skip any leading white space */
29610599SJerry.Gilliam@Sun.COM while (*line && isspace(*line))
2978456SJerry.Gilliam@Sun.COM line++;
2988456SJerry.Gilliam@Sun.COM /*
2998456SJerry.Gilliam@Sun.COM * Find separator for driver name, either space or colon
3008456SJerry.Gilliam@Sun.COM * minor_perm: <driver>:<perm>
3018456SJerry.Gilliam@Sun.COM * driver_aliases: <driver> <alias>
3028456SJerry.Gilliam@Sun.COM * extra_privs: <driver>:<priv>
3038456SJerry.Gilliam@Sun.COM */
3048456SJerry.Gilliam@Sun.COM if ((token = strpbrk(line, " :\t")) == NULL)
3058456SJerry.Gilliam@Sun.COM return (0);
3068456SJerry.Gilliam@Sun.COM token++;
3078456SJerry.Gilliam@Sun.COM /* skip leading white space and quotes */
30810599SJerry.Gilliam@Sun.COM while (*token && (isspace(*token) || isquote(*token)))
3098456SJerry.Gilliam@Sun.COM token++;
3108456SJerry.Gilliam@Sun.COM /* strip trailing newline, white space and quotes */
3118456SJerry.Gilliam@Sun.COM n = strlen(token);
3128456SJerry.Gilliam@Sun.COM p = token + n-1;
31310599SJerry.Gilliam@Sun.COM while (n > 0 && (*p == '\n' || isspace(*p) || isquote(*p))) {
3148456SJerry.Gilliam@Sun.COM *p-- = 0;
3158456SJerry.Gilliam@Sun.COM n--;
3168456SJerry.Gilliam@Sun.COM }
3178456SJerry.Gilliam@Sun.COM if (n == 0)
3188456SJerry.Gilliam@Sun.COM return (0);
3198456SJerry.Gilliam@Sun.COM return (strcmp(token, match) == 0);
3208456SJerry.Gilliam@Sun.COM }
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate * open file
3240Sstevel@tonic-gate * read thru file, deleting all entries if first
3250Sstevel@tonic-gate * entry = driver_name
3260Sstevel@tonic-gate * close
3270Sstevel@tonic-gate * if error, leave original file intact with message
3280Sstevel@tonic-gate * assumption : drvconfig has been modified to work with clone
3290Sstevel@tonic-gate * entries in /etc/minor_perm as driver:mummble NOT
3300Sstevel@tonic-gate * clone:driver mummble
3310Sstevel@tonic-gate * this implementation will NOT find clone entries
3320Sstevel@tonic-gate * clone:driver mummble
3330Sstevel@tonic-gate * match:
3340Sstevel@tonic-gate * delete just the matching entry
3350Sstevel@tonic-gate *
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate int
delete_entry(char * oldfile,char * driver_name,char * marker,char * match)3380Sstevel@tonic-gate delete_entry(
3390Sstevel@tonic-gate char *oldfile,
3400Sstevel@tonic-gate char *driver_name,
3410Sstevel@tonic-gate char *marker,
3420Sstevel@tonic-gate char *match)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate int rv, i;
3450Sstevel@tonic-gate int status = NOERR;
3460Sstevel@tonic-gate int drvr_found = 0;
3470Sstevel@tonic-gate boolean_t nomatch = B_TRUE;
3488456SJerry.Gilliam@Sun.COM char *newfile, *tptr, *cp;
34910599SJerry.Gilliam@Sun.COM char line[MAX_DBFILE_ENTRY];
35010599SJerry.Gilliam@Sun.COM char drv[FILENAME_MAX + 1];
3510Sstevel@tonic-gate FILE *fp, *newfp;
3520Sstevel@tonic-gate struct group *sysgrp;
3538456SJerry.Gilliam@Sun.COM char *copy; /* same size as line */
3549268SJerry.Gilliam@Sun.COM char *match2 = NULL; /* match with quotes cleaned up */
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate /*
3579268SJerry.Gilliam@Sun.COM * if match is specified, sanity check it and clean it
3589268SJerry.Gilliam@Sun.COM * up by removing surrounding quotes as we require
3599268SJerry.Gilliam@Sun.COM * an exact match.
3600Sstevel@tonic-gate */
3619268SJerry.Gilliam@Sun.COM if (match) {
3629268SJerry.Gilliam@Sun.COM cp = match;
36310599SJerry.Gilliam@Sun.COM while (*cp && (isspace(*cp)))
3649268SJerry.Gilliam@Sun.COM cp++;
3659268SJerry.Gilliam@Sun.COM i = strlen(cp);
3669268SJerry.Gilliam@Sun.COM if (i > 0) {
3679268SJerry.Gilliam@Sun.COM if ((match2 = strdup(cp)) == NULL) {
3689268SJerry.Gilliam@Sun.COM perror(NULL);
3699268SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_MEM));
3709268SJerry.Gilliam@Sun.COM return (ERROR);
3719268SJerry.Gilliam@Sun.COM }
37210599SJerry.Gilliam@Sun.COM i = strlen(match2) - 1;
37310599SJerry.Gilliam@Sun.COM while (i >= 0 && (isspace(match2[i]))) {
37410599SJerry.Gilliam@Sun.COM match2[i] = 0;
37510599SJerry.Gilliam@Sun.COM i--;
37610599SJerry.Gilliam@Sun.COM }
3779268SJerry.Gilliam@Sun.COM }
3789268SJerry.Gilliam@Sun.COM if (match2 == NULL || (strlen(match2) == 0)) {
3799268SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
3809268SJerry.Gilliam@Sun.COM gettext(ERR_INT_UPDATE), oldfile);
3819268SJerry.Gilliam@Sun.COM return (ERROR);
3829268SJerry.Gilliam@Sun.COM }
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate if ((fp = fopen(oldfile, "r")) == NULL) {
3860Sstevel@tonic-gate perror(NULL);
3870Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), oldfile);
3880Sstevel@tonic-gate return (ERROR);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3918456SJerry.Gilliam@Sun.COM /* Space for defensive copy of input line */
3928456SJerry.Gilliam@Sun.COM copy = calloc(sizeof (line), 1);
3930Sstevel@tonic-gate
3948456SJerry.Gilliam@Sun.COM /* Build filename for temporary file */
3958456SJerry.Gilliam@Sun.COM tptr = calloc(strlen(oldfile) + strlen(XEND) + 1, 1);
3968456SJerry.Gilliam@Sun.COM if (tptr == NULL || copy == NULL) {
3970Sstevel@tonic-gate perror(NULL);
3980Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
3998456SJerry.Gilliam@Sun.COM return (ERROR);
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate (void) strcpy(tptr, oldfile);
4030Sstevel@tonic-gate (void) strcat(tptr, XEND);
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * Set gid so we preserve group attribute. Ideally we wouldn't
4070Sstevel@tonic-gate * assume a gid of "sys" but we can't undo the damage on already
4080Sstevel@tonic-gate * installed systems unless we force the issue.
4090Sstevel@tonic-gate */
4100Sstevel@tonic-gate if ((sysgrp = getgrnam("sys")) != NULL) {
4110Sstevel@tonic-gate (void) setgid(sysgrp->gr_gid);
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate newfile = mktemp(tptr);
4150Sstevel@tonic-gate
4160Sstevel@tonic-gate if ((newfp = fopen(newfile, "w")) == NULL) {
4170Sstevel@tonic-gate perror(NULL);
4180Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
4190Sstevel@tonic-gate newfile);
4200Sstevel@tonic-gate return (ERROR);
4210Sstevel@tonic-gate }
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate while ((fgets(line, sizeof (line), fp) != NULL) && status == NOERR) {
4248456SJerry.Gilliam@Sun.COM /* copy the whole line */
4258456SJerry.Gilliam@Sun.COM if (strlcpy(copy, line, sizeof (line)) >= sizeof (line)) {
4268456SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_UPDATE), oldfile);
4272805Seota status = ERROR;
4282805Seota break;
4292805Seota }
4302805Seota /* cut off comments starting with '#' */
4318456SJerry.Gilliam@Sun.COM if ((cp = strchr(copy, '#')) != NULL)
4322805Seota *cp = '\0';
4332805Seota /* ignore comment or blank lines */
4348456SJerry.Gilliam@Sun.COM if (is_blank(copy)) {
4352805Seota if (fputs(line, newfp) == EOF) {
4360Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE),
4370Sstevel@tonic-gate oldfile);
4380Sstevel@tonic-gate status = ERROR;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate continue;
4410Sstevel@tonic-gate }
4422805Seota
4432805Seota /* get the driver name */
44410599SJerry.Gilliam@Sun.COM if (sscanf(copy, "%" VAL2STR(FILENAME_MAX) "s", drv) != 1) {
4450Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
4460Sstevel@tonic-gate oldfile, line);
4470Sstevel@tonic-gate status = ERROR;
4482805Seota break;
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate for (i = strcspn(drv, marker); i < FILENAME_MAX; i++) {
4520Sstevel@tonic-gate drv[i] = '\0';
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate if (strcmp(driver_name, drv) != 0) {
4560Sstevel@tonic-gate if ((fputs(line, newfp)) == EOF) {
4570Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE),
4580Sstevel@tonic-gate oldfile);
4590Sstevel@tonic-gate status = ERROR;
4600Sstevel@tonic-gate }
4610Sstevel@tonic-gate } else {
4620Sstevel@tonic-gate drvr_found++;
4639268SJerry.Gilliam@Sun.COM if (match2) { /* Just delete one entry */
4640Sstevel@tonic-gate /* for now delete just minor_perm and aliases */
4650Sstevel@tonic-gate if ((strcmp(oldfile, minor_perm) == 0) ||
4660Sstevel@tonic-gate (strcmp(oldfile, extra_privs) == 0) ||
4670Sstevel@tonic-gate (strcmp(oldfile, driver_aliases) == 0)) {
4688456SJerry.Gilliam@Sun.COM
4698456SJerry.Gilliam@Sun.COM /* make defensive copy */
4708456SJerry.Gilliam@Sun.COM if (strlcpy(copy, line, sizeof (line))
4718456SJerry.Gilliam@Sun.COM >= sizeof (line)) {
4728456SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
4738456SJerry.Gilliam@Sun.COM gettext(ERR_UPDATE),
4748456SJerry.Gilliam@Sun.COM oldfile);
4758456SJerry.Gilliam@Sun.COM status = ERROR;
4768456SJerry.Gilliam@Sun.COM break;
4778456SJerry.Gilliam@Sun.COM }
4789268SJerry.Gilliam@Sun.COM if (match_entry(copy, match2)) {
4790Sstevel@tonic-gate nomatch = B_FALSE;
4800Sstevel@tonic-gate } else {
4810Sstevel@tonic-gate if ((fputs(line, newfp)) ==
4820Sstevel@tonic-gate EOF) {
4830Sstevel@tonic-gate (void) fprintf(stderr,
4840Sstevel@tonic-gate gettext(ERR_UPDATE),
4850Sstevel@tonic-gate oldfile);
4860Sstevel@tonic-gate status = ERROR;
4870Sstevel@tonic-gate }
4880Sstevel@tonic-gate if (nomatch != B_FALSE)
4890Sstevel@tonic-gate nomatch = B_TRUE;
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate } /* end of else */
4950Sstevel@tonic-gate } /* end of while */
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate (void) fclose(fp);
4988456SJerry.Gilliam@Sun.COM free(tptr);
4998456SJerry.Gilliam@Sun.COM free(copy);
5009268SJerry.Gilliam@Sun.COM if (match2)
5019268SJerry.Gilliam@Sun.COM free(match2);
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate /* Make sure that the file is on disk */
5040Sstevel@tonic-gate if (fflush(newfp) != 0 || fsync(fileno(newfp)) != 0)
5050Sstevel@tonic-gate status = ERROR;
5060Sstevel@tonic-gate else
5070Sstevel@tonic-gate rv = NOERR;
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate (void) fclose(newfp);
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate /* no matching driver found */
5120Sstevel@tonic-gate rv = NOERR;
5130Sstevel@tonic-gate if (!drvr_found ||
5140Sstevel@tonic-gate (nomatch == B_TRUE)) {
5150Sstevel@tonic-gate rv = NONE_FOUND;
5160Sstevel@tonic-gate }
5170Sstevel@tonic-gate
5180Sstevel@tonic-gate /*
5190Sstevel@tonic-gate * if error, leave original file, delete new file
5200Sstevel@tonic-gate * if noerr, replace original file with new file
5210Sstevel@tonic-gate */
5220Sstevel@tonic-gate
5230Sstevel@tonic-gate if (status == NOERR) {
5240Sstevel@tonic-gate if (rename(oldfile, tmphold) == -1) {
5250Sstevel@tonic-gate perror(NULL);
5260Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), oldfile);
5270Sstevel@tonic-gate (void) unlink(newfile);
5280Sstevel@tonic-gate return (ERROR);
5290Sstevel@tonic-gate } else if (rename(newfile, oldfile) == -1) {
5300Sstevel@tonic-gate perror(NULL);
5310Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), oldfile);
5320Sstevel@tonic-gate (void) unlink(oldfile);
5330Sstevel@tonic-gate (void) unlink(newfile);
5340Sstevel@tonic-gate if (link(tmphold, oldfile) == -1) {
5350Sstevel@tonic-gate perror(NULL);
5360Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINK),
5370Sstevel@tonic-gate oldfile, tmphold);
5380Sstevel@tonic-gate }
5390Sstevel@tonic-gate return (ERROR);
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate (void) unlink(tmphold);
5420Sstevel@tonic-gate } else {
5430Sstevel@tonic-gate /*
5440Sstevel@tonic-gate * since there's an error, leave file alone; remove
5450Sstevel@tonic-gate * new file
5460Sstevel@tonic-gate */
5470Sstevel@tonic-gate if (unlink(newfile) == -1) {
5480Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_RM), newfile);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate return (ERROR);
5510Sstevel@tonic-gate }
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate return (rv);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate
5570Sstevel@tonic-gate /*
5580Sstevel@tonic-gate * wrapper for call to get_name_to_major_entry(): given driver name,
5590Sstevel@tonic-gate * retrieve major number.
5600Sstevel@tonic-gate */
5610Sstevel@tonic-gate int
get_major_no(char * driver_name,char * file_name)5620Sstevel@tonic-gate get_major_no(char *driver_name, char *file_name)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate int major = UNIQUE;
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate if (get_name_to_major_entry(&major, driver_name, file_name) == ERROR)
5670Sstevel@tonic-gate return (ERROR);
5680Sstevel@tonic-gate else
5690Sstevel@tonic-gate return (major);
5700Sstevel@tonic-gate }
5710Sstevel@tonic-gate
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * wrapper for call to get_name_to_major_entry(): given major number,
5740Sstevel@tonic-gate * retrieve driver name.
5750Sstevel@tonic-gate */
5760Sstevel@tonic-gate int
get_driver_name(int major,char * file_name,char * buf)5770Sstevel@tonic-gate get_driver_name(int major, char *file_name, char *buf)
5780Sstevel@tonic-gate {
5790Sstevel@tonic-gate if (major < 0)
5800Sstevel@tonic-gate return (ERROR);
5810Sstevel@tonic-gate return (get_name_to_major_entry(&major, buf, file_name));
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate
5850Sstevel@tonic-gate /*
5860Sstevel@tonic-gate * return pointer to cached name_to_major file - reads file into
5870Sstevel@tonic-gate * cache if this has not already been done. Since there may be
5880Sstevel@tonic-gate * requests for multiple name_to_major files (rem_name_to_major,
5890Sstevel@tonic-gate * name_to_major), this routine keeps a list of cached files.
5900Sstevel@tonic-gate */
5910Sstevel@tonic-gate static int
get_cached_n_to_m_file(char * filename,char *** cache)5920Sstevel@tonic-gate get_cached_n_to_m_file(char *filename, char ***cache)
5930Sstevel@tonic-gate {
5940Sstevel@tonic-gate struct n_to_m_cache {
5950Sstevel@tonic-gate char *file;
5960Sstevel@tonic-gate char **cached_file;
5970Sstevel@tonic-gate int size;
5980Sstevel@tonic-gate struct n_to_m_cache *next;
5990Sstevel@tonic-gate };
6000Sstevel@tonic-gate static struct n_to_m_cache *head = NULL;
6010Sstevel@tonic-gate struct n_to_m_cache *ptr;
6020Sstevel@tonic-gate FILE *fp;
6030Sstevel@tonic-gate char drv[FILENAME_MAX + 1];
6040Sstevel@tonic-gate char entry[FILENAME_MAX + 1];
6052805Seota char line[MAX_N2M_ALIAS_LINE], *cp;
6060Sstevel@tonic-gate int maj;
6070Sstevel@tonic-gate int size = 0;
6080Sstevel@tonic-gate
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate /*
6110Sstevel@tonic-gate * see if the file is already cached - either
6120Sstevel@tonic-gate * rem_name_to_major or name_to_major
6130Sstevel@tonic-gate */
6140Sstevel@tonic-gate ptr = head;
6150Sstevel@tonic-gate while (ptr != NULL) {
6160Sstevel@tonic-gate if (strcmp(ptr->file, filename) == 0)
6170Sstevel@tonic-gate break;
6180Sstevel@tonic-gate ptr = ptr->next;
6190Sstevel@tonic-gate }
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate if (ptr == NULL) { /* we need to cache the contents */
6220Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) {
6230Sstevel@tonic-gate perror(NULL);
6240Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_OPEN),
6250Sstevel@tonic-gate filename);
6260Sstevel@tonic-gate return (ERROR);
6270Sstevel@tonic-gate }
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != NULL) {
6302805Seota /* cut off comments starting with '#' */
6312805Seota if ((cp = strchr(line, '#')) != NULL)
6322805Seota *cp = '\0';
6332805Seota /* ignore comment or blank lines */
6342805Seota if (is_blank(line))
6352805Seota continue;
6362805Seota /* sanity-check */
63710599SJerry.Gilliam@Sun.COM if (sscanf(line,
63810599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s" /* drv */
63910599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s", /* entry */
64010599SJerry.Gilliam@Sun.COM drv, entry) != 2) {
6410Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
6420Sstevel@tonic-gate filename, line);
6430Sstevel@tonic-gate continue;
6440Sstevel@tonic-gate }
6450Sstevel@tonic-gate maj = atoi(entry);
6460Sstevel@tonic-gate if (maj > size)
6470Sstevel@tonic-gate size = maj;
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate /* allocate struct to cache the file */
6510Sstevel@tonic-gate ptr = (struct n_to_m_cache *)calloc(1,
6520Sstevel@tonic-gate sizeof (struct n_to_m_cache));
6530Sstevel@tonic-gate if (ptr == NULL) {
6540Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
6550Sstevel@tonic-gate return (ERROR);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate ptr->size = size + 1;
6580Sstevel@tonic-gate /* allocate space to cache contents of file */
6590Sstevel@tonic-gate ptr->cached_file = (char **)calloc(ptr->size, sizeof (char *));
6600Sstevel@tonic-gate if (ptr->cached_file == NULL) {
6610Sstevel@tonic-gate free(ptr);
6620Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
6630Sstevel@tonic-gate return (ERROR);
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate rewind(fp);
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate /*
6690Sstevel@tonic-gate * now fill the cache
6700Sstevel@tonic-gate * the cache is an array of char pointers indexed by major
6710Sstevel@tonic-gate * number
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != NULL) {
6742805Seota /* cut off comments starting with '#' */
6752805Seota if ((cp = strchr(line, '#')) != NULL)
6762805Seota *cp = '\0';
6772805Seota /* ignore comment or blank lines */
6782805Seota if (is_blank(line))
6792805Seota continue;
6802805Seota /* sanity-check */
68110599SJerry.Gilliam@Sun.COM if (sscanf(line,
68210599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s" /* drv */
68310599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s", /* entry */
68410599SJerry.Gilliam@Sun.COM drv, entry) != 2) {
6850Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
6860Sstevel@tonic-gate filename, line);
6870Sstevel@tonic-gate continue;
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate maj = atoi(entry);
6900Sstevel@tonic-gate if ((ptr->cached_file[maj] = strdup(drv)) == NULL) {
6910Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
6920Sstevel@tonic-gate free(ptr->cached_file);
6930Sstevel@tonic-gate free(ptr);
6940Sstevel@tonic-gate return (ERROR);
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate (void) strcpy(ptr->cached_file[maj], drv);
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate (void) fclose(fp);
6990Sstevel@tonic-gate /* link the cache struct into the list of cached files */
7000Sstevel@tonic-gate ptr->file = strdup(filename);
7010Sstevel@tonic-gate if (ptr->file == NULL) {
7020Sstevel@tonic-gate for (maj = 0; maj <= ptr->size; maj++)
7030Sstevel@tonic-gate free(ptr->cached_file[maj]);
7040Sstevel@tonic-gate free(ptr->cached_file);
7050Sstevel@tonic-gate free(ptr);
7060Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
7070Sstevel@tonic-gate return (ERROR);
7080Sstevel@tonic-gate }
7090Sstevel@tonic-gate ptr->next = head;
7100Sstevel@tonic-gate head = ptr;
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate /* return value pointer to contents of file */
7130Sstevel@tonic-gate *cache = ptr->cached_file;
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate /* return size */
7160Sstevel@tonic-gate return (ptr->size);
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate /*
7210Sstevel@tonic-gate * Using get_cached_n_to_m_file(), retrieve maximum major number
7220Sstevel@tonic-gate * found in the specificed file (name_to_major/rem_name_to_major).
7230Sstevel@tonic-gate *
7240Sstevel@tonic-gate * The return value is actually the size of the internal cache including 0.
7250Sstevel@tonic-gate */
7260Sstevel@tonic-gate int
get_max_major(char * file_name)7270Sstevel@tonic-gate get_max_major(char *file_name)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate char **n_to_m_cache = NULL;
7300Sstevel@tonic-gate
7310Sstevel@tonic-gate return (get_cached_n_to_m_file(file_name, &n_to_m_cache));
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate /*
7360Sstevel@tonic-gate * searching name_to_major: if major_no == UNIQUE then the caller wants to
7370Sstevel@tonic-gate * use the driver name as the key. Otherwise, the caller wants to use
7380Sstevel@tonic-gate * the major number as a key.
7390Sstevel@tonic-gate *
7400Sstevel@tonic-gate * This routine caches the contents of the name_to_major file on
7410Sstevel@tonic-gate * first call. And it could be generalized to deal with other
7420Sstevel@tonic-gate * config files if necessary.
7430Sstevel@tonic-gate */
7440Sstevel@tonic-gate static int
get_name_to_major_entry(int * major_no,char * driver_name,char * file_name)7450Sstevel@tonic-gate get_name_to_major_entry(int *major_no, char *driver_name, char *file_name)
7460Sstevel@tonic-gate {
7470Sstevel@tonic-gate int maj;
7480Sstevel@tonic-gate char **n_to_m_cache = NULL;
7490Sstevel@tonic-gate int size = 0;
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate int ret = NOT_UNIQUE;
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate /*
7540Sstevel@tonic-gate * read the file in - we cache it in case caller wants to
7550Sstevel@tonic-gate * do multiple lookups
7560Sstevel@tonic-gate */
7570Sstevel@tonic-gate size = get_cached_n_to_m_file(file_name, &n_to_m_cache);
7580Sstevel@tonic-gate
7590Sstevel@tonic-gate if (size == ERROR)
7600Sstevel@tonic-gate return (ERROR);
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /* search with driver name as key */
7630Sstevel@tonic-gate if (*major_no == UNIQUE) {
7640Sstevel@tonic-gate for (maj = 0; maj < size; maj++) {
7650Sstevel@tonic-gate if ((n_to_m_cache[maj] != NULL) &&
7660Sstevel@tonic-gate (strcmp(driver_name, n_to_m_cache[maj]) == 0)) {
7670Sstevel@tonic-gate *major_no = maj;
7680Sstevel@tonic-gate break;
7690Sstevel@tonic-gate }
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate if (maj >= size)
7720Sstevel@tonic-gate ret = UNIQUE;
7730Sstevel@tonic-gate /* search with major number as key */
7740Sstevel@tonic-gate } else {
7750Sstevel@tonic-gate /*
7760Sstevel@tonic-gate * Bugid 1254588, drvconfig dump core after loading driver
7770Sstevel@tonic-gate * with major number bigger than entries defined in
7780Sstevel@tonic-gate * /etc/name_to_major.
7790Sstevel@tonic-gate */
7800Sstevel@tonic-gate if (*major_no >= size)
7810Sstevel@tonic-gate return (UNIQUE);
7820Sstevel@tonic-gate
7830Sstevel@tonic-gate if (n_to_m_cache[*major_no] != NULL) {
7840Sstevel@tonic-gate (void) strcpy(driver_name, n_to_m_cache[*major_no]);
7850Sstevel@tonic-gate } else
7860Sstevel@tonic-gate ret = UNIQUE;
7870Sstevel@tonic-gate }
7880Sstevel@tonic-gate return (ret);
7890Sstevel@tonic-gate }
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate /*
7924145Scth * Given pointer to begining of member 'n' in a space (or separator)
7934145Scth * separated list, return pointer to member 'n+1', and establish member 'n'
7944145Scth * in *current_entry. If unquote, then we skip a leading quote and treat
7954145Scth * the trailing quote as a separator (and skip).
7960Sstevel@tonic-gate */
7970Sstevel@tonic-gate char *
get_entry(char * prev_member,char * current_entry,char separator,int unquote)7980Sstevel@tonic-gate get_entry(
7990Sstevel@tonic-gate char *prev_member,
8000Sstevel@tonic-gate char *current_entry,
8014145Scth char separator,
8024145Scth int unquote)
8030Sstevel@tonic-gate {
8044145Scth char *ptr;
8054145Scth int quoted = 0;
8060Sstevel@tonic-gate
8070Sstevel@tonic-gate ptr = prev_member;
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate /* skip white space */
81010599SJerry.Gilliam@Sun.COM while (isspace(*ptr))
8110Sstevel@tonic-gate ptr++;
8120Sstevel@tonic-gate
8134145Scth /* if unquote skip leading quote */
8144145Scth if (unquote && *ptr == '"') {
8154145Scth quoted++;
8164145Scth ptr++;
8174145Scth }
8184145Scth
8194145Scth /* read thru the current entry looking for end, separator, or unquote */
8204145Scth while (*ptr &&
82110599SJerry.Gilliam@Sun.COM (*ptr != separator) && (!isspace(*ptr)) &&
8224145Scth (!quoted || (*ptr != '"'))) {
8230Sstevel@tonic-gate *current_entry++ = *ptr++;
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate *current_entry = '\0';
8260Sstevel@tonic-gate
8274145Scth if (separator && (*ptr == separator))
8284145Scth ptr++; /* skip over separator */
8294145Scth if (quoted && (*ptr == '"'))
8304145Scth ptr++; /* skip over trailing quote */
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate /* skip white space */
83310599SJerry.Gilliam@Sun.COM while (isspace(*ptr))
8340Sstevel@tonic-gate ptr++;
83510599SJerry.Gilliam@Sun.COM
83610599SJerry.Gilliam@Sun.COM return (ptr);
83710599SJerry.Gilliam@Sun.COM }
83810599SJerry.Gilliam@Sun.COM
83910599SJerry.Gilliam@Sun.COM /*
84010599SJerry.Gilliam@Sun.COM * A parser specific to the add_drv "-m permission" syntax:
84110599SJerry.Gilliam@Sun.COM *
84210599SJerry.Gilliam@Sun.COM * -m '<minor-name> <permissions> <owner> <group>', ...
84310599SJerry.Gilliam@Sun.COM *
84410599SJerry.Gilliam@Sun.COM * One entry is parsed starting at prev_member and returned
84510599SJerry.Gilliam@Sun.COM * in the string pointed at by current_entry. A pointer
84610599SJerry.Gilliam@Sun.COM * to the entry following is returned.
84710599SJerry.Gilliam@Sun.COM */
84810599SJerry.Gilliam@Sun.COM char *
get_perm_entry(char * prev_member,char * current_entry)84910599SJerry.Gilliam@Sun.COM get_perm_entry(
85010599SJerry.Gilliam@Sun.COM char *prev_member,
85110599SJerry.Gilliam@Sun.COM char *current_entry)
85210599SJerry.Gilliam@Sun.COM {
85310599SJerry.Gilliam@Sun.COM char *ptr;
85410599SJerry.Gilliam@Sun.COM int nfields = 0;
85510599SJerry.Gilliam@Sun.COM int maxfields = 4; /* fields in a permissions format */
85610599SJerry.Gilliam@Sun.COM
85710599SJerry.Gilliam@Sun.COM ptr = prev_member;
85810599SJerry.Gilliam@Sun.COM while (isspace(*ptr))
85910599SJerry.Gilliam@Sun.COM ptr++;
86010599SJerry.Gilliam@Sun.COM
86110599SJerry.Gilliam@Sun.COM while (*ptr) {
86210599SJerry.Gilliam@Sun.COM /* comma allowed in minor name token only */
86310599SJerry.Gilliam@Sun.COM if (*ptr == ',' && nfields > 0) {
86410599SJerry.Gilliam@Sun.COM break;
86510599SJerry.Gilliam@Sun.COM } else if (isspace(*ptr)) {
86610599SJerry.Gilliam@Sun.COM *current_entry++ = *ptr++;
86710599SJerry.Gilliam@Sun.COM while (isspace(*ptr))
86810599SJerry.Gilliam@Sun.COM ptr++;
86910599SJerry.Gilliam@Sun.COM if (++nfields == maxfields)
87010599SJerry.Gilliam@Sun.COM break;
87110599SJerry.Gilliam@Sun.COM } else
87210599SJerry.Gilliam@Sun.COM *current_entry++ = *ptr++;
8730Sstevel@tonic-gate }
87410599SJerry.Gilliam@Sun.COM *current_entry = '\0';
87510599SJerry.Gilliam@Sun.COM
87610599SJerry.Gilliam@Sun.COM while (isspace(*ptr))
87710599SJerry.Gilliam@Sun.COM ptr++;
87810599SJerry.Gilliam@Sun.COM if (*ptr == ',') {
87910599SJerry.Gilliam@Sun.COM ptr++; /* skip over optional trailing comma */
88010599SJerry.Gilliam@Sun.COM }
88110599SJerry.Gilliam@Sun.COM while (isspace(*ptr))
88210599SJerry.Gilliam@Sun.COM ptr++;
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate return (ptr);
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate void
enter_lock(void)8880Sstevel@tonic-gate enter_lock(void)
8890Sstevel@tonic-gate {
8903442Svikram struct flock lock;
8910Sstevel@tonic-gate
8920Sstevel@tonic-gate /*
89310599SJerry.Gilliam@Sun.COM * Attempt to create the lock file. Open the file itself,
89410599SJerry.Gilliam@Sun.COM * and not a symlink to some other file.
8950Sstevel@tonic-gate */
89610599SJerry.Gilliam@Sun.COM add_rem_lock_fd = open(add_rem_lock,
89710599SJerry.Gilliam@Sun.COM O_CREAT|O_RDWR|O_NOFOLLOW|O_NOLINKS, S_IRUSR|S_IWUSR);
8983442Svikram if (add_rem_lock_fd < 0) {
8993442Svikram (void) fprintf(stderr, gettext(ERR_CREAT_LOCK),
9003442Svikram add_rem_lock, strerror(errno));
9013442Svikram exit(1);
9023442Svikram }
9033442Svikram
9043442Svikram lock.l_type = F_WRLCK;
9053442Svikram lock.l_whence = SEEK_SET;
9063442Svikram lock.l_start = 0;
9073442Svikram lock.l_len = 0;
9083442Svikram
9093442Svikram /* Try for the lock but don't wait. */
9103442Svikram if (fcntl(add_rem_lock_fd, F_SETLK, &lock) == -1) {
9113442Svikram if (errno == EACCES || errno == EAGAIN) {
9120Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_PROG_IN_USE));
9130Sstevel@tonic-gate } else {
9143442Svikram (void) fprintf(stderr, gettext(ERR_LOCK),
9153442Svikram add_rem_lock, strerror(errno));
9160Sstevel@tonic-gate }
9170Sstevel@tonic-gate exit(1);
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate }
9200Sstevel@tonic-gate
9210Sstevel@tonic-gate void
err_exit(void)9220Sstevel@tonic-gate err_exit(void)
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate /* release memory allocated for moddir */
9250Sstevel@tonic-gate cleanup_moddir();
9260Sstevel@tonic-gate /* remove add_drv/rem_drv lock */
9270Sstevel@tonic-gate exit_unlock();
9280Sstevel@tonic-gate exit(1);
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate void
cleanup_moddir(void)9320Sstevel@tonic-gate cleanup_moddir(void)
9330Sstevel@tonic-gate {
9340Sstevel@tonic-gate struct drvmod_dir *walk_ptr;
9350Sstevel@tonic-gate struct drvmod_dir *free_ptr = moddir;
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate while (free_ptr != NULL) {
9380Sstevel@tonic-gate walk_ptr = free_ptr->next;
9390Sstevel@tonic-gate free(free_ptr);
9400Sstevel@tonic-gate free_ptr = walk_ptr;
9410Sstevel@tonic-gate }
9420Sstevel@tonic-gate }
9430Sstevel@tonic-gate
9440Sstevel@tonic-gate void
exit_unlock(void)9450Sstevel@tonic-gate exit_unlock(void)
9460Sstevel@tonic-gate {
9473442Svikram struct flock unlock;
9483442Svikram
9493442Svikram if (add_rem_lock_fd < 0)
9503442Svikram return;
9510Sstevel@tonic-gate
9523442Svikram unlock.l_type = F_UNLCK;
9533442Svikram unlock.l_whence = SEEK_SET;
9543442Svikram unlock.l_start = 0;
9553442Svikram unlock.l_len = 0;
9563442Svikram
9573442Svikram if (fcntl(add_rem_lock_fd, F_SETLK, &unlock) == -1) {
9583442Svikram (void) fprintf(stderr, gettext(ERR_UNLOCK),
9593442Svikram add_rem_lock, strerror(errno));
9603442Svikram } else {
9613442Svikram (void) close(add_rem_lock_fd);
9623442Svikram add_rem_lock_fd = -1;
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate }
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate /*
9670Sstevel@tonic-gate * error adding driver; need to back out any changes to files.
9680Sstevel@tonic-gate * check flag to see which files need entries removed
9690Sstevel@tonic-gate * entry removal based on driver name
9700Sstevel@tonic-gate */
9710Sstevel@tonic-gate void
remove_entry(int c_flag,char * driver_name)9720Sstevel@tonic-gate remove_entry(
9730Sstevel@tonic-gate int c_flag,
9740Sstevel@tonic-gate char *driver_name)
9750Sstevel@tonic-gate {
9760Sstevel@tonic-gate
9770Sstevel@tonic-gate if (c_flag & CLEAN_NAM_MAJ) {
9780Sstevel@tonic-gate if (delete_entry(name_to_major, driver_name, " ",
9790Sstevel@tonic-gate NULL) == ERROR) {
9800Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_CLEAN),
9810Sstevel@tonic-gate name_to_major, driver_name);
9820Sstevel@tonic-gate }
9830Sstevel@tonic-gate }
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate if (c_flag & CLEAN_DRV_ALIAS) {
9860Sstevel@tonic-gate if (delete_entry(driver_aliases, driver_name, " ",
9870Sstevel@tonic-gate NULL) == ERROR) {
9880Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY),
9890Sstevel@tonic-gate driver_name, driver_aliases);
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate }
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate if (c_flag & CLEAN_DRV_CLASSES) {
9940Sstevel@tonic-gate if (delete_entry(driver_classes, driver_name, "\t", NULL) ==
9950Sstevel@tonic-gate ERROR) {
9960Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY),
9970Sstevel@tonic-gate driver_name, driver_classes);
9980Sstevel@tonic-gate }
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate
10010Sstevel@tonic-gate if (c_flag & CLEAN_MINOR_PERM) {
10020Sstevel@tonic-gate if (delete_entry(minor_perm, driver_name, ":", NULL) == ERROR) {
10030Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY),
10040Sstevel@tonic-gate driver_name, minor_perm);
10050Sstevel@tonic-gate }
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate /*
10080Sstevel@tonic-gate * There's no point in removing entries from files that don't
10090Sstevel@tonic-gate * exist. Prevent error messages by checking for file existence
10100Sstevel@tonic-gate * first.
10110Sstevel@tonic-gate */
10120Sstevel@tonic-gate if ((c_flag & CLEAN_DEV_POLICY) != 0 &&
10130Sstevel@tonic-gate access(device_policy, F_OK) == 0) {
10140Sstevel@tonic-gate if (delete_plcy_entry(device_policy, driver_name) == ERROR) {
10150Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY),
10168331SJerry.Gilliam@Sun.COM driver_name, device_policy);
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate }
10190Sstevel@tonic-gate if ((c_flag & CLEAN_DRV_PRIV) != 0 &&
10200Sstevel@tonic-gate access(extra_privs, F_OK) == 0) {
10210Sstevel@tonic-gate if (delete_entry(extra_privs, driver_name, ":", NULL) ==
10220Sstevel@tonic-gate ERROR) {
10230Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY),
10248331SJerry.Gilliam@Sun.COM driver_name, extra_privs);
10250Sstevel@tonic-gate }
10260Sstevel@tonic-gate }
10270Sstevel@tonic-gate }
10280Sstevel@tonic-gate
10290Sstevel@tonic-gate int
check_perms_aliases(int m_flag,int i_flag)10300Sstevel@tonic-gate check_perms_aliases(
10310Sstevel@tonic-gate int m_flag,
10320Sstevel@tonic-gate int i_flag)
10330Sstevel@tonic-gate {
10340Sstevel@tonic-gate /*
10350Sstevel@tonic-gate * If neither i_flag nor m_flag are specified no need to check the
10360Sstevel@tonic-gate * files for access permissions
10370Sstevel@tonic-gate */
10380Sstevel@tonic-gate if (!m_flag && !i_flag)
10390Sstevel@tonic-gate return (NOERR);
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate /* check minor_perm file : exits and is writable */
10420Sstevel@tonic-gate if (m_flag) {
10430Sstevel@tonic-gate if (access(minor_perm, R_OK | W_OK)) {
10440Sstevel@tonic-gate perror(NULL);
10450Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
10460Sstevel@tonic-gate minor_perm);
10470Sstevel@tonic-gate return (ERROR);
10480Sstevel@tonic-gate }
10490Sstevel@tonic-gate }
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate /* check driver_aliases file : exits and is writable */
10520Sstevel@tonic-gate if (i_flag) {
10530Sstevel@tonic-gate if (access(driver_aliases, R_OK | W_OK)) {
10540Sstevel@tonic-gate perror(NULL);
10550Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
10560Sstevel@tonic-gate driver_aliases);
10570Sstevel@tonic-gate return (ERROR);
10580Sstevel@tonic-gate }
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate return (NOERR);
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate
10640Sstevel@tonic-gate
10650Sstevel@tonic-gate int
check_name_to_major(int mode)10660Sstevel@tonic-gate check_name_to_major(int mode)
10670Sstevel@tonic-gate {
10680Sstevel@tonic-gate /* check name_to_major file : exists and is writable */
10690Sstevel@tonic-gate if (access(name_to_major, mode)) {
10700Sstevel@tonic-gate perror(NULL);
10710Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
10720Sstevel@tonic-gate name_to_major);
10730Sstevel@tonic-gate return (ERROR);
10740Sstevel@tonic-gate }
10750Sstevel@tonic-gate
10760Sstevel@tonic-gate return (NOERR);
10770Sstevel@tonic-gate }
10780Sstevel@tonic-gate
10790Sstevel@tonic-gate
10800Sstevel@tonic-gate /*
10810Sstevel@tonic-gate * All this stuff is to support a server installing
10820Sstevel@tonic-gate * drivers on diskless clients. When on the server
10830Sstevel@tonic-gate * need to prepend the basedir
10840Sstevel@tonic-gate */
10850Sstevel@tonic-gate int
build_filenames(char * basedir)10860Sstevel@tonic-gate build_filenames(char *basedir)
10870Sstevel@tonic-gate {
10889268SJerry.Gilliam@Sun.COM int len;
10899268SJerry.Gilliam@Sun.COM int driver_aliases_len;
10909268SJerry.Gilliam@Sun.COM int driver_classes_len;
10919268SJerry.Gilliam@Sun.COM int minor_perm_len;
10929268SJerry.Gilliam@Sun.COM int name_to_major_len;
10939268SJerry.Gilliam@Sun.COM int rem_name_to_major_len;
10949268SJerry.Gilliam@Sun.COM int add_rem_lock_len;
10959268SJerry.Gilliam@Sun.COM int tmphold_len;
10969268SJerry.Gilliam@Sun.COM int devfs_root_len;
10979268SJerry.Gilliam@Sun.COM int device_policy_len;
10989268SJerry.Gilliam@Sun.COM int extra_privs_len;
10990Sstevel@tonic-gate
11000Sstevel@tonic-gate if (basedir == NULL) {
11010Sstevel@tonic-gate driver_aliases = DRIVER_ALIAS;
11020Sstevel@tonic-gate driver_classes = DRIVER_CLASSES;
11030Sstevel@tonic-gate minor_perm = MINOR_PERM;
11040Sstevel@tonic-gate name_to_major = NAM_TO_MAJ;
11050Sstevel@tonic-gate rem_name_to_major = REM_NAM_TO_MAJ;
11060Sstevel@tonic-gate add_rem_lock = ADD_REM_LOCK;
11070Sstevel@tonic-gate tmphold = TMPHOLD;
11080Sstevel@tonic-gate devfs_root = DEVFS_ROOT;
11090Sstevel@tonic-gate device_policy = DEV_POLICY;
11100Sstevel@tonic-gate extra_privs = EXTRA_PRIVS;
11110Sstevel@tonic-gate
11120Sstevel@tonic-gate } else {
11139268SJerry.Gilliam@Sun.COM len = strlen(basedir) + 1;
11140Sstevel@tonic-gate
11159268SJerry.Gilliam@Sun.COM driver_aliases_len = len + sizeof (DRIVER_ALIAS);
11169268SJerry.Gilliam@Sun.COM driver_classes_len = len + sizeof (DRIVER_CLASSES);
11179268SJerry.Gilliam@Sun.COM minor_perm_len = len + sizeof (MINOR_PERM);
11189268SJerry.Gilliam@Sun.COM name_to_major_len = len + sizeof (NAM_TO_MAJ);
11199268SJerry.Gilliam@Sun.COM rem_name_to_major_len = len + sizeof (REM_NAM_TO_MAJ);
11209268SJerry.Gilliam@Sun.COM add_rem_lock_len = len + sizeof (ADD_REM_LOCK);
11219268SJerry.Gilliam@Sun.COM tmphold_len = len + sizeof (TMPHOLD);
11229268SJerry.Gilliam@Sun.COM devfs_root_len = len + sizeof (DEVFS_ROOT);
11239268SJerry.Gilliam@Sun.COM device_policy_len = len + sizeof (DEV_POLICY);
11249268SJerry.Gilliam@Sun.COM extra_privs_len = len + sizeof (EXTRA_PRIVS);
11250Sstevel@tonic-gate
11269268SJerry.Gilliam@Sun.COM driver_aliases = malloc(driver_aliases_len);
11279268SJerry.Gilliam@Sun.COM driver_classes = malloc(driver_classes_len);
11289268SJerry.Gilliam@Sun.COM minor_perm = malloc(minor_perm_len);
11299268SJerry.Gilliam@Sun.COM name_to_major = malloc(name_to_major_len);
11309268SJerry.Gilliam@Sun.COM rem_name_to_major = malloc(rem_name_to_major_len);
11319268SJerry.Gilliam@Sun.COM add_rem_lock = malloc(add_rem_lock_len);
11329268SJerry.Gilliam@Sun.COM tmphold = malloc(tmphold_len);
11339268SJerry.Gilliam@Sun.COM devfs_root = malloc(devfs_root_len);
11349268SJerry.Gilliam@Sun.COM device_policy = malloc(device_policy_len);
11359268SJerry.Gilliam@Sun.COM extra_privs = malloc(extra_privs_len);
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate if ((driver_aliases == NULL) ||
11380Sstevel@tonic-gate (driver_classes == NULL) ||
11390Sstevel@tonic-gate (minor_perm == NULL) ||
11400Sstevel@tonic-gate (name_to_major == NULL) ||
11410Sstevel@tonic-gate (rem_name_to_major == NULL) ||
11420Sstevel@tonic-gate (add_rem_lock == NULL) ||
11430Sstevel@tonic-gate (tmphold == NULL) ||
11440Sstevel@tonic-gate (devfs_root == NULL) ||
11450Sstevel@tonic-gate (device_policy == NULL) ||
11460Sstevel@tonic-gate (extra_privs == NULL)) {
11470Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
11480Sstevel@tonic-gate return (ERROR);
11490Sstevel@tonic-gate }
11500Sstevel@tonic-gate
11519268SJerry.Gilliam@Sun.COM (void) snprintf(driver_aliases, driver_aliases_len,
11529268SJerry.Gilliam@Sun.COM "%s%s", basedir, DRIVER_ALIAS);
11539268SJerry.Gilliam@Sun.COM (void) snprintf(driver_classes, driver_classes_len,
11549268SJerry.Gilliam@Sun.COM "%s%s", basedir, DRIVER_CLASSES);
11559268SJerry.Gilliam@Sun.COM (void) snprintf(minor_perm, minor_perm_len,
11569268SJerry.Gilliam@Sun.COM "%s%s", basedir, MINOR_PERM);
11579268SJerry.Gilliam@Sun.COM (void) snprintf(name_to_major, name_to_major_len,
11589268SJerry.Gilliam@Sun.COM "%s%s", basedir, NAM_TO_MAJ);
11599268SJerry.Gilliam@Sun.COM (void) snprintf(rem_name_to_major, rem_name_to_major_len,
11609268SJerry.Gilliam@Sun.COM "%s%s", basedir, REM_NAM_TO_MAJ);
11619268SJerry.Gilliam@Sun.COM (void) snprintf(add_rem_lock, add_rem_lock_len,
11629268SJerry.Gilliam@Sun.COM "%s%s", basedir, ADD_REM_LOCK);
11639268SJerry.Gilliam@Sun.COM (void) snprintf(tmphold, tmphold_len,
11649268SJerry.Gilliam@Sun.COM "%s%s", basedir, TMPHOLD);
11659268SJerry.Gilliam@Sun.COM (void) snprintf(devfs_root, devfs_root_len,
11669268SJerry.Gilliam@Sun.COM "%s%s", basedir, DEVFS_ROOT);
11679268SJerry.Gilliam@Sun.COM (void) snprintf(device_policy, device_policy_len,
11689268SJerry.Gilliam@Sun.COM "%s%s", basedir, DEV_POLICY);
11699268SJerry.Gilliam@Sun.COM (void) snprintf(extra_privs, extra_privs_len,
11709268SJerry.Gilliam@Sun.COM "%s%s", basedir, EXTRA_PRIVS);
11710Sstevel@tonic-gate }
11720Sstevel@tonic-gate
11730Sstevel@tonic-gate return (NOERR);
11740Sstevel@tonic-gate }
11750Sstevel@tonic-gate
11760Sstevel@tonic-gate static int
exec_command(char * path,char * cmdline[MAX_CMD_LINE])11770Sstevel@tonic-gate exec_command(char *path, char *cmdline[MAX_CMD_LINE])
11780Sstevel@tonic-gate {
11790Sstevel@tonic-gate pid_t pid;
11800Sstevel@tonic-gate uint_t stat_loc;
11810Sstevel@tonic-gate int waitstat;
11820Sstevel@tonic-gate int exit_status;
11830Sstevel@tonic-gate
11840Sstevel@tonic-gate /* child */
11850Sstevel@tonic-gate if ((pid = fork()) == 0) {
11860Sstevel@tonic-gate (void) execv(path, cmdline);
11870Sstevel@tonic-gate perror(NULL);
11880Sstevel@tonic-gate return (ERROR);
11890Sstevel@tonic-gate } else if (pid == -1) {
11900Sstevel@tonic-gate /* fork failed */
11910Sstevel@tonic-gate perror(NULL);
11920Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_FORK_FAIL), cmdline);
11930Sstevel@tonic-gate return (ERROR);
11940Sstevel@tonic-gate } else {
11950Sstevel@tonic-gate /* parent */
11960Sstevel@tonic-gate do {
11970Sstevel@tonic-gate waitstat = waitpid(pid, (int *)&stat_loc, 0);
11980Sstevel@tonic-gate
11990Sstevel@tonic-gate } while ((!WIFEXITED(stat_loc) &&
12008331SJerry.Gilliam@Sun.COM !WIFSIGNALED(stat_loc)) || (waitstat == 0));
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate exit_status = WEXITSTATUS(stat_loc);
12030Sstevel@tonic-gate
12040Sstevel@tonic-gate return (exit_status);
12050Sstevel@tonic-gate }
12060Sstevel@tonic-gate }
12070Sstevel@tonic-gate
12080Sstevel@tonic-gate /*
12098831SJerry.Gilliam@Sun.COM * Exec devfsadm to perform driver config/unconfig operation,
12108831SJerry.Gilliam@Sun.COM * adding or removing aliases.
12110Sstevel@tonic-gate */
12128831SJerry.Gilliam@Sun.COM static int
exec_devfsadm(boolean_t config,char * driver_name,major_t major_num,char * aliases,char * classes,int config_flags)12138831SJerry.Gilliam@Sun.COM exec_devfsadm(
12148831SJerry.Gilliam@Sun.COM boolean_t config,
12150Sstevel@tonic-gate char *driver_name,
12160Sstevel@tonic-gate major_t major_num,
12170Sstevel@tonic-gate char *aliases,
12180Sstevel@tonic-gate char *classes,
1219*10842SJerry.Gilliam@Sun.COM int config_flags)
12200Sstevel@tonic-gate {
12210Sstevel@tonic-gate int n = 0;
12220Sstevel@tonic-gate char *cmdline[MAX_CMD_LINE];
12230Sstevel@tonic-gate char maj_num[128];
12240Sstevel@tonic-gate char *previous;
12250Sstevel@tonic-gate char *current;
12260Sstevel@tonic-gate int len;
12278831SJerry.Gilliam@Sun.COM int rv;
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate /* build command line */
12300Sstevel@tonic-gate cmdline[n++] = DRVCONFIG;
12318831SJerry.Gilliam@Sun.COM if (config == B_FALSE) {
12328831SJerry.Gilliam@Sun.COM cmdline[n++] = "-u"; /* unconfigure */
1233*10842SJerry.Gilliam@Sun.COM if (config_flags & CONFIG_DRV_FORCE)
12348831SJerry.Gilliam@Sun.COM cmdline[n++] = "-f"; /* force if currently in use */
12358831SJerry.Gilliam@Sun.COM }
1236*10842SJerry.Gilliam@Sun.COM if (config_flags & CONFIG_DRV_VERBOSE) {
12370Sstevel@tonic-gate cmdline[n++] = "-v";
12380Sstevel@tonic-gate }
12390Sstevel@tonic-gate cmdline[n++] = "-b";
12400Sstevel@tonic-gate if (classes) {
12410Sstevel@tonic-gate cmdline[n++] = "-c";
12420Sstevel@tonic-gate cmdline[n++] = classes;
12430Sstevel@tonic-gate }
12440Sstevel@tonic-gate cmdline[n++] = "-i";
12450Sstevel@tonic-gate cmdline[n++] = driver_name;
12460Sstevel@tonic-gate cmdline[n++] = "-m";
12479268SJerry.Gilliam@Sun.COM (void) snprintf(maj_num, sizeof (maj_num), "%lu", major_num);
12480Sstevel@tonic-gate cmdline[n++] = maj_num;
1249*10842SJerry.Gilliam@Sun.COM if (config_flags & CONFIG_DRV_UPDATE_ONLY)
1250*10842SJerry.Gilliam@Sun.COM cmdline[n++] = "-x";
12510Sstevel@tonic-gate
12520Sstevel@tonic-gate if (aliases != NULL) {
12530Sstevel@tonic-gate len = strlen(aliases);
12540Sstevel@tonic-gate previous = aliases;
12550Sstevel@tonic-gate do {
12560Sstevel@tonic-gate cmdline[n++] = "-a";
12570Sstevel@tonic-gate cmdline[n] = calloc(len + 1, 1);
12580Sstevel@tonic-gate if (cmdline[n] == NULL) {
12590Sstevel@tonic-gate (void) fprintf(stderr,
12600Sstevel@tonic-gate gettext(ERR_NO_MEM));
12610Sstevel@tonic-gate return (ERROR);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate current = get_entry(previous,
12644145Scth cmdline[n++], ' ', 0);
12650Sstevel@tonic-gate previous = current;
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate } while (*current != '\0');
12680Sstevel@tonic-gate
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate cmdline[n] = (char *)0;
12710Sstevel@tonic-gate
12728831SJerry.Gilliam@Sun.COM rv = exec_command(DRVCONFIG_PATH, cmdline);
12738831SJerry.Gilliam@Sun.COM if (rv == NOERR)
12748831SJerry.Gilliam@Sun.COM return (NOERR);
12758831SJerry.Gilliam@Sun.COM return (ERROR);
12768831SJerry.Gilliam@Sun.COM }
12778831SJerry.Gilliam@Sun.COM
12788831SJerry.Gilliam@Sun.COM int
unconfig_driver(char * driver_name,major_t major_num,char * aliases,int config_flags)12798831SJerry.Gilliam@Sun.COM unconfig_driver(
12808831SJerry.Gilliam@Sun.COM char *driver_name,
12818831SJerry.Gilliam@Sun.COM major_t major_num,
12828831SJerry.Gilliam@Sun.COM char *aliases,
1283*10842SJerry.Gilliam@Sun.COM int config_flags)
12848831SJerry.Gilliam@Sun.COM {
12858831SJerry.Gilliam@Sun.COM return (exec_devfsadm(B_FALSE, driver_name, major_num,
1286*10842SJerry.Gilliam@Sun.COM aliases, NULL, config_flags));
12878831SJerry.Gilliam@Sun.COM }
12880Sstevel@tonic-gate
12898831SJerry.Gilliam@Sun.COM /*
12908831SJerry.Gilliam@Sun.COM * check that major_num doesn't exceed maximum on this machine
12918831SJerry.Gilliam@Sun.COM * do this here to support add_drv on server for diskless clients
12928831SJerry.Gilliam@Sun.COM */
12938831SJerry.Gilliam@Sun.COM int
config_driver(char * driver_name,major_t major_num,char * aliases,char * classes,int cleanup_flag,int config_flags)12948831SJerry.Gilliam@Sun.COM config_driver(
12958831SJerry.Gilliam@Sun.COM char *driver_name,
12968831SJerry.Gilliam@Sun.COM major_t major_num,
12978831SJerry.Gilliam@Sun.COM char *aliases,
12988831SJerry.Gilliam@Sun.COM char *classes,
12998831SJerry.Gilliam@Sun.COM int cleanup_flag,
1300*10842SJerry.Gilliam@Sun.COM int config_flags)
13018831SJerry.Gilliam@Sun.COM {
13028831SJerry.Gilliam@Sun.COM int max_dev;
13038831SJerry.Gilliam@Sun.COM int rv;
13048831SJerry.Gilliam@Sun.COM
13058831SJerry.Gilliam@Sun.COM if (modctl(MODRESERVED, NULL, &max_dev) < 0) {
13068831SJerry.Gilliam@Sun.COM perror(NULL);
13078831SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_MAX_MAJOR));
13088831SJerry.Gilliam@Sun.COM return (ERROR);
13098831SJerry.Gilliam@Sun.COM }
13108831SJerry.Gilliam@Sun.COM
13118831SJerry.Gilliam@Sun.COM if (major_num >= max_dev) {
13128831SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_MAX_EXCEEDS),
13138831SJerry.Gilliam@Sun.COM major_num, max_dev);
13148831SJerry.Gilliam@Sun.COM return (ERROR);
13158831SJerry.Gilliam@Sun.COM }
13168831SJerry.Gilliam@Sun.COM
13178831SJerry.Gilliam@Sun.COM /* bind major number and driver name */
13188831SJerry.Gilliam@Sun.COM rv = exec_devfsadm(B_TRUE, driver_name, major_num,
1319*10842SJerry.Gilliam@Sun.COM aliases, classes, config_flags);
13208831SJerry.Gilliam@Sun.COM
13218831SJerry.Gilliam@Sun.COM if (rv == NOERR)
13220Sstevel@tonic-gate return (NOERR);
13230Sstevel@tonic-gate perror(NULL);
13240Sstevel@tonic-gate remove_entry(cleanup_flag, driver_name);
13250Sstevel@tonic-gate return (ERROR);
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate
13280Sstevel@tonic-gate void
load_driver(char * driver_name,int verbose_flag)13290Sstevel@tonic-gate load_driver(char *driver_name, int verbose_flag)
13300Sstevel@tonic-gate {
13310Sstevel@tonic-gate int n = 0;
13320Sstevel@tonic-gate char *cmdline[MAX_CMD_LINE];
13330Sstevel@tonic-gate int exec_status;
13340Sstevel@tonic-gate
13350Sstevel@tonic-gate /* build command line */
13360Sstevel@tonic-gate cmdline[n++] = DEVFSADM;
13370Sstevel@tonic-gate if (verbose_flag) {
13380Sstevel@tonic-gate cmdline[n++] = "-v";
13390Sstevel@tonic-gate }
13400Sstevel@tonic-gate cmdline[n++] = "-i";
13410Sstevel@tonic-gate cmdline[n++] = driver_name;
13420Sstevel@tonic-gate cmdline[n] = (char *)0;
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate exec_status = exec_command(DEVFSADM_PATH, cmdline);
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate if (exec_status != NOERR) {
13470Sstevel@tonic-gate /* no clean : name and major number are bound */
13488456SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_CONFIG), driver_name);
13490Sstevel@tonic-gate }
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate void
get_modid(char * driver_name,int * mod)13530Sstevel@tonic-gate get_modid(char *driver_name, int *mod)
13540Sstevel@tonic-gate {
13550Sstevel@tonic-gate struct modinfo modinfo;
13560Sstevel@tonic-gate
13570Sstevel@tonic-gate modinfo.mi_id = -1;
13580Sstevel@tonic-gate modinfo.mi_info = MI_INFO_ALL;
13590Sstevel@tonic-gate do {
13600Sstevel@tonic-gate /*
13610Sstevel@tonic-gate * If we are at the end of the list of loaded modules
13620Sstevel@tonic-gate * then set *mod = -1 and return
13630Sstevel@tonic-gate */
13640Sstevel@tonic-gate if (modctl(MODINFO, 0, &modinfo) < 0) {
13650Sstevel@tonic-gate *mod = -1;
13660Sstevel@tonic-gate return;
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate *mod = modinfo.mi_id;
13700Sstevel@tonic-gate } while (strcmp(driver_name, modinfo.mi_name) != 0);
13710Sstevel@tonic-gate }
13720Sstevel@tonic-gate
13730Sstevel@tonic-gate int
create_reconfig(char * basedir)13740Sstevel@tonic-gate create_reconfig(char *basedir)
13750Sstevel@tonic-gate {
13760Sstevel@tonic-gate char reconfig_file[MAXPATHLEN + FILENAME_MAX + 1];
13770Sstevel@tonic-gate FILE *reconfig_fp;
13780Sstevel@tonic-gate
13790Sstevel@tonic-gate if (basedir != NULL) {
13800Sstevel@tonic-gate (void) strcpy(reconfig_file, basedir);
13810Sstevel@tonic-gate (void) strcat(reconfig_file, RECONFIGURE);
13820Sstevel@tonic-gate } else {
13830Sstevel@tonic-gate (void) strcpy(reconfig_file, RECONFIGURE);
13840Sstevel@tonic-gate }
13850Sstevel@tonic-gate if ((reconfig_fp = fopen(reconfig_file, "a")) == NULL)
13860Sstevel@tonic-gate return (ERROR);
13870Sstevel@tonic-gate
13880Sstevel@tonic-gate (void) fclose(reconfig_fp);
13890Sstevel@tonic-gate return (NOERR);
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate /*
13940Sstevel@tonic-gate * update_minor_entry:
13950Sstevel@tonic-gate * open file
13960Sstevel@tonic-gate * for each entry in list
13970Sstevel@tonic-gate * where list entries are separated by <list_separator>
13980Sstevel@tonic-gate * modify entry : driver_name <entry_separator> entry
13990Sstevel@tonic-gate * close file
14000Sstevel@tonic-gate *
14010Sstevel@tonic-gate * return error/noerr
14020Sstevel@tonic-gate */
14030Sstevel@tonic-gate int
update_minor_entry(char * driver_name,char * perm_list)14040Sstevel@tonic-gate update_minor_entry(char *driver_name, char *perm_list)
14050Sstevel@tonic-gate {
140610599SJerry.Gilliam@Sun.COM FILE *fp;
140710599SJerry.Gilliam@Sun.COM FILE *newfp;
140810599SJerry.Gilliam@Sun.COM int match = 0;
140910599SJerry.Gilliam@Sun.COM char line[MAX_DBFILE_ENTRY];
141010599SJerry.Gilliam@Sun.COM char drv[FILENAME_MAX + 1];
141110599SJerry.Gilliam@Sun.COM char minor[FILENAME_MAX + 1];
141210599SJerry.Gilliam@Sun.COM char perm[OPT_LEN + 1];
141310599SJerry.Gilliam@Sun.COM char own[OPT_LEN + 1];
141410599SJerry.Gilliam@Sun.COM char grp[OPT_LEN + 1];
141510599SJerry.Gilliam@Sun.COM int status = NOERR, i;
141610599SJerry.Gilliam@Sun.COM char *newfile, *tptr;
141710599SJerry.Gilliam@Sun.COM char *cp, *dup, *drv_minor;
14180Sstevel@tonic-gate struct group *sysgrp;
14190Sstevel@tonic-gate
14200Sstevel@tonic-gate if ((fp = fopen(minor_perm, "r")) == NULL) {
14210Sstevel@tonic-gate perror(NULL);
14220Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
14230Sstevel@tonic-gate minor_perm);
14240Sstevel@tonic-gate
14250Sstevel@tonic-gate return (ERROR);
14260Sstevel@tonic-gate }
14270Sstevel@tonic-gate
14280Sstevel@tonic-gate /*
14290Sstevel@tonic-gate * Build filename for temporary file
14300Sstevel@tonic-gate */
14310Sstevel@tonic-gate if ((tptr = calloc(strlen(minor_perm) + strlen(XEND) + 1, 1)) == NULL) {
14320Sstevel@tonic-gate perror(NULL);
14330Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
14340Sstevel@tonic-gate }
14350Sstevel@tonic-gate (void) strcpy(tptr, minor_perm);
14360Sstevel@tonic-gate (void) strcat(tptr, XEND);
14370Sstevel@tonic-gate
14380Sstevel@tonic-gate /*
14390Sstevel@tonic-gate * Set gid so we preserve group attribute. Ideally we wouldn't
14400Sstevel@tonic-gate * assume a gid of "sys" but we can't undo the damage on already
14410Sstevel@tonic-gate * installed systems unless we force the issue.
14420Sstevel@tonic-gate */
14430Sstevel@tonic-gate if ((sysgrp = getgrnam("sys")) != NULL) {
14440Sstevel@tonic-gate (void) setgid(sysgrp->gr_gid);
14450Sstevel@tonic-gate }
14460Sstevel@tonic-gate
14470Sstevel@tonic-gate newfile = mktemp(tptr);
14480Sstevel@tonic-gate if ((newfp = fopen(newfile, "w")) == NULL) {
14490Sstevel@tonic-gate perror(NULL);
14500Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
14510Sstevel@tonic-gate newfile);
14520Sstevel@tonic-gate return (ERROR);
14530Sstevel@tonic-gate }
14540Sstevel@tonic-gate
145510599SJerry.Gilliam@Sun.COM if (sscanf(perm_list,
145610599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s" /* minor */
145710599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s" /* perm */
145810599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s" /* own */
145910599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s", /* grp */
146010599SJerry.Gilliam@Sun.COM minor, perm, own, grp) != 4) {
14610Sstevel@tonic-gate status = ERROR;
14620Sstevel@tonic-gate }
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate while ((fgets(line, sizeof (line), fp) != NULL) && status == NOERR) {
14652805Seota /* copy the whole line into dup */
14662805Seota if ((dup = strdup(line)) == NULL) {
14672805Seota perror(NULL);
14682805Seota (void) fprintf(stderr, gettext(ERR_NO_MEM));
14692805Seota status = ERROR;
14702805Seota break;
14712805Seota }
14722805Seota /* cut off comments starting with '#' */
14732805Seota if ((cp = strchr(dup, '#')) != NULL)
14742805Seota *cp = '\0';
14752805Seota /* ignore comment or blank lines */
14762805Seota if (is_blank(dup)) {
14772805Seota if (fputs(line, newfp) == EOF) {
14780Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE),
14790Sstevel@tonic-gate minor_perm);
14800Sstevel@tonic-gate status = ERROR;
14810Sstevel@tonic-gate }
14822805Seota free(dup);
14830Sstevel@tonic-gate continue;
14840Sstevel@tonic-gate }
14850Sstevel@tonic-gate
14862805Seota /* get the driver name */
148710599SJerry.Gilliam@Sun.COM if (sscanf(dup, "%" VAL2STR(FILENAME_MAX) "s", drv) != 1) {
14882805Seota (void) fprintf(stderr, gettext(ERR_BAD_LINE),
14892805Seota minor_perm, line);
14902805Seota status = ERROR;
14912805Seota free(dup);
14922805Seota break;
14932805Seota }
14942805Seota
14952805Seota /*
14962805Seota * get the minor name; place the NULL character at the
14972805Seota * end of the driver name, then make the drv_minor
14982805Seota * point to the first character of the minor name.
14992805Seota * the line missing ':' must be treated as a broken one.
15002805Seota */
15012805Seota i = strcspn(drv, ":");
15022805Seota if (i == strlen(drv)) {
15030Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
15040Sstevel@tonic-gate minor_perm, line);
15050Sstevel@tonic-gate status = ERROR;
15062805Seota free(dup);
15072805Seota break;
15080Sstevel@tonic-gate }
15092805Seota drv[i] = '\0';
15102805Seota drv_minor = &drv[strlen(drv) + 1];
15110Sstevel@tonic-gate
15122805Seota /*
15132805Seota * compare both of the driver name and the minor name.
15142805Seota * then the new line should be written to the file if
15152805Seota * both of them match
15162805Seota */
15170Sstevel@tonic-gate if ((strcmp(drv, driver_name) == 0) &&
15180Sstevel@tonic-gate (strcmp(minor, drv_minor) == 0)) {
15192805Seota /* if it has a comment, keep it */
15202805Seota if (cp != NULL) {
15212805Seota cp++; /* skip a terminator */
15229268SJerry.Gilliam@Sun.COM (void) snprintf(line, sizeof (line),
15239268SJerry.Gilliam@Sun.COM "%s:%s %s %s %s #%s\n",
15242805Seota drv, minor, perm, own, grp, cp);
15252805Seota } else {
15269268SJerry.Gilliam@Sun.COM (void) snprintf(line, sizeof (line),
15279268SJerry.Gilliam@Sun.COM "%s:%s %s %s %s\n",
15282805Seota drv, minor, perm, own, grp);
15292805Seota }
15300Sstevel@tonic-gate match = 1;
15310Sstevel@tonic-gate }
15322805Seota free(dup);
15330Sstevel@tonic-gate
15342805Seota /* update the file */
15350Sstevel@tonic-gate if ((fputs(line, newfp)) == EOF) {
15360Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE),
15370Sstevel@tonic-gate minor_perm);
15380Sstevel@tonic-gate status = ERROR;
15390Sstevel@tonic-gate }
15400Sstevel@tonic-gate }
15410Sstevel@tonic-gate
15420Sstevel@tonic-gate if (!match) {
15430Sstevel@tonic-gate (void) bzero(line, sizeof (&line[0]));
15449268SJerry.Gilliam@Sun.COM (void) snprintf(line, sizeof (line),
15459268SJerry.Gilliam@Sun.COM "%s:%s %s %s %s\n",
15460Sstevel@tonic-gate driver_name, minor, perm, own, grp);
15470Sstevel@tonic-gate
15480Sstevel@tonic-gate /* add the new entry */
15490Sstevel@tonic-gate if ((fputs(line, newfp)) == EOF) {
15500Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), minor_perm);
15510Sstevel@tonic-gate status = ERROR;
15520Sstevel@tonic-gate }
15530Sstevel@tonic-gate }
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate (void) fclose(fp);
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate if (fflush(newfp) != 0 || fsync(fileno(newfp)) != 0)
15580Sstevel@tonic-gate status = ERROR;
15590Sstevel@tonic-gate
15600Sstevel@tonic-gate (void) fclose(newfp);
15610Sstevel@tonic-gate
15620Sstevel@tonic-gate /*
15630Sstevel@tonic-gate * if error, leave original file, delete new file
15640Sstevel@tonic-gate * if noerr, replace original file with new file
15650Sstevel@tonic-gate */
15660Sstevel@tonic-gate if (status == NOERR) {
15670Sstevel@tonic-gate if (rename(minor_perm, tmphold) == -1) {
15680Sstevel@tonic-gate perror(NULL);
15690Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), minor_perm);
15700Sstevel@tonic-gate (void) unlink(newfile);
15710Sstevel@tonic-gate return (ERROR);
15720Sstevel@tonic-gate } else if (rename(newfile, minor_perm) == -1) {
15730Sstevel@tonic-gate perror(NULL);
15740Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), minor_perm);
15750Sstevel@tonic-gate (void) unlink(minor_perm);
15760Sstevel@tonic-gate (void) unlink(newfile);
15770Sstevel@tonic-gate if (link(tmphold, minor_perm) == -1) {
15780Sstevel@tonic-gate perror(NULL);
15790Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINK),
15800Sstevel@tonic-gate minor_perm, tmphold);
15810Sstevel@tonic-gate }
15820Sstevel@tonic-gate return (ERROR);
15830Sstevel@tonic-gate }
15840Sstevel@tonic-gate (void) unlink(tmphold);
15850Sstevel@tonic-gate } else {
15860Sstevel@tonic-gate /*
15870Sstevel@tonic-gate * since there's an error, leave file alone; remove
15880Sstevel@tonic-gate * new file
15890Sstevel@tonic-gate */
15900Sstevel@tonic-gate if (unlink(newfile) == -1) {
15910Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_RM), newfile);
15920Sstevel@tonic-gate }
15930Sstevel@tonic-gate return (ERROR);
15940Sstevel@tonic-gate }
15950Sstevel@tonic-gate
15960Sstevel@tonic-gate return (NOERR);
15970Sstevel@tonic-gate
15980Sstevel@tonic-gate }
15990Sstevel@tonic-gate
16000Sstevel@tonic-gate
16010Sstevel@tonic-gate /*
16020Sstevel@tonic-gate * list_entry:
16030Sstevel@tonic-gate * open file
16040Sstevel@tonic-gate * read thru file, listing all entries if first entry = driver_name
16050Sstevel@tonic-gate * close
16060Sstevel@tonic-gate */
16070Sstevel@tonic-gate void
list_entry(char * oldfile,char * driver_name,char * marker)16080Sstevel@tonic-gate list_entry(
16090Sstevel@tonic-gate char *oldfile,
16100Sstevel@tonic-gate char *driver_name,
16110Sstevel@tonic-gate char *marker)
16120Sstevel@tonic-gate {
16130Sstevel@tonic-gate FILE *fp;
16140Sstevel@tonic-gate int i;
16152805Seota char line[MAX_DBFILE_ENTRY], *cp;
16160Sstevel@tonic-gate char drv[FILENAME_MAX + 1];
16170Sstevel@tonic-gate
16180Sstevel@tonic-gate if ((fp = fopen(oldfile, "r")) == NULL) {
16190Sstevel@tonic-gate perror(NULL);
16200Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), oldfile);
16210Sstevel@tonic-gate
16220Sstevel@tonic-gate return;
16230Sstevel@tonic-gate }
16240Sstevel@tonic-gate
16250Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != NULL) {
16262805Seota /* cut off comments starting with '#' */
16272805Seota if ((cp = strchr(line, '#')) != NULL)
16282805Seota *cp = '\0';
16292805Seota /* ignore comment or blank lines */
16302805Seota if (is_blank(line))
16310Sstevel@tonic-gate continue;
16322805Seota /* sanity-check */
163310599SJerry.Gilliam@Sun.COM if (sscanf(line, "%" VAL2STR(FILENAME_MAX) "s", drv) != 1) {
16340Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
16350Sstevel@tonic-gate oldfile, line);
16360Sstevel@tonic-gate }
16370Sstevel@tonic-gate
16380Sstevel@tonic-gate for (i = strcspn(drv, marker); i < FILENAME_MAX; i++) {
16390Sstevel@tonic-gate drv[i] = '\0';
16400Sstevel@tonic-gate }
16410Sstevel@tonic-gate
16420Sstevel@tonic-gate if (strcmp(driver_name, drv) == 0) {
16430Sstevel@tonic-gate (void) fprintf(stdout, "%s", line);
16440Sstevel@tonic-gate }
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate (void) fclose(fp);
16480Sstevel@tonic-gate }
16490Sstevel@tonic-gate
16502805Seota static boolean_t
is_token(char * tok)16512805Seota is_token(char *tok)
16522805Seota {
16532805Seota /*
16542805Seota * Check the token here. According to IEEE1275 Open Firmware Boot
16552805Seota * Standard, the name is composed of 1 to 31 letters,
16562805Seota * digits and punctuation characters from the set ",._+-", and
16572805Seota * uppercase and lowercase characters are considered distinct.
16582805Seota * (ie. token := [a-zA-Z0-9,._+-]+, length(token) <= 31)
16592805Seota * However, since either the definition of driver or aliase names is
16602805Seota * not known well, only '#' is avoided explicitly. (the kernel lexical
16612805Seota * analyzer treats it as a start of a comment)
16622805Seota */
16632805Seota for (/* nothing */; *tok != '\0'; tok++)
16642805Seota if (*tok == '#' || iscntrl(*tok))
16652805Seota return (B_FALSE);
16662805Seota
16672805Seota return (B_TRUE);
16682805Seota }
16690Sstevel@tonic-gate
16700Sstevel@tonic-gate /*
16710Sstevel@tonic-gate * check each entry in perm_list for:
16720Sstevel@tonic-gate * 4 arguments
16730Sstevel@tonic-gate * permission arg is in valid range
16740Sstevel@tonic-gate * permlist entries separated by comma
16750Sstevel@tonic-gate * return ERROR/NOERR
16760Sstevel@tonic-gate */
16770Sstevel@tonic-gate int
check_perm_opts(char * perm_list)16780Sstevel@tonic-gate check_perm_opts(char *perm_list)
16790Sstevel@tonic-gate {
16800Sstevel@tonic-gate char *current_head;
16810Sstevel@tonic-gate char *previous_head;
16820Sstevel@tonic-gate char *one_entry;
168310599SJerry.Gilliam@Sun.COM int len, scan_stat;
16840Sstevel@tonic-gate char minor[FILENAME_MAX + 1];
16850Sstevel@tonic-gate char perm[OPT_LEN + 1];
16860Sstevel@tonic-gate char own[OPT_LEN + 1];
16870Sstevel@tonic-gate char grp[OPT_LEN + 1];
16880Sstevel@tonic-gate char dumb[OPT_LEN + 1];
16890Sstevel@tonic-gate int status = NOERR;
16900Sstevel@tonic-gate int intperm;
16910Sstevel@tonic-gate
169210599SJerry.Gilliam@Sun.COM if ((len = strlen(perm_list)) == 0)
16930Sstevel@tonic-gate return (ERROR);
16940Sstevel@tonic-gate
169510599SJerry.Gilliam@Sun.COM if ((one_entry = calloc(len + 1, 1)) == NULL) {
16960Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
16970Sstevel@tonic-gate return (ERROR);
16980Sstevel@tonic-gate }
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate previous_head = perm_list;
17010Sstevel@tonic-gate current_head = perm_list;
17020Sstevel@tonic-gate
17030Sstevel@tonic-gate while (*current_head != '\0') {
170410599SJerry.Gilliam@Sun.COM bzero(one_entry, len + 1);
170510599SJerry.Gilliam@Sun.COM current_head = get_perm_entry(previous_head, one_entry);
17060Sstevel@tonic-gate
17070Sstevel@tonic-gate previous_head = current_head;
170810599SJerry.Gilliam@Sun.COM scan_stat = sscanf(one_entry,
170910599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s" /* minor */
171010599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s" /* perm */
171110599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s" /* own */
171210599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s" /* grp */
171310599SJerry.Gilliam@Sun.COM "%" VAL2STR(OPT_LEN) "s", /* dumb */
171410599SJerry.Gilliam@Sun.COM minor, perm, own, grp, dumb);
17150Sstevel@tonic-gate
17160Sstevel@tonic-gate if (scan_stat < 4) {
17170Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MIS_TOK),
17180Sstevel@tonic-gate "-m", one_entry);
17190Sstevel@tonic-gate status = ERROR;
17200Sstevel@tonic-gate }
17210Sstevel@tonic-gate if (scan_stat > 4) {
17220Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_TOO_MANY_ARGS),
17230Sstevel@tonic-gate "-m", one_entry);
17240Sstevel@tonic-gate status = ERROR;
17250Sstevel@tonic-gate }
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate intperm = atoi(perm);
17280Sstevel@tonic-gate if (intperm < 0000 || intperm > 4777) {
17290Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_MODE), perm);
17300Sstevel@tonic-gate status = ERROR;
17310Sstevel@tonic-gate }
17320Sstevel@tonic-gate }
17330Sstevel@tonic-gate
17340Sstevel@tonic-gate free(one_entry);
17350Sstevel@tonic-gate return (status);
17360Sstevel@tonic-gate }
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate
17390Sstevel@tonic-gate /*
17400Sstevel@tonic-gate * check each alias :
17410Sstevel@tonic-gate * alias list members separated by white space
17420Sstevel@tonic-gate * cannot exist as driver name in /etc/name_to_major
17430Sstevel@tonic-gate * cannot exist as driver or alias name in /etc/driver_aliases
17440Sstevel@tonic-gate */
17450Sstevel@tonic-gate int
aliases_unique(char * aliases)17460Sstevel@tonic-gate aliases_unique(char *aliases)
17470Sstevel@tonic-gate {
17480Sstevel@tonic-gate char *current_head;
17490Sstevel@tonic-gate char *previous_head;
17500Sstevel@tonic-gate char *one_entry;
17518831SJerry.Gilliam@Sun.COM int len;
17520Sstevel@tonic-gate int is_unique;
17538831SJerry.Gilliam@Sun.COM int err;
17540Sstevel@tonic-gate
17550Sstevel@tonic-gate len = strlen(aliases);
17560Sstevel@tonic-gate
17570Sstevel@tonic-gate one_entry = calloc(len + 1, 1);
17580Sstevel@tonic-gate if (one_entry == NULL) {
17590Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
17600Sstevel@tonic-gate return (ERROR);
17610Sstevel@tonic-gate }
17620Sstevel@tonic-gate
17630Sstevel@tonic-gate previous_head = aliases;
17640Sstevel@tonic-gate
17650Sstevel@tonic-gate do {
17668831SJerry.Gilliam@Sun.COM bzero(one_entry, len+1);
17674145Scth current_head = get_entry(previous_head, one_entry, ' ', 1);
17680Sstevel@tonic-gate previous_head = current_head;
17690Sstevel@tonic-gate
17700Sstevel@tonic-gate if ((unique_driver_name(one_entry, name_to_major,
17718831SJerry.Gilliam@Sun.COM &is_unique)) == ERROR)
17728831SJerry.Gilliam@Sun.COM goto err_out;
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate if (is_unique != UNIQUE) {
17750Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_ALIAS_IN_NAM_MAJ),
17760Sstevel@tonic-gate one_entry);
17778831SJerry.Gilliam@Sun.COM goto err_out;
17780Sstevel@tonic-gate }
17790Sstevel@tonic-gate
17808831SJerry.Gilliam@Sun.COM if ((err = unique_drv_alias(one_entry)) != UNIQUE) {
17818831SJerry.Gilliam@Sun.COM if (err == NOT_UNIQUE) {
17828831SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
17838831SJerry.Gilliam@Sun.COM gettext(ERR_ALIAS_IN_USE), one_entry);
17848831SJerry.Gilliam@Sun.COM }
17858831SJerry.Gilliam@Sun.COM goto err_out;
17860Sstevel@tonic-gate }
17870Sstevel@tonic-gate
17882805Seota if (!is_token(one_entry)) {
17892805Seota (void) fprintf(stderr, gettext(ERR_BAD_TOK),
17902805Seota "-i", one_entry);
17918831SJerry.Gilliam@Sun.COM goto err_out;
17922805Seota }
17932805Seota
17940Sstevel@tonic-gate } while (*current_head != '\0');
17950Sstevel@tonic-gate
17960Sstevel@tonic-gate free(one_entry);
17970Sstevel@tonic-gate return (NOERR);
17980Sstevel@tonic-gate
17998831SJerry.Gilliam@Sun.COM err_out:
18008831SJerry.Gilliam@Sun.COM free(one_entry);
18018831SJerry.Gilliam@Sun.COM return (ERROR);
18028831SJerry.Gilliam@Sun.COM }
18038831SJerry.Gilliam@Sun.COM
18048831SJerry.Gilliam@Sun.COM /*
18058831SJerry.Gilliam@Sun.COM * verify each alias :
18068831SJerry.Gilliam@Sun.COM * alias list members separated by white space and quoted
18078831SJerry.Gilliam@Sun.COM * exist as alias name in /etc/driver_aliases
18088831SJerry.Gilliam@Sun.COM */
18098831SJerry.Gilliam@Sun.COM int
aliases_exist(char * aliases)18109268SJerry.Gilliam@Sun.COM aliases_exist(char *aliases)
18118831SJerry.Gilliam@Sun.COM {
18128831SJerry.Gilliam@Sun.COM char *current_head;
18138831SJerry.Gilliam@Sun.COM char *previous_head;
18148831SJerry.Gilliam@Sun.COM char *one_entry;
18158831SJerry.Gilliam@Sun.COM int len;
18168831SJerry.Gilliam@Sun.COM
18178831SJerry.Gilliam@Sun.COM len = strlen(aliases);
18188831SJerry.Gilliam@Sun.COM
18198831SJerry.Gilliam@Sun.COM one_entry = calloc(len + 1, 1);
18208831SJerry.Gilliam@Sun.COM if (one_entry == NULL) {
18218831SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_MEM));
18228831SJerry.Gilliam@Sun.COM return (ERROR);
18238831SJerry.Gilliam@Sun.COM }
18248831SJerry.Gilliam@Sun.COM
18258831SJerry.Gilliam@Sun.COM previous_head = aliases;
18268831SJerry.Gilliam@Sun.COM
18278831SJerry.Gilliam@Sun.COM do {
18288831SJerry.Gilliam@Sun.COM bzero(one_entry, len+1);
18298831SJerry.Gilliam@Sun.COM current_head = get_entry(previous_head, one_entry, ' ', 1);
18308831SJerry.Gilliam@Sun.COM previous_head = current_head;
18318831SJerry.Gilliam@Sun.COM
18329268SJerry.Gilliam@Sun.COM if (unique_drv_alias(one_entry) != NOT_UNIQUE)
18338831SJerry.Gilliam@Sun.COM goto err_out;
18348831SJerry.Gilliam@Sun.COM
18358831SJerry.Gilliam@Sun.COM if (!is_token(one_entry)) {
18368831SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_BAD_TOK),
18378831SJerry.Gilliam@Sun.COM "-i", one_entry);
18388831SJerry.Gilliam@Sun.COM goto err_out;
18398831SJerry.Gilliam@Sun.COM }
18408831SJerry.Gilliam@Sun.COM
18418831SJerry.Gilliam@Sun.COM } while (*current_head != '\0');
18428831SJerry.Gilliam@Sun.COM
18438831SJerry.Gilliam@Sun.COM free(one_entry);
18448831SJerry.Gilliam@Sun.COM return (NOERR);
18458831SJerry.Gilliam@Sun.COM
18468831SJerry.Gilliam@Sun.COM err_out:
18478831SJerry.Gilliam@Sun.COM free(one_entry);
18488831SJerry.Gilliam@Sun.COM return (ERROR);
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate
18510Sstevel@tonic-gate
18524145Scth /*
18534145Scth * check each alias :
18544145Scth * if path-oriented alias, path exists
18554145Scth */
18564145Scth int
aliases_paths_exist(char * aliases)18574145Scth aliases_paths_exist(char *aliases)
18584145Scth {
18594145Scth char *current_head;
18604145Scth char *previous_head;
18614145Scth char *one_entry;
18624145Scth int i, len;
18634145Scth char path[MAXPATHLEN];
18644145Scth struct stat buf;
18654145Scth
18664145Scth len = strlen(aliases);
18674145Scth
18684145Scth one_entry = calloc(len + 1, 1);
18694145Scth if (one_entry == NULL) {
18704145Scth (void) fprintf(stderr, gettext(ERR_NO_MEM));
18714145Scth return (ERROR);
18724145Scth }
18734145Scth
18744145Scth previous_head = aliases;
18754145Scth
18764145Scth do {
18774145Scth for (i = 0; i <= len; i++)
18784145Scth one_entry[i] = 0;
18794145Scth
18804145Scth current_head = get_entry(previous_head, one_entry, ' ', 1);
18814145Scth previous_head = current_head;
18824145Scth
18834145Scth /* if the alias is a path, ensure that the path exists */
18844145Scth if (*one_entry != '/')
18854145Scth continue;
18864145Scth (void) snprintf(path, sizeof (path), "/devices/%s", one_entry);
18874145Scth if (stat(path, &buf) == 0)
18884145Scth continue;
18894145Scth
18904145Scth /* no device at specified path-oriented alias path */
18914145Scth (void) fprintf(stderr, gettext(ERR_PATH_ORIENTED_ALIAS),
18924145Scth one_entry);
18934145Scth free(one_entry);
18944145Scth return (ERROR);
18954145Scth
18964145Scth } while (*current_head != '\0');
18974145Scth
18984145Scth free(one_entry);
18994145Scth
19004145Scth return (NOERR);
19014145Scth }
19024145Scth
19034145Scth
19040Sstevel@tonic-gate int
update_driver_aliases(char * driver_name,char * aliases)19050Sstevel@tonic-gate update_driver_aliases(
19060Sstevel@tonic-gate char *driver_name,
19070Sstevel@tonic-gate char *aliases)
19080Sstevel@tonic-gate {
19090Sstevel@tonic-gate /* make call to update the aliases file */
19104145Scth return (append_to_file(driver_name, aliases, driver_aliases,
19114145Scth ' ', " ", 1));
19120Sstevel@tonic-gate }
19130Sstevel@tonic-gate
19140Sstevel@tonic-gate
19158831SJerry.Gilliam@Sun.COM /*
19168831SJerry.Gilliam@Sun.COM * Return:
19178831SJerry.Gilliam@Sun.COM * ERROR in case of memory or read error
19188831SJerry.Gilliam@Sun.COM * UNIQUE if there is no existing match to the supplied alias
19198831SJerry.Gilliam@Sun.COM * NOT_UNIQUE if there is a match
19208831SJerry.Gilliam@Sun.COM * An error message is emitted in the case of ERROR,
19218831SJerry.Gilliam@Sun.COM * up to the caller otherwise.
19228831SJerry.Gilliam@Sun.COM */
19230Sstevel@tonic-gate int
unique_drv_alias(char * drv_alias)19240Sstevel@tonic-gate unique_drv_alias(char *drv_alias)
19250Sstevel@tonic-gate {
19260Sstevel@tonic-gate FILE *fp;
19270Sstevel@tonic-gate char drv[FILENAME_MAX + 1];
19282805Seota char line[MAX_N2M_ALIAS_LINE + 1], *cp;
19290Sstevel@tonic-gate char alias[FILENAME_MAX + 1];
19304145Scth char *a;
19318831SJerry.Gilliam@Sun.COM int status = UNIQUE;
19320Sstevel@tonic-gate
19330Sstevel@tonic-gate fp = fopen(driver_aliases, "r");
19340Sstevel@tonic-gate
19350Sstevel@tonic-gate if (fp != NULL) {
19360Sstevel@tonic-gate while ((fgets(line, sizeof (line), fp) != 0) &&
19378831SJerry.Gilliam@Sun.COM status == UNIQUE) {
19382805Seota /* cut off comments starting with '#' */
19392805Seota if ((cp = strchr(line, '#')) != NULL)
19402805Seota *cp = '\0';
19412805Seota /* ignore comment or blank lines */
19422805Seota if (is_blank(line))
19432805Seota continue;
19442805Seota /* sanity-check */
194510599SJerry.Gilliam@Sun.COM if (sscanf(line,
194610599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s" /* drv */
194710599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s", /* alias */
194810599SJerry.Gilliam@Sun.COM drv, alias) != 2)
19490Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
19500Sstevel@tonic-gate driver_aliases, line);
19510Sstevel@tonic-gate
19524145Scth /* unquote for compare */
19534145Scth if ((*alias == '"') &&
19544145Scth (*(alias + strlen(alias) - 1) == '"')) {
19554145Scth a = &alias[1];
19564145Scth alias[strlen(alias) - 1] = '\0';
19574145Scth } else
19584145Scth a = alias;
19594145Scth
19600Sstevel@tonic-gate if ((strcmp(drv_alias, drv) == 0) ||
19614145Scth (strcmp(drv_alias, a) == 0)) {
19628831SJerry.Gilliam@Sun.COM status = NOT_UNIQUE;
19638831SJerry.Gilliam@Sun.COM break;
19640Sstevel@tonic-gate }
19650Sstevel@tonic-gate }
19660Sstevel@tonic-gate (void) fclose(fp);
19670Sstevel@tonic-gate return (status);
19680Sstevel@tonic-gate } else {
19690Sstevel@tonic-gate perror(NULL);
19700Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_OPEN), driver_aliases);
19710Sstevel@tonic-gate return (ERROR);
19720Sstevel@tonic-gate }
19730Sstevel@tonic-gate }
19740Sstevel@tonic-gate
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate /*
19770Sstevel@tonic-gate * search for driver_name in first field of file file_name
19788831SJerry.Gilliam@Sun.COM * searching name_to_major and driver_aliases: name separated
19798831SJerry.Gilliam@Sun.COM * from the remainder of the line by white space.
19800Sstevel@tonic-gate */
19810Sstevel@tonic-gate int
unique_driver_name(char * driver_name,char * file_name,int * is_unique)19820Sstevel@tonic-gate unique_driver_name(char *driver_name, char *file_name,
19830Sstevel@tonic-gate int *is_unique)
19840Sstevel@tonic-gate {
19858831SJerry.Gilliam@Sun.COM int ret, err;
19860Sstevel@tonic-gate
19870Sstevel@tonic-gate if ((ret = get_major_no(driver_name, file_name)) == ERROR) {
19880Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE),
19890Sstevel@tonic-gate file_name);
19900Sstevel@tonic-gate } else {
19910Sstevel@tonic-gate /* check alias file for name collision */
19928831SJerry.Gilliam@Sun.COM if ((err = unique_drv_alias(driver_name)) != UNIQUE) {
19938831SJerry.Gilliam@Sun.COM if (err == NOT_UNIQUE) {
19948831SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
19958831SJerry.Gilliam@Sun.COM gettext(ERR_ALIAS_IN_USE),
19968831SJerry.Gilliam@Sun.COM driver_name);
19978831SJerry.Gilliam@Sun.COM }
19980Sstevel@tonic-gate ret = ERROR;
19990Sstevel@tonic-gate } else {
20000Sstevel@tonic-gate if (ret != UNIQUE)
20010Sstevel@tonic-gate *is_unique = NOT_UNIQUE;
20020Sstevel@tonic-gate else
20030Sstevel@tonic-gate *is_unique = ret;
20040Sstevel@tonic-gate ret = NOERR;
20050Sstevel@tonic-gate }
20060Sstevel@tonic-gate }
20070Sstevel@tonic-gate return (ret);
20080Sstevel@tonic-gate }
20090Sstevel@tonic-gate
20108331SJerry.Gilliam@Sun.COM /*
20118331SJerry.Gilliam@Sun.COM * returns:
20128331SJerry.Gilliam@Sun.COM * SUCCESS - not an existing driver alias
20138331SJerry.Gilliam@Sun.COM * NOT_UNIQUE - matching driver alias exists
20148331SJerry.Gilliam@Sun.COM * ERROR - an error occurred
20158331SJerry.Gilliam@Sun.COM */
20168331SJerry.Gilliam@Sun.COM int
check_duplicate_driver_alias(char * driver_name,char * drv_alias)20178331SJerry.Gilliam@Sun.COM check_duplicate_driver_alias(char *driver_name, char *drv_alias)
20188331SJerry.Gilliam@Sun.COM {
20198331SJerry.Gilliam@Sun.COM FILE *fp;
20208331SJerry.Gilliam@Sun.COM char drv[FILENAME_MAX + 1];
20218331SJerry.Gilliam@Sun.COM char line[MAX_N2M_ALIAS_LINE + 1], *cp;
20228331SJerry.Gilliam@Sun.COM char alias[FILENAME_MAX + 1];
20238331SJerry.Gilliam@Sun.COM char *a;
20248331SJerry.Gilliam@Sun.COM int status = SUCCESS;
20258331SJerry.Gilliam@Sun.COM
20268331SJerry.Gilliam@Sun.COM if ((fp = fopen(driver_aliases, "r")) == NULL) {
20278331SJerry.Gilliam@Sun.COM perror(NULL);
20288331SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_CANT_OPEN), driver_aliases);
20298331SJerry.Gilliam@Sun.COM return (ERROR);
20308331SJerry.Gilliam@Sun.COM }
20318331SJerry.Gilliam@Sun.COM
20328331SJerry.Gilliam@Sun.COM while (fgets(line, sizeof (line), fp) != 0) {
20338331SJerry.Gilliam@Sun.COM /* cut off comments starting with '#' */
20348331SJerry.Gilliam@Sun.COM if ((cp = strchr(line, '#')) != NULL)
20358331SJerry.Gilliam@Sun.COM *cp = '\0';
20368331SJerry.Gilliam@Sun.COM /* ignore comment or blank lines */
20378331SJerry.Gilliam@Sun.COM if (is_blank(line))
20388331SJerry.Gilliam@Sun.COM continue;
20398331SJerry.Gilliam@Sun.COM /* sanity-check */
204010599SJerry.Gilliam@Sun.COM if (sscanf(line,
204110599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s" /* drv */
204210599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s", /* alias */
204310599SJerry.Gilliam@Sun.COM drv, alias) != 2)
20448331SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_BAD_LINE),
20458331SJerry.Gilliam@Sun.COM driver_aliases, line);
20468331SJerry.Gilliam@Sun.COM
20478331SJerry.Gilliam@Sun.COM /* unquote for compare */
20488331SJerry.Gilliam@Sun.COM if ((*alias == '"') &&
20498331SJerry.Gilliam@Sun.COM (*(alias + strlen(alias) - 1) == '"')) {
20508331SJerry.Gilliam@Sun.COM a = &alias[1];
20518331SJerry.Gilliam@Sun.COM alias[strlen(alias) - 1] = '\0';
20528331SJerry.Gilliam@Sun.COM } else
20538331SJerry.Gilliam@Sun.COM a = alias;
20548331SJerry.Gilliam@Sun.COM
20558331SJerry.Gilliam@Sun.COM if ((strcmp(drv_alias, a) == 0) &&
20568331SJerry.Gilliam@Sun.COM (strcmp(drv, driver_name) == 0)) {
20578331SJerry.Gilliam@Sun.COM status = NOT_UNIQUE;
20588331SJerry.Gilliam@Sun.COM }
20598331SJerry.Gilliam@Sun.COM
20608331SJerry.Gilliam@Sun.COM if ((strcmp(drv_alias, drv) == 0) ||
20618331SJerry.Gilliam@Sun.COM ((strcmp(drv_alias, a) == 0) &&
20628331SJerry.Gilliam@Sun.COM (strcmp(drv, driver_name) != 0))) {
20638331SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
20648331SJerry.Gilliam@Sun.COM gettext(ERR_ALIAS_IN_USE),
20658331SJerry.Gilliam@Sun.COM drv_alias);
20668331SJerry.Gilliam@Sun.COM status = ERROR;
20678331SJerry.Gilliam@Sun.COM goto done;
20688331SJerry.Gilliam@Sun.COM }
20698331SJerry.Gilliam@Sun.COM }
20708331SJerry.Gilliam@Sun.COM
20718331SJerry.Gilliam@Sun.COM done:
20728331SJerry.Gilliam@Sun.COM (void) fclose(fp);
20738331SJerry.Gilliam@Sun.COM return (status);
20748331SJerry.Gilliam@Sun.COM }
20758331SJerry.Gilliam@Sun.COM
20768331SJerry.Gilliam@Sun.COM int
trim_duplicate_aliases(char * driver_name,char * aliases,char ** aliases2p)20778331SJerry.Gilliam@Sun.COM trim_duplicate_aliases(char *driver_name, char *aliases, char **aliases2p)
20788331SJerry.Gilliam@Sun.COM {
20798331SJerry.Gilliam@Sun.COM char *current_head;
20808331SJerry.Gilliam@Sun.COM char *previous_head;
20818331SJerry.Gilliam@Sun.COM char *one_entry;
20828331SJerry.Gilliam@Sun.COM char *aliases2;
20838331SJerry.Gilliam@Sun.COM int rv, len;
20848331SJerry.Gilliam@Sun.COM int n = 0;
20858331SJerry.Gilliam@Sun.COM
20868331SJerry.Gilliam@Sun.COM *aliases2p = NULL;
20878331SJerry.Gilliam@Sun.COM len = strlen(aliases) + 1;
20888331SJerry.Gilliam@Sun.COM
20898331SJerry.Gilliam@Sun.COM one_entry = calloc(len, 1);
20908331SJerry.Gilliam@Sun.COM aliases2 = calloc(len, 1);
20918331SJerry.Gilliam@Sun.COM if (one_entry == NULL || aliases2 == NULL) {
20928331SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_NO_MEM));
20938331SJerry.Gilliam@Sun.COM return (ERROR);
20948331SJerry.Gilliam@Sun.COM }
20958331SJerry.Gilliam@Sun.COM
20968331SJerry.Gilliam@Sun.COM previous_head = aliases;
20978331SJerry.Gilliam@Sun.COM
20988331SJerry.Gilliam@Sun.COM do {
20998331SJerry.Gilliam@Sun.COM (void) bzero(one_entry, len);
21008331SJerry.Gilliam@Sun.COM current_head = get_entry(previous_head, one_entry, ' ', 1);
21018331SJerry.Gilliam@Sun.COM previous_head = current_head;
21028331SJerry.Gilliam@Sun.COM
21038331SJerry.Gilliam@Sun.COM rv = check_duplicate_driver_alias(driver_name, one_entry);
21048331SJerry.Gilliam@Sun.COM switch (rv) {
21058331SJerry.Gilliam@Sun.COM case SUCCESS:
21068331SJerry.Gilliam@Sun.COM /* not an existing driver alias: add it */
21078331SJerry.Gilliam@Sun.COM if (n > 0) {
21088331SJerry.Gilliam@Sun.COM if (strlcat(aliases2, " ", len) >= len)
21098331SJerry.Gilliam@Sun.COM goto err;
21108331SJerry.Gilliam@Sun.COM }
21118331SJerry.Gilliam@Sun.COM if (strlcat(aliases2, one_entry, len) >= len)
21128331SJerry.Gilliam@Sun.COM goto err;
21138331SJerry.Gilliam@Sun.COM n++;
21148331SJerry.Gilliam@Sun.COM break;
21158331SJerry.Gilliam@Sun.COM case NOT_UNIQUE:
21168331SJerry.Gilliam@Sun.COM /* matching driver alias exists: do not add it */
21178331SJerry.Gilliam@Sun.COM break;
21188331SJerry.Gilliam@Sun.COM case ERROR:
21198331SJerry.Gilliam@Sun.COM /* error reading the alias file */
21208331SJerry.Gilliam@Sun.COM goto err;
21218331SJerry.Gilliam@Sun.COM default:
21228331SJerry.Gilliam@Sun.COM goto err;
21238331SJerry.Gilliam@Sun.COM }
21248331SJerry.Gilliam@Sun.COM
21258331SJerry.Gilliam@Sun.COM if (!is_token(one_entry)) {
21268331SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_BAD_TOK),
21278331SJerry.Gilliam@Sun.COM "-i", one_entry);
21288331SJerry.Gilliam@Sun.COM goto err;
21298331SJerry.Gilliam@Sun.COM }
21308331SJerry.Gilliam@Sun.COM } while (*current_head != '\0');
21318331SJerry.Gilliam@Sun.COM
21328331SJerry.Gilliam@Sun.COM /*
21338331SJerry.Gilliam@Sun.COM * If all the aliases listed are already
21348331SJerry.Gilliam@Sun.COM * present we actually have none to do.
21358331SJerry.Gilliam@Sun.COM */
21368331SJerry.Gilliam@Sun.COM if (n == 0) {
21378331SJerry.Gilliam@Sun.COM free(aliases2);
21388331SJerry.Gilliam@Sun.COM } else {
21398331SJerry.Gilliam@Sun.COM *aliases2p = aliases2;
21408331SJerry.Gilliam@Sun.COM }
21418331SJerry.Gilliam@Sun.COM free(one_entry);
21428331SJerry.Gilliam@Sun.COM return (NOERR);
21438331SJerry.Gilliam@Sun.COM
21448331SJerry.Gilliam@Sun.COM err:
21458331SJerry.Gilliam@Sun.COM free(aliases2);
21468331SJerry.Gilliam@Sun.COM free(one_entry);
21478331SJerry.Gilliam@Sun.COM return (ERROR);
21488331SJerry.Gilliam@Sun.COM }
21490Sstevel@tonic-gate
21500Sstevel@tonic-gate int
check_space_within_quote(char * str)21510Sstevel@tonic-gate check_space_within_quote(char *str)
21520Sstevel@tonic-gate {
21530Sstevel@tonic-gate register int i;
21540Sstevel@tonic-gate register int len;
21550Sstevel@tonic-gate int quoted = 0;
21560Sstevel@tonic-gate
21570Sstevel@tonic-gate len = strlen(str);
21580Sstevel@tonic-gate for (i = 0; i < len; i++, str++) {
21590Sstevel@tonic-gate if (*str == '"') {
21600Sstevel@tonic-gate if (quoted == 0)
21610Sstevel@tonic-gate quoted++;
21620Sstevel@tonic-gate else
21630Sstevel@tonic-gate quoted--;
21640Sstevel@tonic-gate } else if (*str == ' ' && quoted)
21650Sstevel@tonic-gate return (ERROR);
21660Sstevel@tonic-gate }
21670Sstevel@tonic-gate
21680Sstevel@tonic-gate return (0);
21690Sstevel@tonic-gate }
21700Sstevel@tonic-gate
21710Sstevel@tonic-gate
21720Sstevel@tonic-gate /*
21730Sstevel@tonic-gate * get major number
21740Sstevel@tonic-gate * write driver_name major_num to name_to_major file
21750Sstevel@tonic-gate * major_num returned in major_num
21760Sstevel@tonic-gate * return success/failure
21770Sstevel@tonic-gate */
21780Sstevel@tonic-gate int
update_name_to_major(char * driver_name,major_t * major_num,int server)21790Sstevel@tonic-gate update_name_to_major(char *driver_name, major_t *major_num, int server)
21800Sstevel@tonic-gate {
21810Sstevel@tonic-gate char major[MAX_STR_MAJOR + 1];
21820Sstevel@tonic-gate struct stat buf;
21830Sstevel@tonic-gate char *num_list;
21840Sstevel@tonic-gate char drv_majnum_str[MAX_STR_MAJOR + 1];
21850Sstevel@tonic-gate int new_maj = -1;
21860Sstevel@tonic-gate int i, tmp = 0, is_unique, have_rem_n2m = 0;
21870Sstevel@tonic-gate int max_dev = 0;
21880Sstevel@tonic-gate
21890Sstevel@tonic-gate /*
21900Sstevel@tonic-gate * if driver_name already in rem_name_to_major
21910Sstevel@tonic-gate * delete entry from rem_nam_to_major
21920Sstevel@tonic-gate * put entry into name_to_major
21930Sstevel@tonic-gate */
21940Sstevel@tonic-gate
21950Sstevel@tonic-gate if (stat(rem_name_to_major, &buf) == 0) {
21960Sstevel@tonic-gate have_rem_n2m = 1;
21970Sstevel@tonic-gate }
21980Sstevel@tonic-gate
21990Sstevel@tonic-gate if (have_rem_n2m) {
22000Sstevel@tonic-gate if ((is_unique = get_major_no(driver_name, rem_name_to_major))
22010Sstevel@tonic-gate == ERROR)
22020Sstevel@tonic-gate return (ERROR);
22030Sstevel@tonic-gate
22040Sstevel@tonic-gate /*
22050Sstevel@tonic-gate * found a match in rem_name_to_major
22060Sstevel@tonic-gate */
22070Sstevel@tonic-gate if (is_unique != UNIQUE) {
22080Sstevel@tonic-gate char scratch[FILENAME_MAX];
22090Sstevel@tonic-gate
22100Sstevel@tonic-gate /*
22110Sstevel@tonic-gate * If there is a match in /etc/rem_name_to_major then
22120Sstevel@tonic-gate * be paranoid: is that major number already in
22130Sstevel@tonic-gate * /etc/name_to_major (potentially under another name)?
22140Sstevel@tonic-gate */
22150Sstevel@tonic-gate if (get_driver_name(is_unique, name_to_major,
22160Sstevel@tonic-gate scratch) != UNIQUE) {
22170Sstevel@tonic-gate /*
22180Sstevel@tonic-gate * nuke the rem_name_to_major entry-- it
22190Sstevel@tonic-gate * isn't helpful.
22200Sstevel@tonic-gate */
22210Sstevel@tonic-gate (void) delete_entry(rem_name_to_major,
22220Sstevel@tonic-gate driver_name, " ", NULL);
22230Sstevel@tonic-gate } else {
22240Sstevel@tonic-gate (void) snprintf(major, sizeof (major),
22250Sstevel@tonic-gate "%d", is_unique);
22260Sstevel@tonic-gate
22270Sstevel@tonic-gate if (append_to_file(driver_name, major,
22284145Scth name_to_major, ' ', " ", 0) == ERROR) {
22290Sstevel@tonic-gate (void) fprintf(stderr,
22300Sstevel@tonic-gate gettext(ERR_NO_UPDATE),
22310Sstevel@tonic-gate name_to_major);
22320Sstevel@tonic-gate return (ERROR);
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate
22350Sstevel@tonic-gate if (delete_entry(rem_name_to_major,
22360Sstevel@tonic-gate driver_name, " ", NULL) == ERROR) {
22370Sstevel@tonic-gate (void) fprintf(stderr,
22380Sstevel@tonic-gate gettext(ERR_DEL_ENTRY), driver_name,
22390Sstevel@tonic-gate rem_name_to_major);
22400Sstevel@tonic-gate return (ERROR);
22410Sstevel@tonic-gate }
22420Sstevel@tonic-gate
22430Sstevel@tonic-gate /* found matching entry : no errors */
22440Sstevel@tonic-gate *major_num = is_unique;
22450Sstevel@tonic-gate return (NOERR);
22460Sstevel@tonic-gate }
22470Sstevel@tonic-gate }
22480Sstevel@tonic-gate }
22490Sstevel@tonic-gate
22500Sstevel@tonic-gate /*
22510Sstevel@tonic-gate * Bugid: 1264079
22520Sstevel@tonic-gate * In a server case (with -b option), we can't use modctl() to find
22530Sstevel@tonic-gate * the maximum major number, we need to dig thru client's
22540Sstevel@tonic-gate * /etc/name_to_major and /etc/rem_name_to_major for the max_dev.
22550Sstevel@tonic-gate *
22560Sstevel@tonic-gate * if (server)
22570Sstevel@tonic-gate * get maximum major number thru (rem_)name_to_major file on client
22580Sstevel@tonic-gate * else
22590Sstevel@tonic-gate * get maximum major number allowable on current system using modctl
22600Sstevel@tonic-gate */
22610Sstevel@tonic-gate if (server) {
22620Sstevel@tonic-gate max_dev = 0;
22630Sstevel@tonic-gate tmp = 0;
22640Sstevel@tonic-gate
22650Sstevel@tonic-gate max_dev = get_max_major(name_to_major);
22660Sstevel@tonic-gate
22670Sstevel@tonic-gate /* If rem_name_to_major exists, we need to check it too */
22680Sstevel@tonic-gate if (have_rem_n2m) {
22690Sstevel@tonic-gate tmp = get_max_major(rem_name_to_major);
22700Sstevel@tonic-gate
22710Sstevel@tonic-gate /*
22720Sstevel@tonic-gate * If name_to_major is missing, we can get max_dev from
22730Sstevel@tonic-gate * /etc/rem_name_to_major. If both missing, bail out!
22740Sstevel@tonic-gate */
22750Sstevel@tonic-gate if ((max_dev == ERROR) && (tmp == ERROR)) {
22760Sstevel@tonic-gate (void) fprintf(stderr,
22778331SJerry.Gilliam@Sun.COM gettext(ERR_CANT_ACCESS_FILE),
22788331SJerry.Gilliam@Sun.COM name_to_major);
22790Sstevel@tonic-gate return (ERROR);
22800Sstevel@tonic-gate }
22810Sstevel@tonic-gate
22820Sstevel@tonic-gate /* guard against bigger maj_num in rem_name_to_major */
22830Sstevel@tonic-gate if (tmp > max_dev)
22840Sstevel@tonic-gate max_dev = tmp;
22850Sstevel@tonic-gate } else {
22860Sstevel@tonic-gate /*
22870Sstevel@tonic-gate * If we can't get major from name_to_major file
22880Sstevel@tonic-gate * and there is no /etc/rem_name_to_major file,
22890Sstevel@tonic-gate * then we don't have a max_dev, bail out quick!
22900Sstevel@tonic-gate */
22910Sstevel@tonic-gate if (max_dev == ERROR)
22920Sstevel@tonic-gate return (ERROR);
22930Sstevel@tonic-gate }
22940Sstevel@tonic-gate
22950Sstevel@tonic-gate /*
22960Sstevel@tonic-gate * In case there is no more slack in current name_to_major
22970Sstevel@tonic-gate * table, provide at least 1 extra entry so the add_drv can
22980Sstevel@tonic-gate * succeed. Since only one add_drv process is allowed at one
22990Sstevel@tonic-gate * time, and hence max_dev will be re-calculated each time
23000Sstevel@tonic-gate * add_drv is ran, we don't need to worry about adding more
23010Sstevel@tonic-gate * than 1 extra slot for max_dev.
23020Sstevel@tonic-gate */
23030Sstevel@tonic-gate max_dev++;
23040Sstevel@tonic-gate
23050Sstevel@tonic-gate } else {
23060Sstevel@tonic-gate if (modctl(MODRESERVED, NULL, &max_dev) < 0) {
23070Sstevel@tonic-gate perror(NULL);
23080Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MAX_MAJOR));
23090Sstevel@tonic-gate return (ERROR);
23100Sstevel@tonic-gate }
23110Sstevel@tonic-gate }
23120Sstevel@tonic-gate
23130Sstevel@tonic-gate /*
23140Sstevel@tonic-gate * max_dev is really how many slots the kernel has allocated for
23150Sstevel@tonic-gate * devices... [0 , maxdev-1], not the largest available device num.
23160Sstevel@tonic-gate */
23170Sstevel@tonic-gate if ((num_list = calloc(max_dev, 1)) == NULL) {
23180Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
23190Sstevel@tonic-gate return (ERROR);
23200Sstevel@tonic-gate }
23210Sstevel@tonic-gate
23220Sstevel@tonic-gate /*
23230Sstevel@tonic-gate * Populate the num_list array
23240Sstevel@tonic-gate */
23250Sstevel@tonic-gate if (fill_n2m_array(name_to_major, &num_list, &max_dev) != 0) {
23260Sstevel@tonic-gate return (ERROR);
23270Sstevel@tonic-gate }
23280Sstevel@tonic-gate if (have_rem_n2m) {
23290Sstevel@tonic-gate if (fill_n2m_array(rem_name_to_major, &num_list, &max_dev) != 0)
23300Sstevel@tonic-gate return (ERROR);
23310Sstevel@tonic-gate }
23320Sstevel@tonic-gate
23330Sstevel@tonic-gate /* find first free major number */
23340Sstevel@tonic-gate for (i = 0; i < max_dev; i++) {
23350Sstevel@tonic-gate if (num_list[i] != 1) {
23360Sstevel@tonic-gate new_maj = i;
23370Sstevel@tonic-gate break;
23380Sstevel@tonic-gate }
23390Sstevel@tonic-gate }
23400Sstevel@tonic-gate
23410Sstevel@tonic-gate if (new_maj == -1) {
23420Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_FREE_MAJOR));
23430Sstevel@tonic-gate return (ERROR);
23440Sstevel@tonic-gate }
23450Sstevel@tonic-gate
23469268SJerry.Gilliam@Sun.COM (void) snprintf(drv_majnum_str, sizeof (drv_majnum_str),
23479268SJerry.Gilliam@Sun.COM "%d", new_maj);
23480Sstevel@tonic-gate if (do_the_update(driver_name, drv_majnum_str) == ERROR) {
23490Sstevel@tonic-gate return (ERROR);
23500Sstevel@tonic-gate }
23510Sstevel@tonic-gate
23520Sstevel@tonic-gate *major_num = new_maj;
23530Sstevel@tonic-gate return (NOERR);
23540Sstevel@tonic-gate }
23550Sstevel@tonic-gate
23560Sstevel@tonic-gate
23570Sstevel@tonic-gate int
fill_n2m_array(char * filename,char ** array,int * nelems)23580Sstevel@tonic-gate fill_n2m_array(char *filename, char **array, int *nelems)
23590Sstevel@tonic-gate {
23600Sstevel@tonic-gate FILE *fp;
23612805Seota char line[MAX_N2M_ALIAS_LINE + 1], *cp;
23620Sstevel@tonic-gate char drv[FILENAME_MAX + 1];
23630Sstevel@tonic-gate u_longlong_t dnum;
23640Sstevel@tonic-gate major_t drv_majnum;
23650Sstevel@tonic-gate
23660Sstevel@tonic-gate /*
23670Sstevel@tonic-gate * Read through the file, marking each major number found
23680Sstevel@tonic-gate * order is not relevant
23690Sstevel@tonic-gate */
23700Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) {
23710Sstevel@tonic-gate perror(NULL);
23720Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), filename);
23730Sstevel@tonic-gate return (ERROR);
23740Sstevel@tonic-gate }
23750Sstevel@tonic-gate
23760Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != 0) {
23772805Seota /* cut off comments starting with '#' */
23782805Seota if ((cp = strchr(line, '#')) != NULL)
23792805Seota *cp = '\0';
23802805Seota /* ignore comment or blank lines */
23812805Seota if (is_blank(line))
23822805Seota continue;
23832805Seota /* sanity-check */
238410599SJerry.Gilliam@Sun.COM if (sscanf(line,
238510599SJerry.Gilliam@Sun.COM "%" VAL2STR(FILENAME_MAX) "s %llu", drv, &dnum) != 2) {
23860Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE),
23870Sstevel@tonic-gate filename, line);
23880Sstevel@tonic-gate (void) fclose(fp);
23890Sstevel@tonic-gate return (ERROR);
23900Sstevel@tonic-gate }
23910Sstevel@tonic-gate
23920Sstevel@tonic-gate if (dnum > L_MAXMAJ32) {
23930Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MAJ_TOOBIG), drv,
23940Sstevel@tonic-gate dnum, filename, L_MAXMAJ32);
23950Sstevel@tonic-gate continue;
23960Sstevel@tonic-gate }
23970Sstevel@tonic-gate /*
23980Sstevel@tonic-gate * cast down to a major_t; we can be sure this is safe because
23990Sstevel@tonic-gate * of the above range-check.
24000Sstevel@tonic-gate */
24010Sstevel@tonic-gate drv_majnum = (major_t)dnum;
24020Sstevel@tonic-gate
24030Sstevel@tonic-gate if (drv_majnum >= *nelems) {
24040Sstevel@tonic-gate /*
24050Sstevel@tonic-gate * Allocate some more space, up to drv_majnum + 1 so
24060Sstevel@tonic-gate * we can accomodate 0 through drv_majnum.
24070Sstevel@tonic-gate *
24080Sstevel@tonic-gate * Note that in the failure case, we leak all of the
24090Sstevel@tonic-gate * old contents of array. It's ok, since we just
24100Sstevel@tonic-gate * wind up exiting immediately anyway.
24110Sstevel@tonic-gate */
24120Sstevel@tonic-gate *nelems = drv_majnum + 1;
24130Sstevel@tonic-gate *array = realloc(*array, *nelems);
24140Sstevel@tonic-gate if (*array == NULL) {
24150Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM));
24160Sstevel@tonic-gate return (ERROR);
24170Sstevel@tonic-gate }
24180Sstevel@tonic-gate }
24190Sstevel@tonic-gate (*array)[drv_majnum] = 1;
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate
24220Sstevel@tonic-gate (void) fclose(fp);
24230Sstevel@tonic-gate return (0);
24240Sstevel@tonic-gate }
24250Sstevel@tonic-gate
24260Sstevel@tonic-gate
24270Sstevel@tonic-gate int
do_the_update(char * driver_name,char * major_number)24280Sstevel@tonic-gate do_the_update(char *driver_name, char *major_number)
24290Sstevel@tonic-gate {
24300Sstevel@tonic-gate return (append_to_file(driver_name, major_number, name_to_major,
24314145Scth ' ', " ", 0));
24320Sstevel@tonic-gate }
24332805Seota
24342805Seota /*
24352805Seota * is_blank() returns 1 (true) if a line specified is composed of
24362805Seota * whitespace characters only. otherwise, it returns 0 (false).
24372805Seota *
24382805Seota * Note. the argument (line) must be null-terminated.
24392805Seota */
24402805Seota static int
is_blank(char * line)24412805Seota is_blank(char *line)
24422805Seota {
24432805Seota for (/* nothing */; *line != '\0'; line++)
24442805Seota if (!isspace(*line))
24452805Seota return (0);
24462805Seota return (1);
24472805Seota }
2448