17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51ca93273Seota * Common Development and Distribution License (the "License"). 61ca93273Seota * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 2288181e00SAlexander Eremin * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 2388181e00SAlexander Eremin * Use is subject to license terms. 2488181e00SAlexander Eremin */ 2588181e00SAlexander Eremin /* 266532b960SJerry Gilliam * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 277c478bd9Sstevel@tonic-gate * Use is subject to license terms. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 321ca93273Seota #include <ctype.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 357c478bd9Sstevel@tonic-gate #include <libintl.h> 367c478bd9Sstevel@tonic-gate #include <wait.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 380013e2d3SJerry Gilliam #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <errno.h> 407c478bd9Sstevel@tonic-gate #include <fcntl.h> 417c478bd9Sstevel@tonic-gate #include <signal.h> 427c478bd9Sstevel@tonic-gate #include <sys/buf.h> 437c478bd9Sstevel@tonic-gate #include <sys/stat.h> 447c478bd9Sstevel@tonic-gate #include <grp.h> 457c478bd9Sstevel@tonic-gate #include "addrem.h" 467c478bd9Sstevel@tonic-gate #include "errmsg.h" 477c478bd9Sstevel@tonic-gate #include "plcysubr.h" 487c478bd9Sstevel@tonic-gate 493c0ea289SJerry Gilliam /* 503c0ea289SJerry Gilliam * Macros to produce a quoted string containing the value of a 513c0ea289SJerry Gilliam * preprocessor macro. For example, if SIZE is defined to be 256, 523c0ea289SJerry Gilliam * VAL2STR(SIZE) is "256". This is used to construct format 533c0ea289SJerry Gilliam * strings for scanf-family functions below. 543c0ea289SJerry Gilliam * Note: For format string use, the argument to VAL2STR() must 553c0ea289SJerry Gilliam * be a numeric constant that is one less than the size of the 563c0ea289SJerry Gilliam * corresponding data buffer. 573c0ea289SJerry Gilliam */ 583c0ea289SJerry Gilliam #define VAL2STR_QUOTE(x) #x 593c0ea289SJerry Gilliam #define VAL2STR(x) VAL2STR_QUOTE(x) 603c0ea289SJerry Gilliam 613c0ea289SJerry Gilliam /* 623c0ea289SJerry Gilliam * Convenience macro to determine if a character is a quote 633c0ea289SJerry Gilliam */ 643c0ea289SJerry Gilliam #define isquote(c) (((c) == '"') || ((c) == '\'')) 653c0ea289SJerry Gilliam 663c0ea289SJerry Gilliam 677c478bd9Sstevel@tonic-gate static char *add_rem_lock; /* lock file */ 6849e92448Svikram static int add_rem_lock_fd = -1; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static int get_cached_n_to_m_file(char *filename, char ***cache); 717c478bd9Sstevel@tonic-gate static int get_name_to_major_entry(int *major_no, char *driver_name, 727c478bd9Sstevel@tonic-gate char *file_name); 737c478bd9Sstevel@tonic-gate 741ca93273Seota static int is_blank(char *); 751ca93273Seota 767c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 777c478bd9Sstevel@tonic-gate void 787c478bd9Sstevel@tonic-gate log_minorperm_error(minorperm_err_t err, int key) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate switch (err) { 817c478bd9Sstevel@tonic-gate case MP_FOPEN_ERR: 827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 837c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 847c478bd9Sstevel@tonic-gate break; 857c478bd9Sstevel@tonic-gate case MP_FCLOSE_ERR: 867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 877c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 897c478bd9Sstevel@tonic-gate break; 907c478bd9Sstevel@tonic-gate case MP_IGNORING_LINE_ERR: 917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 927c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 937c478bd9Sstevel@tonic-gate break; 947c478bd9Sstevel@tonic-gate case MP_ALLOC_ERR: 957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 967c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 987c478bd9Sstevel@tonic-gate break; 997c478bd9Sstevel@tonic-gate case MP_NVLIST_ERR: 1007c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 1017c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 1027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 1037c478bd9Sstevel@tonic-gate break; 1047c478bd9Sstevel@tonic-gate case MP_CANT_FIND_USER_ERR: 1057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 1067c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 1077c478bd9Sstevel@tonic-gate break; 1087c478bd9Sstevel@tonic-gate case MP_CANT_FIND_GROUP_ERR: 1097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 1107c478bd9Sstevel@tonic-gate MINOR_PERM_FILE); 1117c478bd9Sstevel@tonic-gate break; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * open file 1177c478bd9Sstevel@tonic-gate * for each entry in list 1187c478bd9Sstevel@tonic-gate * where list entries are separated by <list_separator> 1197c478bd9Sstevel@tonic-gate * append entry : driver_name <entry_separator> entry 1207c478bd9Sstevel@tonic-gate * close file 1217c478bd9Sstevel@tonic-gate * return error/noerr 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate int 1247c478bd9Sstevel@tonic-gate append_to_file( 1257c478bd9Sstevel@tonic-gate char *driver_name, 1267c478bd9Sstevel@tonic-gate char *entry_list, 1277c478bd9Sstevel@tonic-gate char *filename, 1287c478bd9Sstevel@tonic-gate char list_separator, 129f4da9be0Scth char *entry_separator, 130f4da9be0Scth int quoted) 1317c478bd9Sstevel@tonic-gate { 1323c0ea289SJerry Gilliam int len, line_len; 1337c478bd9Sstevel@tonic-gate int fpint; 1347c478bd9Sstevel@tonic-gate char *current_head, *previous_head; 1357c478bd9Sstevel@tonic-gate char *line, *one_entry; 1367c478bd9Sstevel@tonic-gate FILE *fp; 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if ((fp = fopen(filename, "a")) == NULL) { 1397c478bd9Sstevel@tonic-gate perror(NULL); 1407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 1417c478bd9Sstevel@tonic-gate filename); 1427c478bd9Sstevel@tonic-gate return (ERROR); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate len = strlen(entry_list); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate one_entry = calloc(len + 1, 1); 1487c478bd9Sstevel@tonic-gate if (one_entry == NULL) { 1497c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), filename); 1507c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 1517c478bd9Sstevel@tonic-gate (void) fclose(fp); 1527c478bd9Sstevel@tonic-gate return (ERROR); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate previous_head = entry_list; 1567c478bd9Sstevel@tonic-gate 157f8cb811fSEdward Pilatowicz line_len = strlen(driver_name) + len + 4; 158f8cb811fSEdward Pilatowicz if (quoted) 159f8cb811fSEdward Pilatowicz line_len += 2; 160f8cb811fSEdward Pilatowicz 161f8cb811fSEdward Pilatowicz line = calloc(line_len, 1); 1627c478bd9Sstevel@tonic-gate if (line == NULL) { 1637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 1647c478bd9Sstevel@tonic-gate (void) fclose(fp); 1657c478bd9Sstevel@tonic-gate err_exit(); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* 1697c478bd9Sstevel@tonic-gate * get one entry at a time from list and append to <filename> file 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate do { 1733c0ea289SJerry Gilliam bzero(one_entry, len + 1); 174f8cb811fSEdward Pilatowicz bzero(line, line_len); 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate current_head = get_entry(previous_head, one_entry, 177f4da9be0Scth list_separator, quoted); 1787c478bd9Sstevel@tonic-gate previous_head = current_head; 1797c478bd9Sstevel@tonic-gate 1803c0ea289SJerry Gilliam (void) snprintf(line, line_len, 1813c0ea289SJerry Gilliam quoted ? "%s%s\"%s\"\n" : "%s%s%s\n", 1823c0ea289SJerry Gilliam driver_name, entry_separator, one_entry); 1833c0ea289SJerry Gilliam 1843c0ea289SJerry Gilliam if ((fputs(line, fp)) == EOF) { 1853c0ea289SJerry Gilliam perror(NULL); 1863c0ea289SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 1873c0ea289SJerry Gilliam filename); 1883c0ea289SJerry Gilliam } 1893c0ea289SJerry Gilliam 1903c0ea289SJerry Gilliam } while (*current_head != '\0'); 1913c0ea289SJerry Gilliam 1923c0ea289SJerry Gilliam 1933c0ea289SJerry Gilliam (void) fflush(fp); 1943c0ea289SJerry Gilliam 1953c0ea289SJerry Gilliam fpint = fileno(fp); 1963c0ea289SJerry Gilliam (void) fsync(fpint); 1973c0ea289SJerry Gilliam 1983c0ea289SJerry Gilliam (void) fclose(fp); 1993c0ea289SJerry Gilliam 2003c0ea289SJerry Gilliam free(one_entry); 2013c0ea289SJerry Gilliam free(line); 2023c0ea289SJerry Gilliam 2033c0ea289SJerry Gilliam return (NOERR); 2043c0ea289SJerry Gilliam } 2053c0ea289SJerry Gilliam 2063c0ea289SJerry Gilliam /* 2073c0ea289SJerry Gilliam * open file 2083c0ea289SJerry Gilliam * for each entry in list 2093c0ea289SJerry Gilliam * where list entries are separated by <list_separator> 2103c0ea289SJerry Gilliam * append entry : driver_name <entry_separator> entry 2113c0ea289SJerry Gilliam * close file 2123c0ea289SJerry Gilliam * return error/noerr 2133c0ea289SJerry Gilliam */ 2143c0ea289SJerry Gilliam int 2153c0ea289SJerry Gilliam append_to_minor_perm( 2163c0ea289SJerry Gilliam char *driver_name, 2173c0ea289SJerry Gilliam char *entry_list, 2183c0ea289SJerry Gilliam char *filename) 2193c0ea289SJerry Gilliam { 2203c0ea289SJerry Gilliam int len, line_len; 2213c0ea289SJerry Gilliam int fpint; 2223c0ea289SJerry Gilliam char *current_head, *previous_head; 2233c0ea289SJerry Gilliam char *line, *one_entry; 2243c0ea289SJerry Gilliam FILE *fp; 2253c0ea289SJerry Gilliam 2263c0ea289SJerry Gilliam if ((fp = fopen(filename, "a")) == NULL) { 2273c0ea289SJerry Gilliam perror(NULL); 2283c0ea289SJerry Gilliam (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 2293c0ea289SJerry Gilliam filename); 2303c0ea289SJerry Gilliam return (ERROR); 2313c0ea289SJerry Gilliam } 2323c0ea289SJerry Gilliam 2333c0ea289SJerry Gilliam len = strlen(entry_list); 2343c0ea289SJerry Gilliam 2353c0ea289SJerry Gilliam one_entry = calloc(len + 1, 1); 2363c0ea289SJerry Gilliam if (one_entry == NULL) { 2373c0ea289SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_UPDATE), filename); 2383c0ea289SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_MEM)); 2393c0ea289SJerry Gilliam (void) fclose(fp); 2403c0ea289SJerry Gilliam return (ERROR); 2413c0ea289SJerry Gilliam } 2423c0ea289SJerry Gilliam 2433c0ea289SJerry Gilliam previous_head = entry_list; 2443c0ea289SJerry Gilliam 2453c0ea289SJerry Gilliam line_len = strlen(driver_name) + len + 4; 2463c0ea289SJerry Gilliam line = calloc(line_len, 1); 2473c0ea289SJerry Gilliam if (line == NULL) { 2483c0ea289SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_MEM)); 2493c0ea289SJerry Gilliam (void) fclose(fp); 2503c0ea289SJerry Gilliam err_exit(); 2513c0ea289SJerry Gilliam } 2523c0ea289SJerry Gilliam 2533c0ea289SJerry Gilliam /* 2543c0ea289SJerry Gilliam * get one entry at a time from list and append to <filename> file 2553c0ea289SJerry Gilliam */ 2563c0ea289SJerry Gilliam do { 2573c0ea289SJerry Gilliam bzero(one_entry, len + 1); 2583c0ea289SJerry Gilliam bzero(line, line_len); 2593c0ea289SJerry Gilliam 2603c0ea289SJerry Gilliam current_head = get_perm_entry(previous_head, one_entry); 2613c0ea289SJerry Gilliam previous_head = current_head; 2623c0ea289SJerry Gilliam 2633c0ea289SJerry Gilliam (void) snprintf(line, line_len, "%s:%s\n", 2643c0ea289SJerry Gilliam driver_name, one_entry); 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if ((fputs(line, fp)) == EOF) { 2677c478bd9Sstevel@tonic-gate perror(NULL); 2687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_UPDATE), 2697c478bd9Sstevel@tonic-gate filename); 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate } while (*current_head != '\0'); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate (void) fflush(fp); 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate fpint = fileno(fp); 2787c478bd9Sstevel@tonic-gate (void) fsync(fpint); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate (void) fclose(fp); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate free(one_entry); 2837c478bd9Sstevel@tonic-gate free(line); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate return (NOERR); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 28811ebc2d0SJerry Gilliam /* 28911ebc2d0SJerry Gilliam * Require exact match to delete a driver alias/permission entry. 29011ebc2d0SJerry Gilliam * Note line argument does not remain unchanged. Return 1 if matched. 29111ebc2d0SJerry Gilliam */ 29211ebc2d0SJerry Gilliam static int 29311ebc2d0SJerry Gilliam match_entry(char *line, char *match) 29411ebc2d0SJerry Gilliam { 29511ebc2d0SJerry Gilliam char *token, *p; 29611ebc2d0SJerry Gilliam int n; 29711ebc2d0SJerry Gilliam 29811ebc2d0SJerry Gilliam /* skip any leading white space */ 2993c0ea289SJerry Gilliam while (*line && isspace(*line)) 30011ebc2d0SJerry Gilliam line++; 30111ebc2d0SJerry Gilliam /* 30211ebc2d0SJerry Gilliam * Find separator for driver name, either space or colon 30311ebc2d0SJerry Gilliam * minor_perm: <driver>:<perm> 30411ebc2d0SJerry Gilliam * driver_aliases: <driver> <alias> 30511ebc2d0SJerry Gilliam * extra_privs: <driver>:<priv> 30611ebc2d0SJerry Gilliam */ 30711ebc2d0SJerry Gilliam if ((token = strpbrk(line, " :\t")) == NULL) 30811ebc2d0SJerry Gilliam return (0); 30911ebc2d0SJerry Gilliam token++; 31011ebc2d0SJerry Gilliam /* skip leading white space and quotes */ 3113c0ea289SJerry Gilliam while (*token && (isspace(*token) || isquote(*token))) 31211ebc2d0SJerry Gilliam token++; 31311ebc2d0SJerry Gilliam /* strip trailing newline, white space and quotes */ 31411ebc2d0SJerry Gilliam n = strlen(token); 31511ebc2d0SJerry Gilliam p = token + n-1; 3163c0ea289SJerry Gilliam while (n > 0 && (*p == '\n' || isspace(*p) || isquote(*p))) { 31711ebc2d0SJerry Gilliam *p-- = 0; 31811ebc2d0SJerry Gilliam n--; 31911ebc2d0SJerry Gilliam } 32011ebc2d0SJerry Gilliam if (n == 0) 32111ebc2d0SJerry Gilliam return (0); 32211ebc2d0SJerry Gilliam return (strcmp(token, match) == 0); 32311ebc2d0SJerry Gilliam } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * open file 3277c478bd9Sstevel@tonic-gate * read thru file, deleting all entries if first 3287c478bd9Sstevel@tonic-gate * entry = driver_name 3297c478bd9Sstevel@tonic-gate * close 3307c478bd9Sstevel@tonic-gate * if error, leave original file intact with message 3317c478bd9Sstevel@tonic-gate * assumption : drvconfig has been modified to work with clone 3327c478bd9Sstevel@tonic-gate * entries in /etc/minor_perm as driver:mummble NOT 3337c478bd9Sstevel@tonic-gate * clone:driver mummble 3347c478bd9Sstevel@tonic-gate * this implementation will NOT find clone entries 3357c478bd9Sstevel@tonic-gate * clone:driver mummble 3367c478bd9Sstevel@tonic-gate * match: 3377c478bd9Sstevel@tonic-gate * delete just the matching entry 3387c478bd9Sstevel@tonic-gate * 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate int 3417c478bd9Sstevel@tonic-gate delete_entry( 3427c478bd9Sstevel@tonic-gate char *oldfile, 3437c478bd9Sstevel@tonic-gate char *driver_name, 3447c478bd9Sstevel@tonic-gate char *marker, 3457c478bd9Sstevel@tonic-gate char *match) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate int rv, i; 3487c478bd9Sstevel@tonic-gate int status = NOERR; 3497c478bd9Sstevel@tonic-gate int drvr_found = 0; 3507c478bd9Sstevel@tonic-gate boolean_t nomatch = B_TRUE; 35188181e00SAlexander Eremin char newfile[MAXPATHLEN]; 35288181e00SAlexander Eremin char *cp; 3533c0ea289SJerry Gilliam char line[MAX_DBFILE_ENTRY]; 3543c0ea289SJerry Gilliam char drv[FILENAME_MAX + 1]; 3557c478bd9Sstevel@tonic-gate FILE *fp, *newfp; 3567c478bd9Sstevel@tonic-gate struct group *sysgrp; 35788181e00SAlexander Eremin int newfd; 35811ebc2d0SJerry Gilliam char *copy; /* same size as line */ 3592e107de7SJerry Gilliam char *match2 = NULL; /* match with quotes cleaned up */ 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate /* 3622e107de7SJerry Gilliam * if match is specified, sanity check it and clean it 3632e107de7SJerry Gilliam * up by removing surrounding quotes as we require 3642e107de7SJerry Gilliam * an exact match. 3657c478bd9Sstevel@tonic-gate */ 3662e107de7SJerry Gilliam if (match) { 3672e107de7SJerry Gilliam cp = match; 3683c0ea289SJerry Gilliam while (*cp && (isspace(*cp))) 3692e107de7SJerry Gilliam cp++; 3702e107de7SJerry Gilliam i = strlen(cp); 3712e107de7SJerry Gilliam if (i > 0) { 3722e107de7SJerry Gilliam if ((match2 = strdup(cp)) == NULL) { 3732e107de7SJerry Gilliam perror(NULL); 3742e107de7SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_MEM)); 3757c478bd9Sstevel@tonic-gate return (ERROR); 3767c478bd9Sstevel@tonic-gate } 3773c0ea289SJerry Gilliam i = strlen(match2) - 1; 3783c0ea289SJerry Gilliam while (i >= 0 && (isspace(match2[i]))) { 3793c0ea289SJerry Gilliam match2[i] = 0; 3803c0ea289SJerry Gilliam i--; 3813c0ea289SJerry Gilliam } 3822e107de7SJerry Gilliam } 3832e107de7SJerry Gilliam if (match2 == NULL || (strlen(match2) == 0)) { 3842e107de7SJerry Gilliam (void) fprintf(stderr, 3852e107de7SJerry Gilliam gettext(ERR_INT_UPDATE), oldfile); 3862e107de7SJerry Gilliam return (ERROR); 3872e107de7SJerry Gilliam } 3882e107de7SJerry Gilliam } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if ((fp = fopen(oldfile, "r")) == NULL) { 3917c478bd9Sstevel@tonic-gate perror(NULL); 3927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), oldfile); 3937c478bd9Sstevel@tonic-gate return (ERROR); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 39611ebc2d0SJerry Gilliam /* Space for defensive copy of input line */ 39788181e00SAlexander Eremin if ((copy = calloc(sizeof (line), 1)) == NULL) { 3987c478bd9Sstevel@tonic-gate perror(NULL); 3997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 40011ebc2d0SJerry Gilliam return (ERROR); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 40388181e00SAlexander Eremin /* Build filename for temporary file */ 40488181e00SAlexander Eremin (void) snprintf(newfile, sizeof (newfile), "%s%s", oldfile, ".hold"); 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * Set gid so we preserve group attribute. Ideally we wouldn't 4087c478bd9Sstevel@tonic-gate * assume a gid of "sys" but we can't undo the damage on already 4097c478bd9Sstevel@tonic-gate * installed systems unless we force the issue. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate if ((sysgrp = getgrnam("sys")) != NULL) { 4127c478bd9Sstevel@tonic-gate (void) setgid(sysgrp->gr_gid); 4137c478bd9Sstevel@tonic-gate } 4147c478bd9Sstevel@tonic-gate 41588181e00SAlexander Eremin if ((newfd = open(newfile, O_WRONLY | O_CREAT | O_EXCL, 0644)) < 0) { 41688181e00SAlexander Eremin if (errno == EEXIST) { 41788181e00SAlexander Eremin (void) fprintf(stderr, gettext(ERR_FILE_EXISTS), 41888181e00SAlexander Eremin newfile); 41988181e00SAlexander Eremin return (ERROR); 42088181e00SAlexander Eremin } else { 42188181e00SAlexander Eremin (void) fprintf(stderr, gettext(ERR_CREAT_LOCK), 42288181e00SAlexander Eremin newfile); 42388181e00SAlexander Eremin return (ERROR); 42488181e00SAlexander Eremin } 42588181e00SAlexander Eremin } 4267c478bd9Sstevel@tonic-gate 42788181e00SAlexander Eremin if ((newfp = fdopen(newfd, "w")) == NULL) { 4287c478bd9Sstevel@tonic-gate perror(NULL); 4297c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 4307c478bd9Sstevel@tonic-gate newfile); 43188181e00SAlexander Eremin (void) close(newfd); 4327c478bd9Sstevel@tonic-gate return (ERROR); 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate while ((fgets(line, sizeof (line), fp) != NULL) && status == NOERR) { 43611ebc2d0SJerry Gilliam /* copy the whole line */ 43711ebc2d0SJerry Gilliam if (strlcpy(copy, line, sizeof (line)) >= sizeof (line)) { 43811ebc2d0SJerry Gilliam (void) fprintf(stderr, gettext(ERR_UPDATE), oldfile); 4391ca93273Seota status = ERROR; 4401ca93273Seota break; 4411ca93273Seota } 4421ca93273Seota /* cut off comments starting with '#' */ 44311ebc2d0SJerry Gilliam if ((cp = strchr(copy, '#')) != NULL) 4441ca93273Seota *cp = '\0'; 4451ca93273Seota /* ignore comment or blank lines */ 44611ebc2d0SJerry Gilliam if (is_blank(copy)) { 4471ca93273Seota if (fputs(line, newfp) == EOF) { 4487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), 4497c478bd9Sstevel@tonic-gate oldfile); 4507c478bd9Sstevel@tonic-gate status = ERROR; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate continue; 4537c478bd9Sstevel@tonic-gate } 4541ca93273Seota 4551ca93273Seota /* get the driver name */ 4563c0ea289SJerry Gilliam if (sscanf(copy, "%" VAL2STR(FILENAME_MAX) "s", drv) != 1) { 4577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 4587c478bd9Sstevel@tonic-gate oldfile, line); 4597c478bd9Sstevel@tonic-gate status = ERROR; 4601ca93273Seota break; 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate for (i = strcspn(drv, marker); i < FILENAME_MAX; i++) { 4647c478bd9Sstevel@tonic-gate drv[i] = '\0'; 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (strcmp(driver_name, drv) != 0) { 4687c478bd9Sstevel@tonic-gate if ((fputs(line, newfp)) == EOF) { 4697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), 4707c478bd9Sstevel@tonic-gate oldfile); 4717c478bd9Sstevel@tonic-gate status = ERROR; 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate } else { 4747c478bd9Sstevel@tonic-gate drvr_found++; 4752e107de7SJerry Gilliam if (match2) { /* Just delete one entry */ 4767c478bd9Sstevel@tonic-gate /* for now delete just minor_perm and aliases */ 4777c478bd9Sstevel@tonic-gate if ((strcmp(oldfile, minor_perm) == 0) || 4787c478bd9Sstevel@tonic-gate (strcmp(oldfile, extra_privs) == 0) || 4797c478bd9Sstevel@tonic-gate (strcmp(oldfile, driver_aliases) == 0)) { 48011ebc2d0SJerry Gilliam 48111ebc2d0SJerry Gilliam /* make defensive copy */ 48211ebc2d0SJerry Gilliam if (strlcpy(copy, line, sizeof (line)) 48311ebc2d0SJerry Gilliam >= sizeof (line)) { 48411ebc2d0SJerry Gilliam (void) fprintf(stderr, 48511ebc2d0SJerry Gilliam gettext(ERR_UPDATE), 48611ebc2d0SJerry Gilliam oldfile); 48711ebc2d0SJerry Gilliam status = ERROR; 48811ebc2d0SJerry Gilliam break; 48911ebc2d0SJerry Gilliam } 4902e107de7SJerry Gilliam if (match_entry(copy, match2)) { 4917c478bd9Sstevel@tonic-gate nomatch = B_FALSE; 4927c478bd9Sstevel@tonic-gate } else { 4937c478bd9Sstevel@tonic-gate if ((fputs(line, newfp)) == 4947c478bd9Sstevel@tonic-gate EOF) { 4957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4967c478bd9Sstevel@tonic-gate gettext(ERR_UPDATE), 4977c478bd9Sstevel@tonic-gate oldfile); 4987c478bd9Sstevel@tonic-gate status = ERROR; 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate if (nomatch != B_FALSE) 5017c478bd9Sstevel@tonic-gate nomatch = B_TRUE; 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate } /* end of else */ 5077c478bd9Sstevel@tonic-gate } /* end of while */ 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate (void) fclose(fp); 51011ebc2d0SJerry Gilliam free(copy); 5112e107de7SJerry Gilliam if (match2) 5122e107de7SJerry Gilliam free(match2); 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate /* Make sure that the file is on disk */ 5157c478bd9Sstevel@tonic-gate if (fflush(newfp) != 0 || fsync(fileno(newfp)) != 0) 5167c478bd9Sstevel@tonic-gate status = ERROR; 5177c478bd9Sstevel@tonic-gate else 5187c478bd9Sstevel@tonic-gate rv = NOERR; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate (void) fclose(newfp); 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate /* no matching driver found */ 5237c478bd9Sstevel@tonic-gate rv = NOERR; 5247c478bd9Sstevel@tonic-gate if (!drvr_found || 5257c478bd9Sstevel@tonic-gate (nomatch == B_TRUE)) { 5267c478bd9Sstevel@tonic-gate rv = NONE_FOUND; 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* 5307c478bd9Sstevel@tonic-gate * if error, leave original file, delete new file 5317c478bd9Sstevel@tonic-gate * if noerr, replace original file with new file 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate if (status == NOERR) { 53588181e00SAlexander Eremin if (rename(newfile, oldfile) == -1) { 5367c478bd9Sstevel@tonic-gate perror(NULL); 5377c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), oldfile); 5387c478bd9Sstevel@tonic-gate (void) unlink(newfile); 5397c478bd9Sstevel@tonic-gate return (ERROR); 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate } else { 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * since there's an error, leave file alone; remove 5447c478bd9Sstevel@tonic-gate * new file 5457c478bd9Sstevel@tonic-gate */ 5467c478bd9Sstevel@tonic-gate if (unlink(newfile) == -1) { 5477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_RM), newfile); 5487c478bd9Sstevel@tonic-gate } 5497c478bd9Sstevel@tonic-gate return (ERROR); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate return (rv); 5537c478bd9Sstevel@tonic-gate } 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * wrapper for call to get_name_to_major_entry(): given driver name, 5587c478bd9Sstevel@tonic-gate * retrieve major number. 5597c478bd9Sstevel@tonic-gate */ 5607c478bd9Sstevel@tonic-gate int 5617c478bd9Sstevel@tonic-gate get_major_no(char *driver_name, char *file_name) 5627c478bd9Sstevel@tonic-gate { 5637c478bd9Sstevel@tonic-gate int major = UNIQUE; 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate if (get_name_to_major_entry(&major, driver_name, file_name) == ERROR) 5667c478bd9Sstevel@tonic-gate return (ERROR); 5677c478bd9Sstevel@tonic-gate else 5687c478bd9Sstevel@tonic-gate return (major); 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate 5717c478bd9Sstevel@tonic-gate /* 5727c478bd9Sstevel@tonic-gate * wrapper for call to get_name_to_major_entry(): given major number, 5737c478bd9Sstevel@tonic-gate * retrieve driver name. 5747c478bd9Sstevel@tonic-gate */ 5757c478bd9Sstevel@tonic-gate int 5767c478bd9Sstevel@tonic-gate get_driver_name(int major, char *file_name, char *buf) 5777c478bd9Sstevel@tonic-gate { 5787c478bd9Sstevel@tonic-gate if (major < 0) 5797c478bd9Sstevel@tonic-gate return (ERROR); 5807c478bd9Sstevel@tonic-gate return (get_name_to_major_entry(&major, buf, file_name)); 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* 5857c478bd9Sstevel@tonic-gate * return pointer to cached name_to_major file - reads file into 5867c478bd9Sstevel@tonic-gate * cache if this has not already been done. Since there may be 5877c478bd9Sstevel@tonic-gate * requests for multiple name_to_major files (rem_name_to_major, 5887c478bd9Sstevel@tonic-gate * name_to_major), this routine keeps a list of cached files. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate static int 5917c478bd9Sstevel@tonic-gate get_cached_n_to_m_file(char *filename, char ***cache) 5927c478bd9Sstevel@tonic-gate { 5937c478bd9Sstevel@tonic-gate struct n_to_m_cache { 5947c478bd9Sstevel@tonic-gate char *file; 5957c478bd9Sstevel@tonic-gate char **cached_file; 5967c478bd9Sstevel@tonic-gate int size; 5977c478bd9Sstevel@tonic-gate struct n_to_m_cache *next; 5987c478bd9Sstevel@tonic-gate }; 5997c478bd9Sstevel@tonic-gate static struct n_to_m_cache *head = NULL; 6007c478bd9Sstevel@tonic-gate struct n_to_m_cache *ptr; 6017c478bd9Sstevel@tonic-gate FILE *fp; 6027c478bd9Sstevel@tonic-gate char drv[FILENAME_MAX + 1]; 6037c478bd9Sstevel@tonic-gate char entry[FILENAME_MAX + 1]; 6041ca93273Seota char line[MAX_N2M_ALIAS_LINE], *cp; 6057c478bd9Sstevel@tonic-gate int maj; 6067c478bd9Sstevel@tonic-gate int size = 0; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate 6097c478bd9Sstevel@tonic-gate /* 6107c478bd9Sstevel@tonic-gate * see if the file is already cached - either 6117c478bd9Sstevel@tonic-gate * rem_name_to_major or name_to_major 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate ptr = head; 6147c478bd9Sstevel@tonic-gate while (ptr != NULL) { 6157c478bd9Sstevel@tonic-gate if (strcmp(ptr->file, filename) == 0) 6167c478bd9Sstevel@tonic-gate break; 6177c478bd9Sstevel@tonic-gate ptr = ptr->next; 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate if (ptr == NULL) { /* we need to cache the contents */ 6217c478bd9Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) { 6227c478bd9Sstevel@tonic-gate perror(NULL); 6237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_OPEN), 6247c478bd9Sstevel@tonic-gate filename); 6257c478bd9Sstevel@tonic-gate return (ERROR); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != NULL) { 6291ca93273Seota /* cut off comments starting with '#' */ 6301ca93273Seota if ((cp = strchr(line, '#')) != NULL) 6311ca93273Seota *cp = '\0'; 6321ca93273Seota /* ignore comment or blank lines */ 6331ca93273Seota if (is_blank(line)) 6341ca93273Seota continue; 6351ca93273Seota /* sanity-check */ 6363c0ea289SJerry Gilliam if (sscanf(line, 6373c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s" /* drv */ 6383c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s", /* entry */ 6393c0ea289SJerry Gilliam drv, entry) != 2) { 6407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 6417c478bd9Sstevel@tonic-gate filename, line); 6427c478bd9Sstevel@tonic-gate continue; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate maj = atoi(entry); 6457c478bd9Sstevel@tonic-gate if (maj > size) 6467c478bd9Sstevel@tonic-gate size = maj; 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate /* allocate struct to cache the file */ 6507c478bd9Sstevel@tonic-gate ptr = (struct n_to_m_cache *)calloc(1, 6517c478bd9Sstevel@tonic-gate sizeof (struct n_to_m_cache)); 6527c478bd9Sstevel@tonic-gate if (ptr == NULL) { 6537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 6547c478bd9Sstevel@tonic-gate return (ERROR); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate ptr->size = size + 1; 6577c478bd9Sstevel@tonic-gate /* allocate space to cache contents of file */ 6587c478bd9Sstevel@tonic-gate ptr->cached_file = (char **)calloc(ptr->size, sizeof (char *)); 6597c478bd9Sstevel@tonic-gate if (ptr->cached_file == NULL) { 6607c478bd9Sstevel@tonic-gate free(ptr); 6617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 6627c478bd9Sstevel@tonic-gate return (ERROR); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate rewind(fp); 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate /* 6687c478bd9Sstevel@tonic-gate * now fill the cache 6697c478bd9Sstevel@tonic-gate * the cache is an array of char pointers indexed by major 6707c478bd9Sstevel@tonic-gate * number 6717c478bd9Sstevel@tonic-gate */ 6727c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != NULL) { 6731ca93273Seota /* cut off comments starting with '#' */ 6741ca93273Seota if ((cp = strchr(line, '#')) != NULL) 6751ca93273Seota *cp = '\0'; 6761ca93273Seota /* ignore comment or blank lines */ 6771ca93273Seota if (is_blank(line)) 6781ca93273Seota continue; 6791ca93273Seota /* sanity-check */ 6803c0ea289SJerry Gilliam if (sscanf(line, 6813c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s" /* drv */ 6823c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s", /* entry */ 6833c0ea289SJerry Gilliam drv, entry) != 2) { 6847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 6857c478bd9Sstevel@tonic-gate filename, line); 6867c478bd9Sstevel@tonic-gate continue; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate maj = atoi(entry); 6897c478bd9Sstevel@tonic-gate if ((ptr->cached_file[maj] = strdup(drv)) == NULL) { 6907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 6917c478bd9Sstevel@tonic-gate free(ptr->cached_file); 6927c478bd9Sstevel@tonic-gate free(ptr); 6937c478bd9Sstevel@tonic-gate return (ERROR); 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate (void) strcpy(ptr->cached_file[maj], drv); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate (void) fclose(fp); 6987c478bd9Sstevel@tonic-gate /* link the cache struct into the list of cached files */ 6997c478bd9Sstevel@tonic-gate ptr->file = strdup(filename); 7007c478bd9Sstevel@tonic-gate if (ptr->file == NULL) { 7017c478bd9Sstevel@tonic-gate for (maj = 0; maj <= ptr->size; maj++) 7027c478bd9Sstevel@tonic-gate free(ptr->cached_file[maj]); 7037c478bd9Sstevel@tonic-gate free(ptr->cached_file); 7047c478bd9Sstevel@tonic-gate free(ptr); 7057c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 7067c478bd9Sstevel@tonic-gate return (ERROR); 7077c478bd9Sstevel@tonic-gate } 7087c478bd9Sstevel@tonic-gate ptr->next = head; 7097c478bd9Sstevel@tonic-gate head = ptr; 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate /* return value pointer to contents of file */ 7127c478bd9Sstevel@tonic-gate *cache = ptr->cached_file; 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate /* return size */ 7157c478bd9Sstevel@tonic-gate return (ptr->size); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * Using get_cached_n_to_m_file(), retrieve maximum major number 7217c478bd9Sstevel@tonic-gate * found in the specificed file (name_to_major/rem_name_to_major). 7227c478bd9Sstevel@tonic-gate * 7237c478bd9Sstevel@tonic-gate * The return value is actually the size of the internal cache including 0. 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate int 7267c478bd9Sstevel@tonic-gate get_max_major(char *file_name) 7277c478bd9Sstevel@tonic-gate { 7287c478bd9Sstevel@tonic-gate char **n_to_m_cache = NULL; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate return (get_cached_n_to_m_file(file_name, &n_to_m_cache)); 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate /* 7357c478bd9Sstevel@tonic-gate * searching name_to_major: if major_no == UNIQUE then the caller wants to 7367c478bd9Sstevel@tonic-gate * use the driver name as the key. Otherwise, the caller wants to use 7377c478bd9Sstevel@tonic-gate * the major number as a key. 7387c478bd9Sstevel@tonic-gate * 7397c478bd9Sstevel@tonic-gate * This routine caches the contents of the name_to_major file on 7407c478bd9Sstevel@tonic-gate * first call. And it could be generalized to deal with other 7417c478bd9Sstevel@tonic-gate * config files if necessary. 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate static int 7447c478bd9Sstevel@tonic-gate get_name_to_major_entry(int *major_no, char *driver_name, char *file_name) 7457c478bd9Sstevel@tonic-gate { 7467c478bd9Sstevel@tonic-gate int maj; 7477c478bd9Sstevel@tonic-gate char **n_to_m_cache = NULL; 7487c478bd9Sstevel@tonic-gate int size = 0; 7497c478bd9Sstevel@tonic-gate 7507c478bd9Sstevel@tonic-gate int ret = NOT_UNIQUE; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * read the file in - we cache it in case caller wants to 7547c478bd9Sstevel@tonic-gate * do multiple lookups 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate size = get_cached_n_to_m_file(file_name, &n_to_m_cache); 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate if (size == ERROR) 7597c478bd9Sstevel@tonic-gate return (ERROR); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate /* search with driver name as key */ 7627c478bd9Sstevel@tonic-gate if (*major_no == UNIQUE) { 7637c478bd9Sstevel@tonic-gate for (maj = 0; maj < size; maj++) { 7647c478bd9Sstevel@tonic-gate if ((n_to_m_cache[maj] != NULL) && 7657c478bd9Sstevel@tonic-gate (strcmp(driver_name, n_to_m_cache[maj]) == 0)) { 7667c478bd9Sstevel@tonic-gate *major_no = maj; 7677c478bd9Sstevel@tonic-gate break; 7687c478bd9Sstevel@tonic-gate } 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate if (maj >= size) 7717c478bd9Sstevel@tonic-gate ret = UNIQUE; 7727c478bd9Sstevel@tonic-gate /* search with major number as key */ 7737c478bd9Sstevel@tonic-gate } else { 7747c478bd9Sstevel@tonic-gate /* 7757c478bd9Sstevel@tonic-gate * Bugid 1254588, drvconfig dump core after loading driver 7767c478bd9Sstevel@tonic-gate * with major number bigger than entries defined in 7777c478bd9Sstevel@tonic-gate * /etc/name_to_major. 7787c478bd9Sstevel@tonic-gate */ 7797c478bd9Sstevel@tonic-gate if (*major_no >= size) 7807c478bd9Sstevel@tonic-gate return (UNIQUE); 7817c478bd9Sstevel@tonic-gate 7827c478bd9Sstevel@tonic-gate if (n_to_m_cache[*major_no] != NULL) { 7837c478bd9Sstevel@tonic-gate (void) strcpy(driver_name, n_to_m_cache[*major_no]); 7847c478bd9Sstevel@tonic-gate } else 7857c478bd9Sstevel@tonic-gate ret = UNIQUE; 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate return (ret); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate /* 791f4da9be0Scth * Given pointer to begining of member 'n' in a space (or separator) 792f4da9be0Scth * separated list, return pointer to member 'n+1', and establish member 'n' 793f4da9be0Scth * in *current_entry. If unquote, then we skip a leading quote and treat 794f4da9be0Scth * the trailing quote as a separator (and skip). 7957c478bd9Sstevel@tonic-gate */ 7967c478bd9Sstevel@tonic-gate char * 7977c478bd9Sstevel@tonic-gate get_entry( 7987c478bd9Sstevel@tonic-gate char *prev_member, 7997c478bd9Sstevel@tonic-gate char *current_entry, 800f4da9be0Scth char separator, 801f4da9be0Scth int unquote) 8027c478bd9Sstevel@tonic-gate { 8037c478bd9Sstevel@tonic-gate char *ptr; 804f4da9be0Scth int quoted = 0; 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate ptr = prev_member; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate /* skip white space */ 8093c0ea289SJerry Gilliam while (isspace(*ptr)) 8107c478bd9Sstevel@tonic-gate ptr++; 8117c478bd9Sstevel@tonic-gate 812f4da9be0Scth /* if unquote skip leading quote */ 813f4da9be0Scth if (unquote && *ptr == '"') { 814f4da9be0Scth quoted++; 815f4da9be0Scth ptr++; 816f4da9be0Scth } 817f4da9be0Scth 818f4da9be0Scth /* read thru the current entry looking for end, separator, or unquote */ 819f4da9be0Scth while (*ptr && 8203c0ea289SJerry Gilliam (*ptr != separator) && (!isspace(*ptr)) && 821f4da9be0Scth (!quoted || (*ptr != '"'))) { 8227c478bd9Sstevel@tonic-gate *current_entry++ = *ptr++; 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate *current_entry = '\0'; 8257c478bd9Sstevel@tonic-gate 826f4da9be0Scth if (separator && (*ptr == separator)) 827f4da9be0Scth ptr++; /* skip over separator */ 828f4da9be0Scth if (quoted && (*ptr == '"')) 829f4da9be0Scth ptr++; /* skip over trailing quote */ 8307c478bd9Sstevel@tonic-gate 8317c478bd9Sstevel@tonic-gate /* skip white space */ 8323c0ea289SJerry Gilliam while (isspace(*ptr)) 8337c478bd9Sstevel@tonic-gate ptr++; 8343c0ea289SJerry Gilliam 8353c0ea289SJerry Gilliam return (ptr); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate 8383c0ea289SJerry Gilliam /* 8393c0ea289SJerry Gilliam * A parser specific to the add_drv "-m permission" syntax: 8403c0ea289SJerry Gilliam * 8413c0ea289SJerry Gilliam * -m '<minor-name> <permissions> <owner> <group>', ... 8423c0ea289SJerry Gilliam * 8433c0ea289SJerry Gilliam * One entry is parsed starting at prev_member and returned 8443c0ea289SJerry Gilliam * in the string pointed at by current_entry. A pointer 8453c0ea289SJerry Gilliam * to the entry following is returned. 8463c0ea289SJerry Gilliam */ 8473c0ea289SJerry Gilliam char * 8483c0ea289SJerry Gilliam get_perm_entry( 8493c0ea289SJerry Gilliam char *prev_member, 8503c0ea289SJerry Gilliam char *current_entry) 8513c0ea289SJerry Gilliam { 8523c0ea289SJerry Gilliam char *ptr; 8533c0ea289SJerry Gilliam int nfields = 0; 8543c0ea289SJerry Gilliam int maxfields = 4; /* fields in a permissions format */ 8553c0ea289SJerry Gilliam 8563c0ea289SJerry Gilliam ptr = prev_member; 8573c0ea289SJerry Gilliam while (isspace(*ptr)) 8583c0ea289SJerry Gilliam ptr++; 8593c0ea289SJerry Gilliam 8603c0ea289SJerry Gilliam while (*ptr) { 8613c0ea289SJerry Gilliam /* comma allowed in minor name token only */ 8623c0ea289SJerry Gilliam if (*ptr == ',' && nfields > 0) { 8633c0ea289SJerry Gilliam break; 8643c0ea289SJerry Gilliam } else if (isspace(*ptr)) { 8653c0ea289SJerry Gilliam *current_entry++ = *ptr++; 8663c0ea289SJerry Gilliam while (isspace(*ptr)) 8673c0ea289SJerry Gilliam ptr++; 8683c0ea289SJerry Gilliam if (++nfields == maxfields) 8693c0ea289SJerry Gilliam break; 8703c0ea289SJerry Gilliam } else 8713c0ea289SJerry Gilliam *current_entry++ = *ptr++; 8723c0ea289SJerry Gilliam } 8733c0ea289SJerry Gilliam *current_entry = '\0'; 8743c0ea289SJerry Gilliam 8753c0ea289SJerry Gilliam while (isspace(*ptr)) 8763c0ea289SJerry Gilliam ptr++; 8773c0ea289SJerry Gilliam if (*ptr == ',') { 8783c0ea289SJerry Gilliam ptr++; /* skip over optional trailing comma */ 8793c0ea289SJerry Gilliam } 8803c0ea289SJerry Gilliam while (isspace(*ptr)) 8813c0ea289SJerry Gilliam ptr++; 8823c0ea289SJerry Gilliam 8837c478bd9Sstevel@tonic-gate return (ptr); 8847c478bd9Sstevel@tonic-gate } 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate void 8877c478bd9Sstevel@tonic-gate enter_lock(void) 8887c478bd9Sstevel@tonic-gate { 88949e92448Svikram struct flock lock; 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate /* 8923c0ea289SJerry Gilliam * Attempt to create the lock file. Open the file itself, 8933c0ea289SJerry Gilliam * and not a symlink to some other file. 8947c478bd9Sstevel@tonic-gate */ 8953c0ea289SJerry Gilliam add_rem_lock_fd = open(add_rem_lock, 8963c0ea289SJerry Gilliam O_CREAT|O_RDWR|O_NOFOLLOW|O_NOLINKS, S_IRUSR|S_IWUSR); 89749e92448Svikram if (add_rem_lock_fd < 0) { 89849e92448Svikram (void) fprintf(stderr, gettext(ERR_CREAT_LOCK), 89949e92448Svikram add_rem_lock, strerror(errno)); 90049e92448Svikram exit(1); 90149e92448Svikram } 90249e92448Svikram 90349e92448Svikram lock.l_type = F_WRLCK; 90449e92448Svikram lock.l_whence = SEEK_SET; 90549e92448Svikram lock.l_start = 0; 90649e92448Svikram lock.l_len = 0; 90749e92448Svikram 90849e92448Svikram /* Try for the lock but don't wait. */ 90949e92448Svikram if (fcntl(add_rem_lock_fd, F_SETLK, &lock) == -1) { 91049e92448Svikram if (errno == EACCES || errno == EAGAIN) { 9117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_PROG_IN_USE)); 9127c478bd9Sstevel@tonic-gate } else { 91349e92448Svikram (void) fprintf(stderr, gettext(ERR_LOCK), 91449e92448Svikram add_rem_lock, strerror(errno)); 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate exit(1); 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate void 9217c478bd9Sstevel@tonic-gate err_exit(void) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate /* release memory allocated for moddir */ 9247c478bd9Sstevel@tonic-gate cleanup_moddir(); 9257c478bd9Sstevel@tonic-gate /* remove add_drv/rem_drv lock */ 9267c478bd9Sstevel@tonic-gate exit_unlock(); 9277c478bd9Sstevel@tonic-gate exit(1); 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate void 9317c478bd9Sstevel@tonic-gate cleanup_moddir(void) 9327c478bd9Sstevel@tonic-gate { 9337c478bd9Sstevel@tonic-gate struct drvmod_dir *walk_ptr; 9347c478bd9Sstevel@tonic-gate struct drvmod_dir *free_ptr = moddir; 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate while (free_ptr != NULL) { 9377c478bd9Sstevel@tonic-gate walk_ptr = free_ptr->next; 9387c478bd9Sstevel@tonic-gate free(free_ptr); 9397c478bd9Sstevel@tonic-gate free_ptr = walk_ptr; 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate } 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate void 9447c478bd9Sstevel@tonic-gate exit_unlock(void) 9457c478bd9Sstevel@tonic-gate { 94649e92448Svikram struct flock unlock; 9477c478bd9Sstevel@tonic-gate 94849e92448Svikram if (add_rem_lock_fd < 0) 94949e92448Svikram return; 95049e92448Svikram 95149e92448Svikram unlock.l_type = F_UNLCK; 95249e92448Svikram unlock.l_whence = SEEK_SET; 95349e92448Svikram unlock.l_start = 0; 95449e92448Svikram unlock.l_len = 0; 95549e92448Svikram 95649e92448Svikram if (fcntl(add_rem_lock_fd, F_SETLK, &unlock) == -1) { 95749e92448Svikram (void) fprintf(stderr, gettext(ERR_UNLOCK), 95849e92448Svikram add_rem_lock, strerror(errno)); 95949e92448Svikram } else { 96049e92448Svikram (void) close(add_rem_lock_fd); 96149e92448Svikram add_rem_lock_fd = -1; 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate /* 9667c478bd9Sstevel@tonic-gate * error adding driver; need to back out any changes to files. 9677c478bd9Sstevel@tonic-gate * check flag to see which files need entries removed 9687c478bd9Sstevel@tonic-gate * entry removal based on driver name 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate void 9717c478bd9Sstevel@tonic-gate remove_entry( 9727c478bd9Sstevel@tonic-gate int c_flag, 9737c478bd9Sstevel@tonic-gate char *driver_name) 9747c478bd9Sstevel@tonic-gate { 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate if (c_flag & CLEAN_NAM_MAJ) { 9777c478bd9Sstevel@tonic-gate if (delete_entry(name_to_major, driver_name, " ", 9787c478bd9Sstevel@tonic-gate NULL) == ERROR) { 9797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_CLEAN), 9807c478bd9Sstevel@tonic-gate name_to_major, driver_name); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate if (c_flag & CLEAN_DRV_ALIAS) { 9857c478bd9Sstevel@tonic-gate if (delete_entry(driver_aliases, driver_name, " ", 9867c478bd9Sstevel@tonic-gate NULL) == ERROR) { 9877c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY), 9887c478bd9Sstevel@tonic-gate driver_name, driver_aliases); 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate if (c_flag & CLEAN_DRV_CLASSES) { 9937c478bd9Sstevel@tonic-gate if (delete_entry(driver_classes, driver_name, "\t", NULL) == 9947c478bd9Sstevel@tonic-gate ERROR) { 9957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY), 9967c478bd9Sstevel@tonic-gate driver_name, driver_classes); 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate } 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate if (c_flag & CLEAN_MINOR_PERM) { 10017c478bd9Sstevel@tonic-gate if (delete_entry(minor_perm, driver_name, ":", NULL) == ERROR) { 10027c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY), 10037c478bd9Sstevel@tonic-gate driver_name, minor_perm); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate /* 10077c478bd9Sstevel@tonic-gate * There's no point in removing entries from files that don't 10087c478bd9Sstevel@tonic-gate * exist. Prevent error messages by checking for file existence 10097c478bd9Sstevel@tonic-gate * first. 10107c478bd9Sstevel@tonic-gate */ 10117c478bd9Sstevel@tonic-gate if ((c_flag & CLEAN_DEV_POLICY) != 0 && 10127c478bd9Sstevel@tonic-gate access(device_policy, F_OK) == 0) { 10137c478bd9Sstevel@tonic-gate if (delete_plcy_entry(device_policy, driver_name) == ERROR) { 10147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY), 10157c478bd9Sstevel@tonic-gate driver_name, device_policy); 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate if ((c_flag & CLEAN_DRV_PRIV) != 0 && 10197c478bd9Sstevel@tonic-gate access(extra_privs, F_OK) == 0) { 10207c478bd9Sstevel@tonic-gate if (delete_entry(extra_privs, driver_name, ":", NULL) == 10217c478bd9Sstevel@tonic-gate ERROR) { 10227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DEL_ENTRY), 10237c478bd9Sstevel@tonic-gate driver_name, extra_privs); 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate } 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate int 10297c478bd9Sstevel@tonic-gate check_perms_aliases( 10307c478bd9Sstevel@tonic-gate int m_flag, 10317c478bd9Sstevel@tonic-gate int i_flag) 10327c478bd9Sstevel@tonic-gate { 10337c478bd9Sstevel@tonic-gate /* 10347c478bd9Sstevel@tonic-gate * If neither i_flag nor m_flag are specified no need to check the 10357c478bd9Sstevel@tonic-gate * files for access permissions 10367c478bd9Sstevel@tonic-gate */ 10377c478bd9Sstevel@tonic-gate if (!m_flag && !i_flag) 10387c478bd9Sstevel@tonic-gate return (NOERR); 10397c478bd9Sstevel@tonic-gate 10407c478bd9Sstevel@tonic-gate /* check minor_perm file : exits and is writable */ 10417c478bd9Sstevel@tonic-gate if (m_flag) { 10427c478bd9Sstevel@tonic-gate if (access(minor_perm, R_OK | W_OK)) { 10437c478bd9Sstevel@tonic-gate perror(NULL); 10447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 10457c478bd9Sstevel@tonic-gate minor_perm); 10467c478bd9Sstevel@tonic-gate return (ERROR); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate } 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate /* check driver_aliases file : exits and is writable */ 10517c478bd9Sstevel@tonic-gate if (i_flag) { 10527c478bd9Sstevel@tonic-gate if (access(driver_aliases, R_OK | W_OK)) { 10537c478bd9Sstevel@tonic-gate perror(NULL); 10547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 10557c478bd9Sstevel@tonic-gate driver_aliases); 10567c478bd9Sstevel@tonic-gate return (ERROR); 10577c478bd9Sstevel@tonic-gate } 10587c478bd9Sstevel@tonic-gate } 10597c478bd9Sstevel@tonic-gate 10607c478bd9Sstevel@tonic-gate return (NOERR); 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate int 10657c478bd9Sstevel@tonic-gate check_name_to_major(int mode) 10667c478bd9Sstevel@tonic-gate { 10677c478bd9Sstevel@tonic-gate /* check name_to_major file : exists and is writable */ 10687c478bd9Sstevel@tonic-gate if (access(name_to_major, mode)) { 10697c478bd9Sstevel@tonic-gate perror(NULL); 10707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 10717c478bd9Sstevel@tonic-gate name_to_major); 10727c478bd9Sstevel@tonic-gate return (ERROR); 10737c478bd9Sstevel@tonic-gate } 10747c478bd9Sstevel@tonic-gate 10757c478bd9Sstevel@tonic-gate return (NOERR); 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* 10807c478bd9Sstevel@tonic-gate * All this stuff is to support a server installing 10817c478bd9Sstevel@tonic-gate * drivers on diskless clients. When on the server 10827c478bd9Sstevel@tonic-gate * need to prepend the basedir 10837c478bd9Sstevel@tonic-gate */ 10847c478bd9Sstevel@tonic-gate int 10857c478bd9Sstevel@tonic-gate build_filenames(char *basedir) 10867c478bd9Sstevel@tonic-gate { 10877c478bd9Sstevel@tonic-gate int len; 10882e107de7SJerry Gilliam int driver_aliases_len; 10892e107de7SJerry Gilliam int driver_classes_len; 10902e107de7SJerry Gilliam int minor_perm_len; 10912e107de7SJerry Gilliam int name_to_major_len; 10922e107de7SJerry Gilliam int rem_name_to_major_len; 10932e107de7SJerry Gilliam int add_rem_lock_len; 10942e107de7SJerry Gilliam int devfs_root_len; 10952e107de7SJerry Gilliam int device_policy_len; 10962e107de7SJerry Gilliam int extra_privs_len; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate if (basedir == NULL) { 10997c478bd9Sstevel@tonic-gate driver_aliases = DRIVER_ALIAS; 11007c478bd9Sstevel@tonic-gate driver_classes = DRIVER_CLASSES; 11017c478bd9Sstevel@tonic-gate minor_perm = MINOR_PERM; 11027c478bd9Sstevel@tonic-gate name_to_major = NAM_TO_MAJ; 11037c478bd9Sstevel@tonic-gate rem_name_to_major = REM_NAM_TO_MAJ; 11047c478bd9Sstevel@tonic-gate add_rem_lock = ADD_REM_LOCK; 11057c478bd9Sstevel@tonic-gate devfs_root = DEVFS_ROOT; 11067c478bd9Sstevel@tonic-gate device_policy = DEV_POLICY; 11077c478bd9Sstevel@tonic-gate extra_privs = EXTRA_PRIVS; 11087c478bd9Sstevel@tonic-gate 11097c478bd9Sstevel@tonic-gate } else { 11102e107de7SJerry Gilliam len = strlen(basedir) + 1; 11117c478bd9Sstevel@tonic-gate 11122e107de7SJerry Gilliam driver_aliases_len = len + sizeof (DRIVER_ALIAS); 11132e107de7SJerry Gilliam driver_classes_len = len + sizeof (DRIVER_CLASSES); 11142e107de7SJerry Gilliam minor_perm_len = len + sizeof (MINOR_PERM); 11152e107de7SJerry Gilliam name_to_major_len = len + sizeof (NAM_TO_MAJ); 11162e107de7SJerry Gilliam rem_name_to_major_len = len + sizeof (REM_NAM_TO_MAJ); 11172e107de7SJerry Gilliam add_rem_lock_len = len + sizeof (ADD_REM_LOCK); 11182e107de7SJerry Gilliam devfs_root_len = len + sizeof (DEVFS_ROOT); 11192e107de7SJerry Gilliam device_policy_len = len + sizeof (DEV_POLICY); 11202e107de7SJerry Gilliam extra_privs_len = len + sizeof (EXTRA_PRIVS); 11217c478bd9Sstevel@tonic-gate 11222e107de7SJerry Gilliam driver_aliases = malloc(driver_aliases_len); 11232e107de7SJerry Gilliam driver_classes = malloc(driver_classes_len); 11242e107de7SJerry Gilliam minor_perm = malloc(minor_perm_len); 11252e107de7SJerry Gilliam name_to_major = malloc(name_to_major_len); 11262e107de7SJerry Gilliam rem_name_to_major = malloc(rem_name_to_major_len); 11272e107de7SJerry Gilliam add_rem_lock = malloc(add_rem_lock_len); 11282e107de7SJerry Gilliam devfs_root = malloc(devfs_root_len); 11292e107de7SJerry Gilliam device_policy = malloc(device_policy_len); 11302e107de7SJerry Gilliam extra_privs = malloc(extra_privs_len); 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate if ((driver_aliases == NULL) || 11337c478bd9Sstevel@tonic-gate (driver_classes == NULL) || 11347c478bd9Sstevel@tonic-gate (minor_perm == NULL) || 11357c478bd9Sstevel@tonic-gate (name_to_major == NULL) || 11367c478bd9Sstevel@tonic-gate (rem_name_to_major == NULL) || 11377c478bd9Sstevel@tonic-gate (add_rem_lock == NULL) || 11387c478bd9Sstevel@tonic-gate (devfs_root == NULL) || 11397c478bd9Sstevel@tonic-gate (device_policy == NULL) || 11407c478bd9Sstevel@tonic-gate (extra_privs == NULL)) { 11417c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 11427c478bd9Sstevel@tonic-gate return (ERROR); 11437c478bd9Sstevel@tonic-gate } 11447c478bd9Sstevel@tonic-gate 11452e107de7SJerry Gilliam (void) snprintf(driver_aliases, driver_aliases_len, 11462e107de7SJerry Gilliam "%s%s", basedir, DRIVER_ALIAS); 11472e107de7SJerry Gilliam (void) snprintf(driver_classes, driver_classes_len, 11482e107de7SJerry Gilliam "%s%s", basedir, DRIVER_CLASSES); 11492e107de7SJerry Gilliam (void) snprintf(minor_perm, minor_perm_len, 11502e107de7SJerry Gilliam "%s%s", basedir, MINOR_PERM); 11512e107de7SJerry Gilliam (void) snprintf(name_to_major, name_to_major_len, 11522e107de7SJerry Gilliam "%s%s", basedir, NAM_TO_MAJ); 11532e107de7SJerry Gilliam (void) snprintf(rem_name_to_major, rem_name_to_major_len, 11542e107de7SJerry Gilliam "%s%s", basedir, REM_NAM_TO_MAJ); 11552e107de7SJerry Gilliam (void) snprintf(add_rem_lock, add_rem_lock_len, 11562e107de7SJerry Gilliam "%s%s", basedir, ADD_REM_LOCK); 11572e107de7SJerry Gilliam (void) snprintf(devfs_root, devfs_root_len, 11582e107de7SJerry Gilliam "%s%s", basedir, DEVFS_ROOT); 11592e107de7SJerry Gilliam (void) snprintf(device_policy, device_policy_len, 11602e107de7SJerry Gilliam "%s%s", basedir, DEV_POLICY); 11612e107de7SJerry Gilliam (void) snprintf(extra_privs, extra_privs_len, 11622e107de7SJerry Gilliam "%s%s", basedir, EXTRA_PRIVS); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate return (NOERR); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate static int 11697c478bd9Sstevel@tonic-gate exec_command(char *path, char *cmdline[MAX_CMD_LINE]) 11707c478bd9Sstevel@tonic-gate { 11717c478bd9Sstevel@tonic-gate pid_t pid; 11727c478bd9Sstevel@tonic-gate uint_t stat_loc; 11737c478bd9Sstevel@tonic-gate int waitstat; 11747c478bd9Sstevel@tonic-gate int exit_status; 11757c478bd9Sstevel@tonic-gate 11767c478bd9Sstevel@tonic-gate /* child */ 11777c478bd9Sstevel@tonic-gate if ((pid = fork()) == 0) { 11787c478bd9Sstevel@tonic-gate (void) execv(path, cmdline); 11797c478bd9Sstevel@tonic-gate perror(NULL); 11807c478bd9Sstevel@tonic-gate return (ERROR); 11817c478bd9Sstevel@tonic-gate } else if (pid == -1) { 11827c478bd9Sstevel@tonic-gate /* fork failed */ 11837c478bd9Sstevel@tonic-gate perror(NULL); 11847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_FORK_FAIL), cmdline); 11857c478bd9Sstevel@tonic-gate return (ERROR); 11867c478bd9Sstevel@tonic-gate } else { 11877c478bd9Sstevel@tonic-gate /* parent */ 11887c478bd9Sstevel@tonic-gate do { 11897c478bd9Sstevel@tonic-gate waitstat = waitpid(pid, (int *)&stat_loc, 0); 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate } while ((!WIFEXITED(stat_loc) && 11927c478bd9Sstevel@tonic-gate !WIFSIGNALED(stat_loc)) || (waitstat == 0)); 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate exit_status = WEXITSTATUS(stat_loc); 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate return (exit_status); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate /* 12016532b960SJerry Gilliam * Exec devfsadm to perform driver config/unconfig operation, 12026532b960SJerry Gilliam * adding or removing aliases. 12037c478bd9Sstevel@tonic-gate */ 12046532b960SJerry Gilliam static int 12056532b960SJerry Gilliam exec_devfsadm( 12066532b960SJerry Gilliam boolean_t config, 12077c478bd9Sstevel@tonic-gate char *driver_name, 12087c478bd9Sstevel@tonic-gate major_t major_num, 12097c478bd9Sstevel@tonic-gate char *aliases, 12107c478bd9Sstevel@tonic-gate char *classes, 1211c9cc1492SJerry Gilliam int config_flags) 12127c478bd9Sstevel@tonic-gate { 12137c478bd9Sstevel@tonic-gate int n = 0; 12147c478bd9Sstevel@tonic-gate char *cmdline[MAX_CMD_LINE]; 12157c478bd9Sstevel@tonic-gate char maj_num[128]; 12167c478bd9Sstevel@tonic-gate char *previous; 12177c478bd9Sstevel@tonic-gate char *current; 12187c478bd9Sstevel@tonic-gate int len; 12196532b960SJerry Gilliam int rv; 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* build command line */ 12227c478bd9Sstevel@tonic-gate cmdline[n++] = DRVCONFIG; 12236532b960SJerry Gilliam if (config == B_FALSE) { 12246532b960SJerry Gilliam cmdline[n++] = "-u"; /* unconfigure */ 1225c9cc1492SJerry Gilliam if (config_flags & CONFIG_DRV_FORCE) 12266532b960SJerry Gilliam cmdline[n++] = "-f"; /* force if currently in use */ 12276532b960SJerry Gilliam } 1228c9cc1492SJerry Gilliam if (config_flags & CONFIG_DRV_VERBOSE) { 12297c478bd9Sstevel@tonic-gate cmdline[n++] = "-v"; 12307c478bd9Sstevel@tonic-gate } 12317c478bd9Sstevel@tonic-gate cmdline[n++] = "-b"; 12327c478bd9Sstevel@tonic-gate if (classes) { 12337c478bd9Sstevel@tonic-gate cmdline[n++] = "-c"; 12347c478bd9Sstevel@tonic-gate cmdline[n++] = classes; 12357c478bd9Sstevel@tonic-gate } 12367c478bd9Sstevel@tonic-gate cmdline[n++] = "-i"; 12377c478bd9Sstevel@tonic-gate cmdline[n++] = driver_name; 12387c478bd9Sstevel@tonic-gate cmdline[n++] = "-m"; 12392e107de7SJerry Gilliam (void) snprintf(maj_num, sizeof (maj_num), "%lu", major_num); 12407c478bd9Sstevel@tonic-gate cmdline[n++] = maj_num; 1241c9cc1492SJerry Gilliam if (config_flags & CONFIG_DRV_UPDATE_ONLY) 1242c9cc1492SJerry Gilliam cmdline[n++] = "-x"; 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate if (aliases != NULL) { 12457c478bd9Sstevel@tonic-gate len = strlen(aliases); 12467c478bd9Sstevel@tonic-gate previous = aliases; 12477c478bd9Sstevel@tonic-gate do { 12487c478bd9Sstevel@tonic-gate cmdline[n++] = "-a"; 12497c478bd9Sstevel@tonic-gate cmdline[n] = calloc(len + 1, 1); 12507c478bd9Sstevel@tonic-gate if (cmdline[n] == NULL) { 12517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 12527c478bd9Sstevel@tonic-gate gettext(ERR_NO_MEM)); 12537c478bd9Sstevel@tonic-gate return (ERROR); 12547c478bd9Sstevel@tonic-gate } 12557c478bd9Sstevel@tonic-gate current = get_entry(previous, 1256f4da9be0Scth cmdline[n++], ' ', 0); 12577c478bd9Sstevel@tonic-gate previous = current; 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate } while (*current != '\0'); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate } 12627c478bd9Sstevel@tonic-gate cmdline[n] = (char *)0; 12637c478bd9Sstevel@tonic-gate 12646532b960SJerry Gilliam rv = exec_command(DRVCONFIG_PATH, cmdline); 12656532b960SJerry Gilliam if (rv == NOERR) 12666532b960SJerry Gilliam return (NOERR); 12676532b960SJerry Gilliam return (ERROR); 12686532b960SJerry Gilliam } 12697c478bd9Sstevel@tonic-gate 12706532b960SJerry Gilliam int 12716532b960SJerry Gilliam unconfig_driver( 12726532b960SJerry Gilliam char *driver_name, 12736532b960SJerry Gilliam major_t major_num, 12746532b960SJerry Gilliam char *aliases, 1275c9cc1492SJerry Gilliam int config_flags) 12766532b960SJerry Gilliam { 12776532b960SJerry Gilliam return (exec_devfsadm(B_FALSE, driver_name, major_num, 1278c9cc1492SJerry Gilliam aliases, NULL, config_flags)); 12796532b960SJerry Gilliam } 12806532b960SJerry Gilliam 12816532b960SJerry Gilliam /* 12826532b960SJerry Gilliam * check that major_num doesn't exceed maximum on this machine 12836532b960SJerry Gilliam * do this here to support add_drv on server for diskless clients 12846532b960SJerry Gilliam */ 12856532b960SJerry Gilliam int 12866532b960SJerry Gilliam config_driver( 12876532b960SJerry Gilliam char *driver_name, 12886532b960SJerry Gilliam major_t major_num, 12896532b960SJerry Gilliam char *aliases, 12906532b960SJerry Gilliam char *classes, 12916532b960SJerry Gilliam int cleanup_flag, 1292c9cc1492SJerry Gilliam int config_flags) 12936532b960SJerry Gilliam { 12946532b960SJerry Gilliam int max_dev; 12956532b960SJerry Gilliam int rv; 12966532b960SJerry Gilliam 12976532b960SJerry Gilliam if (modctl(MODRESERVED, NULL, &max_dev) < 0) { 12986532b960SJerry Gilliam perror(NULL); 12996532b960SJerry Gilliam (void) fprintf(stderr, gettext(ERR_MAX_MAJOR)); 13006532b960SJerry Gilliam return (ERROR); 13016532b960SJerry Gilliam } 13026532b960SJerry Gilliam 13036532b960SJerry Gilliam if (major_num >= max_dev) { 13046532b960SJerry Gilliam (void) fprintf(stderr, gettext(ERR_MAX_EXCEEDS), 13056532b960SJerry Gilliam major_num, max_dev); 13066532b960SJerry Gilliam return (ERROR); 13076532b960SJerry Gilliam } 13086532b960SJerry Gilliam 13096532b960SJerry Gilliam /* bind major number and driver name */ 13106532b960SJerry Gilliam rv = exec_devfsadm(B_TRUE, driver_name, major_num, 1311c9cc1492SJerry Gilliam aliases, classes, config_flags); 13126532b960SJerry Gilliam 13136532b960SJerry Gilliam if (rv == NOERR) 13147c478bd9Sstevel@tonic-gate return (NOERR); 13157c478bd9Sstevel@tonic-gate perror(NULL); 13167c478bd9Sstevel@tonic-gate remove_entry(cleanup_flag, driver_name); 13177c478bd9Sstevel@tonic-gate return (ERROR); 13187c478bd9Sstevel@tonic-gate } 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate void 13217c478bd9Sstevel@tonic-gate load_driver(char *driver_name, int verbose_flag) 13227c478bd9Sstevel@tonic-gate { 13237c478bd9Sstevel@tonic-gate int n = 0; 13247c478bd9Sstevel@tonic-gate char *cmdline[MAX_CMD_LINE]; 13257c478bd9Sstevel@tonic-gate int exec_status; 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate /* build command line */ 13287c478bd9Sstevel@tonic-gate cmdline[n++] = DEVFSADM; 13297c478bd9Sstevel@tonic-gate if (verbose_flag) { 13307c478bd9Sstevel@tonic-gate cmdline[n++] = "-v"; 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate cmdline[n++] = "-i"; 13337c478bd9Sstevel@tonic-gate cmdline[n++] = driver_name; 13347c478bd9Sstevel@tonic-gate cmdline[n] = (char *)0; 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate exec_status = exec_command(DEVFSADM_PATH, cmdline); 13377c478bd9Sstevel@tonic-gate 13387c478bd9Sstevel@tonic-gate if (exec_status != NOERR) { 13397c478bd9Sstevel@tonic-gate /* no clean : name and major number are bound */ 134011ebc2d0SJerry Gilliam (void) fprintf(stderr, gettext(ERR_CONFIG), driver_name); 13417c478bd9Sstevel@tonic-gate } 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate void 13457c478bd9Sstevel@tonic-gate get_modid(char *driver_name, int *mod) 13467c478bd9Sstevel@tonic-gate { 13477c478bd9Sstevel@tonic-gate struct modinfo modinfo; 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate modinfo.mi_id = -1; 13507c478bd9Sstevel@tonic-gate modinfo.mi_info = MI_INFO_ALL; 13517c478bd9Sstevel@tonic-gate do { 13527c478bd9Sstevel@tonic-gate /* 13537c478bd9Sstevel@tonic-gate * If we are at the end of the list of loaded modules 13547c478bd9Sstevel@tonic-gate * then set *mod = -1 and return 13557c478bd9Sstevel@tonic-gate */ 13567c478bd9Sstevel@tonic-gate if (modctl(MODINFO, 0, &modinfo) < 0) { 13577c478bd9Sstevel@tonic-gate *mod = -1; 13587c478bd9Sstevel@tonic-gate return; 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate 13617c478bd9Sstevel@tonic-gate *mod = modinfo.mi_id; 13627c478bd9Sstevel@tonic-gate } while (strcmp(driver_name, modinfo.mi_name) != 0); 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate int 13667c478bd9Sstevel@tonic-gate create_reconfig(char *basedir) 13677c478bd9Sstevel@tonic-gate { 13687c478bd9Sstevel@tonic-gate char reconfig_file[MAXPATHLEN + FILENAME_MAX + 1]; 13697c478bd9Sstevel@tonic-gate FILE *reconfig_fp; 13707c478bd9Sstevel@tonic-gate 13717c478bd9Sstevel@tonic-gate if (basedir != NULL) { 13727c478bd9Sstevel@tonic-gate (void) strcpy(reconfig_file, basedir); 13737c478bd9Sstevel@tonic-gate (void) strcat(reconfig_file, RECONFIGURE); 13747c478bd9Sstevel@tonic-gate } else { 13757c478bd9Sstevel@tonic-gate (void) strcpy(reconfig_file, RECONFIGURE); 13767c478bd9Sstevel@tonic-gate } 13777c478bd9Sstevel@tonic-gate if ((reconfig_fp = fopen(reconfig_file, "a")) == NULL) 13787c478bd9Sstevel@tonic-gate return (ERROR); 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate (void) fclose(reconfig_fp); 13817c478bd9Sstevel@tonic-gate return (NOERR); 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate /* 13867c478bd9Sstevel@tonic-gate * update_minor_entry: 13877c478bd9Sstevel@tonic-gate * open file 13887c478bd9Sstevel@tonic-gate * for each entry in list 13897c478bd9Sstevel@tonic-gate * where list entries are separated by <list_separator> 13907c478bd9Sstevel@tonic-gate * modify entry : driver_name <entry_separator> entry 13917c478bd9Sstevel@tonic-gate * close file 13927c478bd9Sstevel@tonic-gate * 13937c478bd9Sstevel@tonic-gate * return error/noerr 13947c478bd9Sstevel@tonic-gate */ 13957c478bd9Sstevel@tonic-gate int 13967c478bd9Sstevel@tonic-gate update_minor_entry(char *driver_name, char *perm_list) 13977c478bd9Sstevel@tonic-gate { 13987c478bd9Sstevel@tonic-gate FILE *fp; 13997c478bd9Sstevel@tonic-gate FILE *newfp; 14007c478bd9Sstevel@tonic-gate int match = 0; 14013c0ea289SJerry Gilliam char line[MAX_DBFILE_ENTRY]; 14023c0ea289SJerry Gilliam char drv[FILENAME_MAX + 1]; 14033c0ea289SJerry Gilliam char minor[FILENAME_MAX + 1]; 14043c0ea289SJerry Gilliam char perm[OPT_LEN + 1]; 14053c0ea289SJerry Gilliam char own[OPT_LEN + 1]; 14063c0ea289SJerry Gilliam char grp[OPT_LEN + 1]; 14077c478bd9Sstevel@tonic-gate int status = NOERR, i; 140888181e00SAlexander Eremin char newfile[MAXPATHLEN]; 14093c0ea289SJerry Gilliam char *cp, *dup, *drv_minor; 14103c0ea289SJerry Gilliam struct group *sysgrp; 141188181e00SAlexander Eremin int newfd; 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate if ((fp = fopen(minor_perm, "r")) == NULL) { 14147c478bd9Sstevel@tonic-gate perror(NULL); 14157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 14167c478bd9Sstevel@tonic-gate minor_perm); 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate return (ERROR); 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate 142188181e00SAlexander Eremin /* Build filename for temporary file */ 142288181e00SAlexander Eremin (void) snprintf(newfile, sizeof (newfile), "%s%s", minor_perm, ".hold"); 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate /* 14257c478bd9Sstevel@tonic-gate * Set gid so we preserve group attribute. Ideally we wouldn't 14267c478bd9Sstevel@tonic-gate * assume a gid of "sys" but we can't undo the damage on already 14277c478bd9Sstevel@tonic-gate * installed systems unless we force the issue. 14287c478bd9Sstevel@tonic-gate */ 14297c478bd9Sstevel@tonic-gate if ((sysgrp = getgrnam("sys")) != NULL) { 14307c478bd9Sstevel@tonic-gate (void) setgid(sysgrp->gr_gid); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate 143388181e00SAlexander Eremin if ((newfd = open(newfile, O_WRONLY | O_CREAT | O_EXCL, 0644)) < 0) { 143488181e00SAlexander Eremin if (errno == EEXIST) { 143588181e00SAlexander Eremin (void) fprintf(stderr, gettext(ERR_FILE_EXISTS), 143688181e00SAlexander Eremin newfile); 143788181e00SAlexander Eremin return (ERROR); 143888181e00SAlexander Eremin } else { 143988181e00SAlexander Eremin (void) fprintf(stderr, gettext(ERR_CREAT_LOCK), 144088181e00SAlexander Eremin newfile); 144188181e00SAlexander Eremin return (ERROR); 144288181e00SAlexander Eremin } 144388181e00SAlexander Eremin } 144488181e00SAlexander Eremin 144588181e00SAlexander Eremin if ((newfp = fdopen(newfd, "w")) == NULL) { 14467c478bd9Sstevel@tonic-gate perror(NULL); 14477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 14487c478bd9Sstevel@tonic-gate newfile); 144988181e00SAlexander Eremin (void) close(newfd); 14507c478bd9Sstevel@tonic-gate return (ERROR); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14533c0ea289SJerry Gilliam if (sscanf(perm_list, 14543c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s" /* minor */ 14553c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s" /* perm */ 14563c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s" /* own */ 14573c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s", /* grp */ 14583c0ea289SJerry Gilliam minor, perm, own, grp) != 4) { 14597c478bd9Sstevel@tonic-gate status = ERROR; 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate while ((fgets(line, sizeof (line), fp) != NULL) && status == NOERR) { 14631ca93273Seota /* copy the whole line into dup */ 14641ca93273Seota if ((dup = strdup(line)) == NULL) { 14651ca93273Seota perror(NULL); 14661ca93273Seota (void) fprintf(stderr, gettext(ERR_NO_MEM)); 14671ca93273Seota status = ERROR; 14681ca93273Seota break; 14691ca93273Seota } 14701ca93273Seota /* cut off comments starting with '#' */ 14711ca93273Seota if ((cp = strchr(dup, '#')) != NULL) 14721ca93273Seota *cp = '\0'; 14731ca93273Seota /* ignore comment or blank lines */ 14741ca93273Seota if (is_blank(dup)) { 14751ca93273Seota if (fputs(line, newfp) == EOF) { 14767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), 14777c478bd9Sstevel@tonic-gate minor_perm); 14787c478bd9Sstevel@tonic-gate status = ERROR; 14797c478bd9Sstevel@tonic-gate } 14801ca93273Seota free(dup); 14817c478bd9Sstevel@tonic-gate continue; 14827c478bd9Sstevel@tonic-gate } 14837c478bd9Sstevel@tonic-gate 14841ca93273Seota /* get the driver name */ 14853c0ea289SJerry Gilliam if (sscanf(dup, "%" VAL2STR(FILENAME_MAX) "s", drv) != 1) { 14867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 14877c478bd9Sstevel@tonic-gate minor_perm, line); 14887c478bd9Sstevel@tonic-gate status = ERROR; 14891ca93273Seota free(dup); 14901ca93273Seota break; 14917c478bd9Sstevel@tonic-gate } 14921ca93273Seota 14931ca93273Seota /* 14941ca93273Seota * get the minor name; place the NULL character at the 14951ca93273Seota * end of the driver name, then make the drv_minor 14961ca93273Seota * point to the first character of the minor name. 14971ca93273Seota * the line missing ':' must be treated as a broken one. 14981ca93273Seota */ 14991ca93273Seota i = strcspn(drv, ":"); 15001ca93273Seota if (i == strlen(drv)) { 15011ca93273Seota (void) fprintf(stderr, gettext(ERR_BAD_LINE), 15021ca93273Seota minor_perm, line); 15031ca93273Seota status = ERROR; 15041ca93273Seota free(dup); 15051ca93273Seota break; 15061ca93273Seota } 15077c478bd9Sstevel@tonic-gate drv[i] = '\0'; 15081ca93273Seota drv_minor = &drv[strlen(drv) + 1]; 15097c478bd9Sstevel@tonic-gate 15101ca93273Seota /* 15111ca93273Seota * compare both of the driver name and the minor name. 15121ca93273Seota * then the new line should be written to the file if 15131ca93273Seota * both of them match 15141ca93273Seota */ 15157c478bd9Sstevel@tonic-gate if ((strcmp(drv, driver_name) == 0) && 15167c478bd9Sstevel@tonic-gate (strcmp(minor, drv_minor) == 0)) { 15171ca93273Seota /* if it has a comment, keep it */ 15181ca93273Seota if (cp != NULL) { 15191ca93273Seota cp++; /* skip a terminator */ 15202e107de7SJerry Gilliam (void) snprintf(line, sizeof (line), 15212e107de7SJerry Gilliam "%s:%s %s %s %s #%s\n", 15221ca93273Seota drv, minor, perm, own, grp, cp); 15231ca93273Seota } else { 15242e107de7SJerry Gilliam (void) snprintf(line, sizeof (line), 15252e107de7SJerry Gilliam "%s:%s %s %s %s\n", 15267c478bd9Sstevel@tonic-gate drv, minor, perm, own, grp); 15271ca93273Seota } 15287c478bd9Sstevel@tonic-gate match = 1; 15297c478bd9Sstevel@tonic-gate } 15301ca93273Seota free(dup); 15317c478bd9Sstevel@tonic-gate 15321ca93273Seota /* update the file */ 15337c478bd9Sstevel@tonic-gate if ((fputs(line, newfp)) == EOF) { 15347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), 15357c478bd9Sstevel@tonic-gate minor_perm); 15367c478bd9Sstevel@tonic-gate status = ERROR; 15377c478bd9Sstevel@tonic-gate } 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate if (!match) { 15417c478bd9Sstevel@tonic-gate (void) bzero(line, sizeof (&line[0])); 15422e107de7SJerry Gilliam (void) snprintf(line, sizeof (line), 15432e107de7SJerry Gilliam "%s:%s %s %s %s\n", 15447c478bd9Sstevel@tonic-gate driver_name, minor, perm, own, grp); 15457c478bd9Sstevel@tonic-gate 15467c478bd9Sstevel@tonic-gate /* add the new entry */ 15477c478bd9Sstevel@tonic-gate if ((fputs(line, newfp)) == EOF) { 15487c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), minor_perm); 15497c478bd9Sstevel@tonic-gate status = ERROR; 15507c478bd9Sstevel@tonic-gate } 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate 15537c478bd9Sstevel@tonic-gate (void) fclose(fp); 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate if (fflush(newfp) != 0 || fsync(fileno(newfp)) != 0) 15567c478bd9Sstevel@tonic-gate status = ERROR; 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate (void) fclose(newfp); 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate /* 15617c478bd9Sstevel@tonic-gate * if error, leave original file, delete new file 15627c478bd9Sstevel@tonic-gate * if noerr, replace original file with new file 15637c478bd9Sstevel@tonic-gate */ 15647c478bd9Sstevel@tonic-gate if (status == NOERR) { 156588181e00SAlexander Eremin if (rename(newfile, minor_perm) == -1) { 15667c478bd9Sstevel@tonic-gate perror(NULL); 15677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_UPDATE), minor_perm); 15687c478bd9Sstevel@tonic-gate (void) unlink(newfile); 15697c478bd9Sstevel@tonic-gate return (ERROR); 15707c478bd9Sstevel@tonic-gate } 15717c478bd9Sstevel@tonic-gate } else { 15727c478bd9Sstevel@tonic-gate /* 15737c478bd9Sstevel@tonic-gate * since there's an error, leave file alone; remove 15747c478bd9Sstevel@tonic-gate * new file 15757c478bd9Sstevel@tonic-gate */ 15767c478bd9Sstevel@tonic-gate if (unlink(newfile) == -1) { 15777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_RM), newfile); 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate return (ERROR); 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate return (NOERR); 15837c478bd9Sstevel@tonic-gate 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate 15877c478bd9Sstevel@tonic-gate /* 15887c478bd9Sstevel@tonic-gate * list_entry: 15897c478bd9Sstevel@tonic-gate * open file 15907c478bd9Sstevel@tonic-gate * read thru file, listing all entries if first entry = driver_name 15917c478bd9Sstevel@tonic-gate * close 15927c478bd9Sstevel@tonic-gate */ 15937c478bd9Sstevel@tonic-gate void 15947c478bd9Sstevel@tonic-gate list_entry( 15957c478bd9Sstevel@tonic-gate char *oldfile, 15967c478bd9Sstevel@tonic-gate char *driver_name, 15977c478bd9Sstevel@tonic-gate char *marker) 15987c478bd9Sstevel@tonic-gate { 15997c478bd9Sstevel@tonic-gate FILE *fp; 16007c478bd9Sstevel@tonic-gate int i; 16011ca93273Seota char line[MAX_DBFILE_ENTRY], *cp; 16027c478bd9Sstevel@tonic-gate char drv[FILENAME_MAX + 1]; 16037c478bd9Sstevel@tonic-gate 16047c478bd9Sstevel@tonic-gate if ((fp = fopen(oldfile, "r")) == NULL) { 16057c478bd9Sstevel@tonic-gate perror(NULL); 16067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), oldfile); 16077c478bd9Sstevel@tonic-gate 16087c478bd9Sstevel@tonic-gate return; 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != NULL) { 16121ca93273Seota /* cut off comments starting with '#' */ 16131ca93273Seota if ((cp = strchr(line, '#')) != NULL) 16141ca93273Seota *cp = '\0'; 16151ca93273Seota /* ignore comment or blank lines */ 16161ca93273Seota if (is_blank(line)) 16177c478bd9Sstevel@tonic-gate continue; 16181ca93273Seota /* sanity-check */ 16193c0ea289SJerry Gilliam if (sscanf(line, "%" VAL2STR(FILENAME_MAX) "s", drv) != 1) { 16207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 16217c478bd9Sstevel@tonic-gate oldfile, line); 16227c478bd9Sstevel@tonic-gate } 16237c478bd9Sstevel@tonic-gate 16247c478bd9Sstevel@tonic-gate for (i = strcspn(drv, marker); i < FILENAME_MAX; i++) { 16257c478bd9Sstevel@tonic-gate drv[i] = '\0'; 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate if (strcmp(driver_name, drv) == 0) { 16297c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%s", line); 16307c478bd9Sstevel@tonic-gate } 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate (void) fclose(fp); 16347c478bd9Sstevel@tonic-gate } 16357c478bd9Sstevel@tonic-gate 16361ca93273Seota static boolean_t 16371ca93273Seota is_token(char *tok) 16381ca93273Seota { 16391ca93273Seota /* 16401ca93273Seota * Check the token here. According to IEEE1275 Open Firmware Boot 16411ca93273Seota * Standard, the name is composed of 1 to 31 letters, 16421ca93273Seota * digits and punctuation characters from the set ",._+-", and 16431ca93273Seota * uppercase and lowercase characters are considered distinct. 16441ca93273Seota * (ie. token := [a-zA-Z0-9,._+-]+, length(token) <= 31) 16451ca93273Seota * However, since either the definition of driver or aliase names is 16461ca93273Seota * not known well, only '#' is avoided explicitly. (the kernel lexical 16471ca93273Seota * analyzer treats it as a start of a comment) 16481ca93273Seota */ 16491ca93273Seota for (/* nothing */; *tok != '\0'; tok++) 16501ca93273Seota if (*tok == '#' || iscntrl(*tok)) 16511ca93273Seota return (B_FALSE); 16521ca93273Seota 16531ca93273Seota return (B_TRUE); 16541ca93273Seota } 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* 16577c478bd9Sstevel@tonic-gate * check each entry in perm_list for: 16587c478bd9Sstevel@tonic-gate * 4 arguments 16597c478bd9Sstevel@tonic-gate * permission arg is in valid range 16607c478bd9Sstevel@tonic-gate * permlist entries separated by comma 16617c478bd9Sstevel@tonic-gate * return ERROR/NOERR 16627c478bd9Sstevel@tonic-gate */ 16637c478bd9Sstevel@tonic-gate int 16647c478bd9Sstevel@tonic-gate check_perm_opts(char *perm_list) 16657c478bd9Sstevel@tonic-gate { 16667c478bd9Sstevel@tonic-gate char *current_head; 16677c478bd9Sstevel@tonic-gate char *previous_head; 16687c478bd9Sstevel@tonic-gate char *one_entry; 16693c0ea289SJerry Gilliam int len, scan_stat; 16707c478bd9Sstevel@tonic-gate char minor[FILENAME_MAX + 1]; 16717c478bd9Sstevel@tonic-gate char perm[OPT_LEN + 1]; 16727c478bd9Sstevel@tonic-gate char own[OPT_LEN + 1]; 16737c478bd9Sstevel@tonic-gate char grp[OPT_LEN + 1]; 16747c478bd9Sstevel@tonic-gate char dumb[OPT_LEN + 1]; 16757c478bd9Sstevel@tonic-gate int status = NOERR; 16767c478bd9Sstevel@tonic-gate int intperm; 16777c478bd9Sstevel@tonic-gate 16783c0ea289SJerry Gilliam if ((len = strlen(perm_list)) == 0) 16797c478bd9Sstevel@tonic-gate return (ERROR); 16807c478bd9Sstevel@tonic-gate 16813c0ea289SJerry Gilliam if ((one_entry = calloc(len + 1, 1)) == NULL) { 16827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 16837c478bd9Sstevel@tonic-gate return (ERROR); 16847c478bd9Sstevel@tonic-gate } 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate previous_head = perm_list; 16877c478bd9Sstevel@tonic-gate current_head = perm_list; 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate while (*current_head != '\0') { 16903c0ea289SJerry Gilliam bzero(one_entry, len + 1); 16913c0ea289SJerry Gilliam current_head = get_perm_entry(previous_head, one_entry); 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate previous_head = current_head; 16943c0ea289SJerry Gilliam scan_stat = sscanf(one_entry, 16953c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s" /* minor */ 16963c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s" /* perm */ 16973c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s" /* own */ 16983c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s" /* grp */ 16993c0ea289SJerry Gilliam "%" VAL2STR(OPT_LEN) "s", /* dumb */ 17003c0ea289SJerry Gilliam minor, perm, own, grp, dumb); 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate if (scan_stat < 4) { 17037c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MIS_TOK), 17047c478bd9Sstevel@tonic-gate "-m", one_entry); 17057c478bd9Sstevel@tonic-gate status = ERROR; 17067c478bd9Sstevel@tonic-gate } 17077c478bd9Sstevel@tonic-gate if (scan_stat > 4) { 17087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_TOO_MANY_ARGS), 17097c478bd9Sstevel@tonic-gate "-m", one_entry); 17107c478bd9Sstevel@tonic-gate status = ERROR; 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate intperm = atoi(perm); 17147c478bd9Sstevel@tonic-gate if (intperm < 0000 || intperm > 4777) { 17157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_MODE), perm); 17167c478bd9Sstevel@tonic-gate status = ERROR; 17177c478bd9Sstevel@tonic-gate } 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate 17207c478bd9Sstevel@tonic-gate free(one_entry); 17217c478bd9Sstevel@tonic-gate return (status); 17227c478bd9Sstevel@tonic-gate } 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate 17257c478bd9Sstevel@tonic-gate /* 17267c478bd9Sstevel@tonic-gate * check each alias : 17277c478bd9Sstevel@tonic-gate * alias list members separated by white space 17287c478bd9Sstevel@tonic-gate * cannot exist as driver name in /etc/name_to_major 17297c478bd9Sstevel@tonic-gate * cannot exist as driver or alias name in /etc/driver_aliases 17307c478bd9Sstevel@tonic-gate */ 17317c478bd9Sstevel@tonic-gate int 17327c478bd9Sstevel@tonic-gate aliases_unique(char *aliases) 17337c478bd9Sstevel@tonic-gate { 17347c478bd9Sstevel@tonic-gate char *current_head; 17357c478bd9Sstevel@tonic-gate char *previous_head; 17367c478bd9Sstevel@tonic-gate char *one_entry; 17376532b960SJerry Gilliam int len; 17387c478bd9Sstevel@tonic-gate int is_unique; 17396532b960SJerry Gilliam int err; 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate len = strlen(aliases); 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate one_entry = calloc(len + 1, 1); 17447c478bd9Sstevel@tonic-gate if (one_entry == NULL) { 17457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 17467c478bd9Sstevel@tonic-gate return (ERROR); 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate 17497c478bd9Sstevel@tonic-gate previous_head = aliases; 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate do { 17526532b960SJerry Gilliam bzero(one_entry, len+1); 1753f4da9be0Scth current_head = get_entry(previous_head, one_entry, ' ', 1); 17547c478bd9Sstevel@tonic-gate previous_head = current_head; 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate if ((unique_driver_name(one_entry, name_to_major, 17576532b960SJerry Gilliam &is_unique)) == ERROR) 17586532b960SJerry Gilliam goto err_out; 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate if (is_unique != UNIQUE) { 17617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_ALIAS_IN_NAM_MAJ), 17627c478bd9Sstevel@tonic-gate one_entry); 17636532b960SJerry Gilliam goto err_out; 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate 17666532b960SJerry Gilliam if ((err = unique_drv_alias(one_entry)) != UNIQUE) { 17676532b960SJerry Gilliam if (err == NOT_UNIQUE) { 17686532b960SJerry Gilliam (void) fprintf(stderr, 17696532b960SJerry Gilliam gettext(ERR_ALIAS_IN_USE), one_entry); 17706532b960SJerry Gilliam } 17716532b960SJerry Gilliam goto err_out; 17727c478bd9Sstevel@tonic-gate } 17737c478bd9Sstevel@tonic-gate 17741ca93273Seota if (!is_token(one_entry)) { 17751ca93273Seota (void) fprintf(stderr, gettext(ERR_BAD_TOK), 17761ca93273Seota "-i", one_entry); 17776532b960SJerry Gilliam goto err_out; 17781ca93273Seota } 17791ca93273Seota 17807c478bd9Sstevel@tonic-gate } while (*current_head != '\0'); 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate free(one_entry); 17837c478bd9Sstevel@tonic-gate return (NOERR); 17847c478bd9Sstevel@tonic-gate 17856532b960SJerry Gilliam err_out: 17866532b960SJerry Gilliam free(one_entry); 17876532b960SJerry Gilliam return (ERROR); 17886532b960SJerry Gilliam } 17896532b960SJerry Gilliam 17906532b960SJerry Gilliam /* 17916532b960SJerry Gilliam * verify each alias : 17926532b960SJerry Gilliam * alias list members separated by white space and quoted 17936532b960SJerry Gilliam * exist as alias name in /etc/driver_aliases 17946532b960SJerry Gilliam */ 17956532b960SJerry Gilliam int 17962e107de7SJerry Gilliam aliases_exist(char *aliases) 17976532b960SJerry Gilliam { 17986532b960SJerry Gilliam char *current_head; 17996532b960SJerry Gilliam char *previous_head; 18006532b960SJerry Gilliam char *one_entry; 18016532b960SJerry Gilliam int len; 18026532b960SJerry Gilliam 18036532b960SJerry Gilliam len = strlen(aliases); 18046532b960SJerry Gilliam 18056532b960SJerry Gilliam one_entry = calloc(len + 1, 1); 18066532b960SJerry Gilliam if (one_entry == NULL) { 18076532b960SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_MEM)); 18086532b960SJerry Gilliam return (ERROR); 18096532b960SJerry Gilliam } 18106532b960SJerry Gilliam 18116532b960SJerry Gilliam previous_head = aliases; 18126532b960SJerry Gilliam 18136532b960SJerry Gilliam do { 18146532b960SJerry Gilliam bzero(one_entry, len+1); 18156532b960SJerry Gilliam current_head = get_entry(previous_head, one_entry, ' ', 1); 18166532b960SJerry Gilliam previous_head = current_head; 18176532b960SJerry Gilliam 18182e107de7SJerry Gilliam if (unique_drv_alias(one_entry) != NOT_UNIQUE) 18196532b960SJerry Gilliam goto err_out; 18206532b960SJerry Gilliam 18216532b960SJerry Gilliam if (!is_token(one_entry)) { 18226532b960SJerry Gilliam (void) fprintf(stderr, gettext(ERR_BAD_TOK), 18236532b960SJerry Gilliam "-i", one_entry); 18246532b960SJerry Gilliam goto err_out; 18256532b960SJerry Gilliam } 18266532b960SJerry Gilliam 18276532b960SJerry Gilliam } while (*current_head != '\0'); 18286532b960SJerry Gilliam 18296532b960SJerry Gilliam free(one_entry); 18306532b960SJerry Gilliam return (NOERR); 18316532b960SJerry Gilliam 18326532b960SJerry Gilliam err_out: 18336532b960SJerry Gilliam free(one_entry); 18346532b960SJerry Gilliam return (ERROR); 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate 18377c478bd9Sstevel@tonic-gate 1838f4da9be0Scth /* 1839f4da9be0Scth * check each alias : 1840f4da9be0Scth * if path-oriented alias, path exists 1841f4da9be0Scth */ 1842f4da9be0Scth int 1843f4da9be0Scth aliases_paths_exist(char *aliases) 1844f4da9be0Scth { 1845f4da9be0Scth char *current_head; 1846f4da9be0Scth char *previous_head; 1847f4da9be0Scth char *one_entry; 1848f4da9be0Scth int i, len; 1849f4da9be0Scth char path[MAXPATHLEN]; 1850f4da9be0Scth struct stat buf; 1851f4da9be0Scth 1852f4da9be0Scth len = strlen(aliases); 1853f4da9be0Scth 1854f4da9be0Scth one_entry = calloc(len + 1, 1); 1855f4da9be0Scth if (one_entry == NULL) { 1856f4da9be0Scth (void) fprintf(stderr, gettext(ERR_NO_MEM)); 1857f4da9be0Scth return (ERROR); 1858f4da9be0Scth } 1859f4da9be0Scth 1860f4da9be0Scth previous_head = aliases; 1861f4da9be0Scth 1862f4da9be0Scth do { 1863f4da9be0Scth for (i = 0; i <= len; i++) 1864f4da9be0Scth one_entry[i] = 0; 1865f4da9be0Scth 1866f4da9be0Scth current_head = get_entry(previous_head, one_entry, ' ', 1); 1867f4da9be0Scth previous_head = current_head; 1868f4da9be0Scth 1869f4da9be0Scth /* if the alias is a path, ensure that the path exists */ 1870f4da9be0Scth if (*one_entry != '/') 1871f4da9be0Scth continue; 1872f4da9be0Scth (void) snprintf(path, sizeof (path), "/devices/%s", one_entry); 1873f4da9be0Scth if (stat(path, &buf) == 0) 1874f4da9be0Scth continue; 1875f4da9be0Scth 1876f4da9be0Scth /* no device at specified path-oriented alias path */ 1877f4da9be0Scth (void) fprintf(stderr, gettext(ERR_PATH_ORIENTED_ALIAS), 1878f4da9be0Scth one_entry); 1879f4da9be0Scth free(one_entry); 1880f4da9be0Scth return (ERROR); 1881f4da9be0Scth 1882f4da9be0Scth } while (*current_head != '\0'); 1883f4da9be0Scth 1884f4da9be0Scth free(one_entry); 1885f4da9be0Scth 1886f4da9be0Scth return (NOERR); 1887f4da9be0Scth } 1888f4da9be0Scth 1889f4da9be0Scth 18907c478bd9Sstevel@tonic-gate int 18917c478bd9Sstevel@tonic-gate update_driver_aliases( 18927c478bd9Sstevel@tonic-gate char *driver_name, 18937c478bd9Sstevel@tonic-gate char *aliases) 18947c478bd9Sstevel@tonic-gate { 18957c478bd9Sstevel@tonic-gate /* make call to update the aliases file */ 1896f4da9be0Scth return (append_to_file(driver_name, aliases, driver_aliases, 1897f4da9be0Scth ' ', " ", 1)); 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate 19007c478bd9Sstevel@tonic-gate 19016532b960SJerry Gilliam /* 19026532b960SJerry Gilliam * Return: 19036532b960SJerry Gilliam * ERROR in case of memory or read error 19046532b960SJerry Gilliam * UNIQUE if there is no existing match to the supplied alias 19056532b960SJerry Gilliam * NOT_UNIQUE if there is a match 19066532b960SJerry Gilliam * An error message is emitted in the case of ERROR, 19076532b960SJerry Gilliam * up to the caller otherwise. 19086532b960SJerry Gilliam */ 19097c478bd9Sstevel@tonic-gate int 19107c478bd9Sstevel@tonic-gate unique_drv_alias(char *drv_alias) 19117c478bd9Sstevel@tonic-gate { 19127c478bd9Sstevel@tonic-gate FILE *fp; 19137c478bd9Sstevel@tonic-gate char drv[FILENAME_MAX + 1]; 19141ca93273Seota char line[MAX_N2M_ALIAS_LINE + 1], *cp; 19157c478bd9Sstevel@tonic-gate char alias[FILENAME_MAX + 1]; 1916f4da9be0Scth char *a; 19176532b960SJerry Gilliam int status = UNIQUE; 19187c478bd9Sstevel@tonic-gate 19197c478bd9Sstevel@tonic-gate fp = fopen(driver_aliases, "r"); 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate if (fp != NULL) { 19227c478bd9Sstevel@tonic-gate while ((fgets(line, sizeof (line), fp) != 0) && 19236532b960SJerry Gilliam status == UNIQUE) { 19241ca93273Seota /* cut off comments starting with '#' */ 19251ca93273Seota if ((cp = strchr(line, '#')) != NULL) 19261ca93273Seota *cp = '\0'; 19271ca93273Seota /* ignore comment or blank lines */ 19281ca93273Seota if (is_blank(line)) 19291ca93273Seota continue; 19301ca93273Seota /* sanity-check */ 19313c0ea289SJerry Gilliam if (sscanf(line, 19323c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s" /* drv */ 19333c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s", /* alias */ 19343c0ea289SJerry Gilliam drv, alias) != 2) 19357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 19367c478bd9Sstevel@tonic-gate driver_aliases, line); 19377c478bd9Sstevel@tonic-gate 1938f4da9be0Scth /* unquote for compare */ 1939f4da9be0Scth if ((*alias == '"') && 1940f4da9be0Scth (*(alias + strlen(alias) - 1) == '"')) { 1941f4da9be0Scth a = &alias[1]; 1942f4da9be0Scth alias[strlen(alias) - 1] = '\0'; 1943f4da9be0Scth } else 1944f4da9be0Scth a = alias; 1945f4da9be0Scth 19467c478bd9Sstevel@tonic-gate if ((strcmp(drv_alias, drv) == 0) || 1947f4da9be0Scth (strcmp(drv_alias, a) == 0)) { 19486532b960SJerry Gilliam status = NOT_UNIQUE; 19496532b960SJerry Gilliam break; 19507c478bd9Sstevel@tonic-gate } 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate (void) fclose(fp); 19537c478bd9Sstevel@tonic-gate return (status); 19547c478bd9Sstevel@tonic-gate } else { 19557c478bd9Sstevel@tonic-gate perror(NULL); 19567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_OPEN), driver_aliases); 19577c478bd9Sstevel@tonic-gate return (ERROR); 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate 19627c478bd9Sstevel@tonic-gate /* 19637c478bd9Sstevel@tonic-gate * search for driver_name in first field of file file_name 19646532b960SJerry Gilliam * searching name_to_major and driver_aliases: name separated 19656532b960SJerry Gilliam * from the remainder of the line by white space. 19667c478bd9Sstevel@tonic-gate */ 19677c478bd9Sstevel@tonic-gate int 19687c478bd9Sstevel@tonic-gate unique_driver_name(char *driver_name, char *file_name, 19697c478bd9Sstevel@tonic-gate int *is_unique) 19707c478bd9Sstevel@tonic-gate { 19716532b960SJerry Gilliam int ret, err; 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate if ((ret = get_major_no(driver_name, file_name)) == ERROR) { 19747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), 19757c478bd9Sstevel@tonic-gate file_name); 19767c478bd9Sstevel@tonic-gate } else { 19777c478bd9Sstevel@tonic-gate /* check alias file for name collision */ 19786532b960SJerry Gilliam if ((err = unique_drv_alias(driver_name)) != UNIQUE) { 19796532b960SJerry Gilliam if (err == NOT_UNIQUE) { 19806532b960SJerry Gilliam (void) fprintf(stderr, 19816532b960SJerry Gilliam gettext(ERR_ALIAS_IN_USE), 19826532b960SJerry Gilliam driver_name); 19836532b960SJerry Gilliam } 19847c478bd9Sstevel@tonic-gate ret = ERROR; 19857c478bd9Sstevel@tonic-gate } else { 19867c478bd9Sstevel@tonic-gate if (ret != UNIQUE) 19877c478bd9Sstevel@tonic-gate *is_unique = NOT_UNIQUE; 19887c478bd9Sstevel@tonic-gate else 19897c478bd9Sstevel@tonic-gate *is_unique = ret; 19907c478bd9Sstevel@tonic-gate ret = NOERR; 19917c478bd9Sstevel@tonic-gate } 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate return (ret); 19947c478bd9Sstevel@tonic-gate } 19957c478bd9Sstevel@tonic-gate 19960013e2d3SJerry Gilliam /* 19970013e2d3SJerry Gilliam * returns: 19980013e2d3SJerry Gilliam * SUCCESS - not an existing driver alias 19990013e2d3SJerry Gilliam * NOT_UNIQUE - matching driver alias exists 20000013e2d3SJerry Gilliam * ERROR - an error occurred 20010013e2d3SJerry Gilliam */ 20020013e2d3SJerry Gilliam int 20030013e2d3SJerry Gilliam check_duplicate_driver_alias(char *driver_name, char *drv_alias) 20040013e2d3SJerry Gilliam { 20050013e2d3SJerry Gilliam FILE *fp; 20060013e2d3SJerry Gilliam char drv[FILENAME_MAX + 1]; 20070013e2d3SJerry Gilliam char line[MAX_N2M_ALIAS_LINE + 1], *cp; 20080013e2d3SJerry Gilliam char alias[FILENAME_MAX + 1]; 20090013e2d3SJerry Gilliam char *a; 20100013e2d3SJerry Gilliam int status = SUCCESS; 20110013e2d3SJerry Gilliam 20120013e2d3SJerry Gilliam if ((fp = fopen(driver_aliases, "r")) == NULL) { 20130013e2d3SJerry Gilliam perror(NULL); 20140013e2d3SJerry Gilliam (void) fprintf(stderr, gettext(ERR_CANT_OPEN), driver_aliases); 20150013e2d3SJerry Gilliam return (ERROR); 20160013e2d3SJerry Gilliam } 20170013e2d3SJerry Gilliam 20180013e2d3SJerry Gilliam while (fgets(line, sizeof (line), fp) != 0) { 20190013e2d3SJerry Gilliam /* cut off comments starting with '#' */ 20200013e2d3SJerry Gilliam if ((cp = strchr(line, '#')) != NULL) 20210013e2d3SJerry Gilliam *cp = '\0'; 20220013e2d3SJerry Gilliam /* ignore comment or blank lines */ 20230013e2d3SJerry Gilliam if (is_blank(line)) 20240013e2d3SJerry Gilliam continue; 20250013e2d3SJerry Gilliam /* sanity-check */ 20263c0ea289SJerry Gilliam if (sscanf(line, 20273c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s" /* drv */ 20283c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s", /* alias */ 20293c0ea289SJerry Gilliam drv, alias) != 2) 20300013e2d3SJerry Gilliam (void) fprintf(stderr, gettext(ERR_BAD_LINE), 20310013e2d3SJerry Gilliam driver_aliases, line); 20320013e2d3SJerry Gilliam 20330013e2d3SJerry Gilliam /* unquote for compare */ 20340013e2d3SJerry Gilliam if ((*alias == '"') && 20350013e2d3SJerry Gilliam (*(alias + strlen(alias) - 1) == '"')) { 20360013e2d3SJerry Gilliam a = &alias[1]; 20370013e2d3SJerry Gilliam alias[strlen(alias) - 1] = '\0'; 20380013e2d3SJerry Gilliam } else 20390013e2d3SJerry Gilliam a = alias; 20400013e2d3SJerry Gilliam 20410013e2d3SJerry Gilliam if ((strcmp(drv_alias, a) == 0) && 20420013e2d3SJerry Gilliam (strcmp(drv, driver_name) == 0)) { 20430013e2d3SJerry Gilliam status = NOT_UNIQUE; 20440013e2d3SJerry Gilliam } 20450013e2d3SJerry Gilliam 20460013e2d3SJerry Gilliam if ((strcmp(drv_alias, drv) == 0) || 20470013e2d3SJerry Gilliam ((strcmp(drv_alias, a) == 0) && 20480013e2d3SJerry Gilliam (strcmp(drv, driver_name) != 0))) { 20490013e2d3SJerry Gilliam (void) fprintf(stderr, 20500013e2d3SJerry Gilliam gettext(ERR_ALIAS_IN_USE), 20510013e2d3SJerry Gilliam drv_alias); 20520013e2d3SJerry Gilliam status = ERROR; 20530013e2d3SJerry Gilliam goto done; 20540013e2d3SJerry Gilliam } 20550013e2d3SJerry Gilliam } 20560013e2d3SJerry Gilliam 20570013e2d3SJerry Gilliam done: 20580013e2d3SJerry Gilliam (void) fclose(fp); 20590013e2d3SJerry Gilliam return (status); 20600013e2d3SJerry Gilliam } 20610013e2d3SJerry Gilliam 20620013e2d3SJerry Gilliam int 20630013e2d3SJerry Gilliam trim_duplicate_aliases(char *driver_name, char *aliases, char **aliases2p) 20640013e2d3SJerry Gilliam { 20650013e2d3SJerry Gilliam char *current_head; 20660013e2d3SJerry Gilliam char *previous_head; 20670013e2d3SJerry Gilliam char *one_entry; 20680013e2d3SJerry Gilliam char *aliases2; 20690013e2d3SJerry Gilliam int rv, len; 20700013e2d3SJerry Gilliam int n = 0; 20710013e2d3SJerry Gilliam 20720013e2d3SJerry Gilliam *aliases2p = NULL; 20730013e2d3SJerry Gilliam len = strlen(aliases) + 1; 20740013e2d3SJerry Gilliam 20750013e2d3SJerry Gilliam one_entry = calloc(len, 1); 20760013e2d3SJerry Gilliam aliases2 = calloc(len, 1); 20770013e2d3SJerry Gilliam if (one_entry == NULL || aliases2 == NULL) { 20780013e2d3SJerry Gilliam (void) fprintf(stderr, gettext(ERR_NO_MEM)); 20790013e2d3SJerry Gilliam return (ERROR); 20800013e2d3SJerry Gilliam } 20810013e2d3SJerry Gilliam 20820013e2d3SJerry Gilliam previous_head = aliases; 20830013e2d3SJerry Gilliam 20840013e2d3SJerry Gilliam do { 20850013e2d3SJerry Gilliam (void) bzero(one_entry, len); 20860013e2d3SJerry Gilliam current_head = get_entry(previous_head, one_entry, ' ', 1); 20870013e2d3SJerry Gilliam previous_head = current_head; 20880013e2d3SJerry Gilliam 20890013e2d3SJerry Gilliam rv = check_duplicate_driver_alias(driver_name, one_entry); 20900013e2d3SJerry Gilliam switch (rv) { 20910013e2d3SJerry Gilliam case SUCCESS: 20920013e2d3SJerry Gilliam /* not an existing driver alias: add it */ 20930013e2d3SJerry Gilliam if (n > 0) { 20940013e2d3SJerry Gilliam if (strlcat(aliases2, " ", len) >= len) 20950013e2d3SJerry Gilliam goto err; 20960013e2d3SJerry Gilliam } 20970013e2d3SJerry Gilliam if (strlcat(aliases2, one_entry, len) >= len) 20980013e2d3SJerry Gilliam goto err; 20990013e2d3SJerry Gilliam n++; 21000013e2d3SJerry Gilliam break; 21010013e2d3SJerry Gilliam case NOT_UNIQUE: 21020013e2d3SJerry Gilliam /* matching driver alias exists: do not add it */ 21030013e2d3SJerry Gilliam break; 21040013e2d3SJerry Gilliam case ERROR: 21050013e2d3SJerry Gilliam /* error reading the alias file */ 21060013e2d3SJerry Gilliam goto err; 21070013e2d3SJerry Gilliam default: 21080013e2d3SJerry Gilliam goto err; 21090013e2d3SJerry Gilliam } 21100013e2d3SJerry Gilliam 21110013e2d3SJerry Gilliam if (!is_token(one_entry)) { 21120013e2d3SJerry Gilliam (void) fprintf(stderr, gettext(ERR_BAD_TOK), 21130013e2d3SJerry Gilliam "-i", one_entry); 21140013e2d3SJerry Gilliam goto err; 21150013e2d3SJerry Gilliam } 21160013e2d3SJerry Gilliam } while (*current_head != '\0'); 21170013e2d3SJerry Gilliam 21180013e2d3SJerry Gilliam /* 21190013e2d3SJerry Gilliam * If all the aliases listed are already 21200013e2d3SJerry Gilliam * present we actually have none to do. 21210013e2d3SJerry Gilliam */ 21220013e2d3SJerry Gilliam if (n == 0) { 21230013e2d3SJerry Gilliam free(aliases2); 21240013e2d3SJerry Gilliam } else { 21250013e2d3SJerry Gilliam *aliases2p = aliases2; 21260013e2d3SJerry Gilliam } 21270013e2d3SJerry Gilliam free(one_entry); 21280013e2d3SJerry Gilliam return (NOERR); 21290013e2d3SJerry Gilliam 21300013e2d3SJerry Gilliam err: 21310013e2d3SJerry Gilliam free(aliases2); 21320013e2d3SJerry Gilliam free(one_entry); 21330013e2d3SJerry Gilliam return (ERROR); 21340013e2d3SJerry Gilliam } 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate int 21377c478bd9Sstevel@tonic-gate check_space_within_quote(char *str) 21387c478bd9Sstevel@tonic-gate { 21397c478bd9Sstevel@tonic-gate register int i; 21407c478bd9Sstevel@tonic-gate register int len; 21417c478bd9Sstevel@tonic-gate int quoted = 0; 21427c478bd9Sstevel@tonic-gate 21437c478bd9Sstevel@tonic-gate len = strlen(str); 21447c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++, str++) { 21457c478bd9Sstevel@tonic-gate if (*str == '"') { 21467c478bd9Sstevel@tonic-gate if (quoted == 0) 21477c478bd9Sstevel@tonic-gate quoted++; 21487c478bd9Sstevel@tonic-gate else 21497c478bd9Sstevel@tonic-gate quoted--; 21507c478bd9Sstevel@tonic-gate } else if (*str == ' ' && quoted) 21517c478bd9Sstevel@tonic-gate return (ERROR); 21527c478bd9Sstevel@tonic-gate } 21537c478bd9Sstevel@tonic-gate 21547c478bd9Sstevel@tonic-gate return (0); 21557c478bd9Sstevel@tonic-gate } 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate 21587c478bd9Sstevel@tonic-gate /* 21597c478bd9Sstevel@tonic-gate * get major number 21607c478bd9Sstevel@tonic-gate * write driver_name major_num to name_to_major file 21617c478bd9Sstevel@tonic-gate * major_num returned in major_num 21627c478bd9Sstevel@tonic-gate * return success/failure 21637c478bd9Sstevel@tonic-gate */ 21647c478bd9Sstevel@tonic-gate int 21657c478bd9Sstevel@tonic-gate update_name_to_major(char *driver_name, major_t *major_num, int server) 21667c478bd9Sstevel@tonic-gate { 21677c478bd9Sstevel@tonic-gate char major[MAX_STR_MAJOR + 1]; 21687c478bd9Sstevel@tonic-gate struct stat buf; 21697c478bd9Sstevel@tonic-gate char *num_list; 21707c478bd9Sstevel@tonic-gate char drv_majnum_str[MAX_STR_MAJOR + 1]; 21717c478bd9Sstevel@tonic-gate int new_maj = -1; 21727c478bd9Sstevel@tonic-gate int i, tmp = 0, is_unique, have_rem_n2m = 0; 21737c478bd9Sstevel@tonic-gate int max_dev = 0; 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate /* 21767c478bd9Sstevel@tonic-gate * if driver_name already in rem_name_to_major 21777c478bd9Sstevel@tonic-gate * delete entry from rem_nam_to_major 21787c478bd9Sstevel@tonic-gate * put entry into name_to_major 21797c478bd9Sstevel@tonic-gate */ 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate if (stat(rem_name_to_major, &buf) == 0) { 21827c478bd9Sstevel@tonic-gate have_rem_n2m = 1; 21837c478bd9Sstevel@tonic-gate } 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate if (have_rem_n2m) { 21867c478bd9Sstevel@tonic-gate if ((is_unique = get_major_no(driver_name, rem_name_to_major)) 21877c478bd9Sstevel@tonic-gate == ERROR) 21887c478bd9Sstevel@tonic-gate return (ERROR); 21897c478bd9Sstevel@tonic-gate 21907c478bd9Sstevel@tonic-gate /* 21917c478bd9Sstevel@tonic-gate * found a match in rem_name_to_major 21927c478bd9Sstevel@tonic-gate */ 21937c478bd9Sstevel@tonic-gate if (is_unique != UNIQUE) { 21947c478bd9Sstevel@tonic-gate char scratch[FILENAME_MAX]; 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate /* 21977c478bd9Sstevel@tonic-gate * If there is a match in /etc/rem_name_to_major then 21987c478bd9Sstevel@tonic-gate * be paranoid: is that major number already in 21997c478bd9Sstevel@tonic-gate * /etc/name_to_major (potentially under another name)? 22007c478bd9Sstevel@tonic-gate */ 22017c478bd9Sstevel@tonic-gate if (get_driver_name(is_unique, name_to_major, 22027c478bd9Sstevel@tonic-gate scratch) != UNIQUE) { 22037c478bd9Sstevel@tonic-gate /* 22047c478bd9Sstevel@tonic-gate * nuke the rem_name_to_major entry-- it 22057c478bd9Sstevel@tonic-gate * isn't helpful. 22067c478bd9Sstevel@tonic-gate */ 22077c478bd9Sstevel@tonic-gate (void) delete_entry(rem_name_to_major, 22087c478bd9Sstevel@tonic-gate driver_name, " ", NULL); 22097c478bd9Sstevel@tonic-gate } else { 22107c478bd9Sstevel@tonic-gate (void) snprintf(major, sizeof (major), 22117c478bd9Sstevel@tonic-gate "%d", is_unique); 22127c478bd9Sstevel@tonic-gate 22137c478bd9Sstevel@tonic-gate if (append_to_file(driver_name, major, 2214f4da9be0Scth name_to_major, ' ', " ", 0) == ERROR) { 22157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 22167c478bd9Sstevel@tonic-gate gettext(ERR_NO_UPDATE), 22177c478bd9Sstevel@tonic-gate name_to_major); 22187c478bd9Sstevel@tonic-gate return (ERROR); 22197c478bd9Sstevel@tonic-gate } 22207c478bd9Sstevel@tonic-gate 22217c478bd9Sstevel@tonic-gate if (delete_entry(rem_name_to_major, 22227c478bd9Sstevel@tonic-gate driver_name, " ", NULL) == ERROR) { 22237c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 22247c478bd9Sstevel@tonic-gate gettext(ERR_DEL_ENTRY), driver_name, 22257c478bd9Sstevel@tonic-gate rem_name_to_major); 22267c478bd9Sstevel@tonic-gate return (ERROR); 22277c478bd9Sstevel@tonic-gate } 22287c478bd9Sstevel@tonic-gate 22297c478bd9Sstevel@tonic-gate /* found matching entry : no errors */ 22307c478bd9Sstevel@tonic-gate *major_num = is_unique; 22317c478bd9Sstevel@tonic-gate return (NOERR); 22327c478bd9Sstevel@tonic-gate } 22337c478bd9Sstevel@tonic-gate } 22347c478bd9Sstevel@tonic-gate } 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate /* 22377c478bd9Sstevel@tonic-gate * Bugid: 1264079 22387c478bd9Sstevel@tonic-gate * In a server case (with -b option), we can't use modctl() to find 22397c478bd9Sstevel@tonic-gate * the maximum major number, we need to dig thru client's 22407c478bd9Sstevel@tonic-gate * /etc/name_to_major and /etc/rem_name_to_major for the max_dev. 22417c478bd9Sstevel@tonic-gate * 22427c478bd9Sstevel@tonic-gate * if (server) 22437c478bd9Sstevel@tonic-gate * get maximum major number thru (rem_)name_to_major file on client 22447c478bd9Sstevel@tonic-gate * else 22457c478bd9Sstevel@tonic-gate * get maximum major number allowable on current system using modctl 22467c478bd9Sstevel@tonic-gate */ 22477c478bd9Sstevel@tonic-gate if (server) { 22487c478bd9Sstevel@tonic-gate max_dev = 0; 22497c478bd9Sstevel@tonic-gate tmp = 0; 22507c478bd9Sstevel@tonic-gate 22517c478bd9Sstevel@tonic-gate max_dev = get_max_major(name_to_major); 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate /* If rem_name_to_major exists, we need to check it too */ 22547c478bd9Sstevel@tonic-gate if (have_rem_n2m) { 22557c478bd9Sstevel@tonic-gate tmp = get_max_major(rem_name_to_major); 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate /* 22587c478bd9Sstevel@tonic-gate * If name_to_major is missing, we can get max_dev from 22597c478bd9Sstevel@tonic-gate * /etc/rem_name_to_major. If both missing, bail out! 22607c478bd9Sstevel@tonic-gate */ 22617c478bd9Sstevel@tonic-gate if ((max_dev == ERROR) && (tmp == ERROR)) { 22627c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 22637c478bd9Sstevel@tonic-gate gettext(ERR_CANT_ACCESS_FILE), 22647c478bd9Sstevel@tonic-gate name_to_major); 22657c478bd9Sstevel@tonic-gate return (ERROR); 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate /* guard against bigger maj_num in rem_name_to_major */ 22697c478bd9Sstevel@tonic-gate if (tmp > max_dev) 22707c478bd9Sstevel@tonic-gate max_dev = tmp; 22717c478bd9Sstevel@tonic-gate } else { 22727c478bd9Sstevel@tonic-gate /* 22737c478bd9Sstevel@tonic-gate * If we can't get major from name_to_major file 22747c478bd9Sstevel@tonic-gate * and there is no /etc/rem_name_to_major file, 22757c478bd9Sstevel@tonic-gate * then we don't have a max_dev, bail out quick! 22767c478bd9Sstevel@tonic-gate */ 22777c478bd9Sstevel@tonic-gate if (max_dev == ERROR) 22787c478bd9Sstevel@tonic-gate return (ERROR); 22797c478bd9Sstevel@tonic-gate } 22807c478bd9Sstevel@tonic-gate 22817c478bd9Sstevel@tonic-gate /* 22827c478bd9Sstevel@tonic-gate * In case there is no more slack in current name_to_major 22837c478bd9Sstevel@tonic-gate * table, provide at least 1 extra entry so the add_drv can 22847c478bd9Sstevel@tonic-gate * succeed. Since only one add_drv process is allowed at one 22857c478bd9Sstevel@tonic-gate * time, and hence max_dev will be re-calculated each time 22867c478bd9Sstevel@tonic-gate * add_drv is ran, we don't need to worry about adding more 22877c478bd9Sstevel@tonic-gate * than 1 extra slot for max_dev. 22887c478bd9Sstevel@tonic-gate */ 22897c478bd9Sstevel@tonic-gate max_dev++; 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate } else { 22927c478bd9Sstevel@tonic-gate if (modctl(MODRESERVED, NULL, &max_dev) < 0) { 22937c478bd9Sstevel@tonic-gate perror(NULL); 22947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MAX_MAJOR)); 22957c478bd9Sstevel@tonic-gate return (ERROR); 22967c478bd9Sstevel@tonic-gate } 22977c478bd9Sstevel@tonic-gate } 22987c478bd9Sstevel@tonic-gate 22997c478bd9Sstevel@tonic-gate /* 23007c478bd9Sstevel@tonic-gate * max_dev is really how many slots the kernel has allocated for 23017c478bd9Sstevel@tonic-gate * devices... [0 , maxdev-1], not the largest available device num. 23027c478bd9Sstevel@tonic-gate */ 23037c478bd9Sstevel@tonic-gate if ((num_list = calloc(max_dev, 1)) == NULL) { 23047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 23057c478bd9Sstevel@tonic-gate return (ERROR); 23067c478bd9Sstevel@tonic-gate } 23077c478bd9Sstevel@tonic-gate 23087c478bd9Sstevel@tonic-gate /* 23097c478bd9Sstevel@tonic-gate * Populate the num_list array 23107c478bd9Sstevel@tonic-gate */ 23117c478bd9Sstevel@tonic-gate if (fill_n2m_array(name_to_major, &num_list, &max_dev) != 0) { 23127c478bd9Sstevel@tonic-gate return (ERROR); 23137c478bd9Sstevel@tonic-gate } 23147c478bd9Sstevel@tonic-gate if (have_rem_n2m) { 23157c478bd9Sstevel@tonic-gate if (fill_n2m_array(rem_name_to_major, &num_list, &max_dev) != 0) 23167c478bd9Sstevel@tonic-gate return (ERROR); 23177c478bd9Sstevel@tonic-gate } 23187c478bd9Sstevel@tonic-gate 2319*746b0187SRichard Lowe /* 2320*746b0187SRichard Lowe * Find the first free major number. 2321*746b0187SRichard Lowe * 2322*746b0187SRichard Lowe * Note that we begin searching from 1, as drivers have developer the 2323*746b0187SRichard Lowe * erroneous assumption that a dev_t of 0 is invalid, and since we no 2324*746b0187SRichard Lowe * longer include system devices in the base files, a major number of 2325*746b0187SRichard Lowe * 0 may now be given to arbitrary devices. 2326*746b0187SRichard Lowe */ 2327*746b0187SRichard Lowe for (i = 1; i < max_dev; i++) { 23287c478bd9Sstevel@tonic-gate if (num_list[i] != 1) { 23297c478bd9Sstevel@tonic-gate new_maj = i; 23307c478bd9Sstevel@tonic-gate break; 23317c478bd9Sstevel@tonic-gate } 23327c478bd9Sstevel@tonic-gate } 23337c478bd9Sstevel@tonic-gate 23347c478bd9Sstevel@tonic-gate if (new_maj == -1) { 23357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_FREE_MAJOR)); 23367c478bd9Sstevel@tonic-gate return (ERROR); 23377c478bd9Sstevel@tonic-gate } 23387c478bd9Sstevel@tonic-gate 23392e107de7SJerry Gilliam (void) snprintf(drv_majnum_str, sizeof (drv_majnum_str), 23402e107de7SJerry Gilliam "%d", new_maj); 23417c478bd9Sstevel@tonic-gate if (do_the_update(driver_name, drv_majnum_str) == ERROR) { 23427c478bd9Sstevel@tonic-gate return (ERROR); 23437c478bd9Sstevel@tonic-gate } 23447c478bd9Sstevel@tonic-gate 23457c478bd9Sstevel@tonic-gate *major_num = new_maj; 23467c478bd9Sstevel@tonic-gate return (NOERR); 23477c478bd9Sstevel@tonic-gate } 23487c478bd9Sstevel@tonic-gate 23497c478bd9Sstevel@tonic-gate 23507c478bd9Sstevel@tonic-gate int 23517c478bd9Sstevel@tonic-gate fill_n2m_array(char *filename, char **array, int *nelems) 23527c478bd9Sstevel@tonic-gate { 23537c478bd9Sstevel@tonic-gate FILE *fp; 23541ca93273Seota char line[MAX_N2M_ALIAS_LINE + 1], *cp; 23557c478bd9Sstevel@tonic-gate char drv[FILENAME_MAX + 1]; 23567c478bd9Sstevel@tonic-gate u_longlong_t dnum; 23577c478bd9Sstevel@tonic-gate major_t drv_majnum; 23587c478bd9Sstevel@tonic-gate 23597c478bd9Sstevel@tonic-gate /* 23607c478bd9Sstevel@tonic-gate * Read through the file, marking each major number found 23617c478bd9Sstevel@tonic-gate * order is not relevant 23627c478bd9Sstevel@tonic-gate */ 23637c478bd9Sstevel@tonic-gate if ((fp = fopen(filename, "r")) == NULL) { 23647c478bd9Sstevel@tonic-gate perror(NULL); 23657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_CANT_ACCESS_FILE), filename); 23667c478bd9Sstevel@tonic-gate return (ERROR); 23677c478bd9Sstevel@tonic-gate } 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line), fp) != 0) { 23701ca93273Seota /* cut off comments starting with '#' */ 23711ca93273Seota if ((cp = strchr(line, '#')) != NULL) 23721ca93273Seota *cp = '\0'; 23731ca93273Seota /* ignore comment or blank lines */ 23741ca93273Seota if (is_blank(line)) 23751ca93273Seota continue; 23761ca93273Seota /* sanity-check */ 23773c0ea289SJerry Gilliam if (sscanf(line, 23783c0ea289SJerry Gilliam "%" VAL2STR(FILENAME_MAX) "s %llu", drv, &dnum) != 2) { 23797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_BAD_LINE), 23807c478bd9Sstevel@tonic-gate filename, line); 23817c478bd9Sstevel@tonic-gate (void) fclose(fp); 23827c478bd9Sstevel@tonic-gate return (ERROR); 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate if (dnum > L_MAXMAJ32) { 23867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MAJ_TOOBIG), drv, 23877c478bd9Sstevel@tonic-gate dnum, filename, L_MAXMAJ32); 23887c478bd9Sstevel@tonic-gate continue; 23897c478bd9Sstevel@tonic-gate } 23907c478bd9Sstevel@tonic-gate /* 23917c478bd9Sstevel@tonic-gate * cast down to a major_t; we can be sure this is safe because 23927c478bd9Sstevel@tonic-gate * of the above range-check. 23937c478bd9Sstevel@tonic-gate */ 23947c478bd9Sstevel@tonic-gate drv_majnum = (major_t)dnum; 23957c478bd9Sstevel@tonic-gate 23967c478bd9Sstevel@tonic-gate if (drv_majnum >= *nelems) { 23977c478bd9Sstevel@tonic-gate /* 23987c478bd9Sstevel@tonic-gate * Allocate some more space, up to drv_majnum + 1 so 23997c478bd9Sstevel@tonic-gate * we can accomodate 0 through drv_majnum. 24007c478bd9Sstevel@tonic-gate * 24017c478bd9Sstevel@tonic-gate * Note that in the failure case, we leak all of the 24027c478bd9Sstevel@tonic-gate * old contents of array. It's ok, since we just 24037c478bd9Sstevel@tonic-gate * wind up exiting immediately anyway. 24047c478bd9Sstevel@tonic-gate */ 24057c478bd9Sstevel@tonic-gate *nelems = drv_majnum + 1; 24067c478bd9Sstevel@tonic-gate *array = realloc(*array, *nelems); 24077c478bd9Sstevel@tonic-gate if (*array == NULL) { 24087c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_MEM)); 24097c478bd9Sstevel@tonic-gate return (ERROR); 24107c478bd9Sstevel@tonic-gate } 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate (*array)[drv_majnum] = 1; 24137c478bd9Sstevel@tonic-gate } 24147c478bd9Sstevel@tonic-gate 24157c478bd9Sstevel@tonic-gate (void) fclose(fp); 24167c478bd9Sstevel@tonic-gate return (0); 24177c478bd9Sstevel@tonic-gate } 24187c478bd9Sstevel@tonic-gate 24197c478bd9Sstevel@tonic-gate 24207c478bd9Sstevel@tonic-gate int 24217c478bd9Sstevel@tonic-gate do_the_update(char *driver_name, char *major_number) 24227c478bd9Sstevel@tonic-gate { 24237c478bd9Sstevel@tonic-gate return (append_to_file(driver_name, major_number, name_to_major, 2424f4da9be0Scth ' ', " ", 0)); 24257c478bd9Sstevel@tonic-gate } 24261ca93273Seota 24271ca93273Seota /* 24281ca93273Seota * is_blank() returns 1 (true) if a line specified is composed of 24291ca93273Seota * whitespace characters only. otherwise, it returns 0 (false). 24301ca93273Seota * 24311ca93273Seota * Note. the argument (line) must be null-terminated. 24321ca93273Seota */ 24331ca93273Seota static int 24341ca93273Seota is_blank(char *line) 24351ca93273Seota { 24361ca93273Seota for (/* nothing */; *line != '\0'; line++) 24371ca93273Seota if (!isspace(*line)) 24381ca93273Seota return (0); 24391ca93273Seota return (1); 24401ca93273Seota } 2441