10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
54145Scth * Common Development and Distribution License (the "License").
64145Scth * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
228565SJerry.Gilliam@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <locale.h>
280Sstevel@tonic-gate #include <stdlib.h>
290Sstevel@tonic-gate #include <unistd.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include "addrem.h"
330Sstevel@tonic-gate #include "errmsg.h"
340Sstevel@tonic-gate #include "plcysubr.h"
350Sstevel@tonic-gate
360Sstevel@tonic-gate /* function prototypes */
370Sstevel@tonic-gate static void usage();
380Sstevel@tonic-gate static int unload_drv(char *, int, int);
390Sstevel@tonic-gate
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * try to modunload driver.
430Sstevel@tonic-gate * return -1 on failure and 0 on success
440Sstevel@tonic-gate */
450Sstevel@tonic-gate static int
unload_drv(char * driver_name,int force_flag,int verbose_flag)460Sstevel@tonic-gate unload_drv(char *driver_name, int force_flag, int verbose_flag)
470Sstevel@tonic-gate {
480Sstevel@tonic-gate int modid;
490Sstevel@tonic-gate
500Sstevel@tonic-gate get_modid(driver_name, &modid);
510Sstevel@tonic-gate if (modid != -1) {
520Sstevel@tonic-gate if (modctl(MODUNLOAD, modid) < 0) {
530Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_MODUN), driver_name);
540Sstevel@tonic-gate if (force_flag == 0) { /* no force flag */
550Sstevel@tonic-gate if (verbose_flag) {
560Sstevel@tonic-gate (void) fprintf(stderr,
570Sstevel@tonic-gate gettext(NOUPDATE), driver_name);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate /* clean up and exit. remove lock file */
600Sstevel@tonic-gate err_exit();
610Sstevel@tonic-gate }
620Sstevel@tonic-gate (void) fprintf(stderr, gettext(FORCE_UPDATE),
630Sstevel@tonic-gate driver_name);
640Sstevel@tonic-gate
650Sstevel@tonic-gate return (-1);
660Sstevel@tonic-gate }
670Sstevel@tonic-gate }
680Sstevel@tonic-gate
690Sstevel@tonic-gate return (0);
700Sstevel@tonic-gate }
710Sstevel@tonic-gate
720Sstevel@tonic-gate
730Sstevel@tonic-gate static void
usage()740Sstevel@tonic-gate usage()
750Sstevel@tonic-gate {
760Sstevel@tonic-gate (void) fprintf(stderr, gettext(UPD_DRV_USAGE));
770Sstevel@tonic-gate exit(1);
780Sstevel@tonic-gate }
790Sstevel@tonic-gate
800Sstevel@tonic-gate
810Sstevel@tonic-gate int
main(int argc,char * argv[])820Sstevel@tonic-gate main(int argc, char *argv[])
830Sstevel@tonic-gate {
840Sstevel@tonic-gate int error, opt, major;
850Sstevel@tonic-gate int cleanup_flag = 0;
860Sstevel@tonic-gate int update_conf = 1; /* reload driver.conf by default */
870Sstevel@tonic-gate int verbose_flag = 0; /* -v option */
880Sstevel@tonic-gate int force_flag = 0; /* -f option */
890Sstevel@tonic-gate int a_flag = 0; /* -a option */
900Sstevel@tonic-gate int d_flag = 0; /* -d option */
910Sstevel@tonic-gate int i_flag = 0; /* -i option */
920Sstevel@tonic-gate int l_flag = 0; /* -l option */
930Sstevel@tonic-gate int m_flag = 0; /* -m option */
948565SJerry.Gilliam@Sun.COM int n_flag = 0; /* -n option */
950Sstevel@tonic-gate char *perms = NULL;
968331SJerry.Gilliam@Sun.COM char *aliases = NULL;
970Sstevel@tonic-gate char *basedir = NULL;
980Sstevel@tonic-gate char *policy = NULL;
998331SJerry.Gilliam@Sun.COM char *aliases2 = NULL;
1000Sstevel@tonic-gate char *priv = NULL;
1010Sstevel@tonic-gate char *driver_name;
1020Sstevel@tonic-gate int found;
1030Sstevel@tonic-gate major_t major_num;
1040Sstevel@tonic-gate int rval;
105*10842SJerry.Gilliam@Sun.COM int config_flags;
1060Sstevel@tonic-gate
1070Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1080Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
1090Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
1100Sstevel@tonic-gate #endif
1110Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /* must be run by root */
1140Sstevel@tonic-gate if (getuid() != 0) {
1150Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NOT_ROOT));
1160Sstevel@tonic-gate exit(1);
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1198565SJerry.Gilliam@Sun.COM while ((opt = getopt(argc, argv, "m:ni:b:p:adlfuvP:")) != EOF) {
1200Sstevel@tonic-gate switch (opt) {
1210Sstevel@tonic-gate case 'a':
1220Sstevel@tonic-gate a_flag++;
1230Sstevel@tonic-gate break;
1240Sstevel@tonic-gate case 'b':
1250Sstevel@tonic-gate update_conf = 0; /* don't update .conf file */
1260Sstevel@tonic-gate basedir = optarg;
1270Sstevel@tonic-gate break;
1280Sstevel@tonic-gate case 'd':
1290Sstevel@tonic-gate d_flag++;
1300Sstevel@tonic-gate break;
1310Sstevel@tonic-gate case 'f':
1320Sstevel@tonic-gate force_flag++;
1330Sstevel@tonic-gate break;
1340Sstevel@tonic-gate case 'i':
1350Sstevel@tonic-gate i_flag++;
1360Sstevel@tonic-gate aliases = optarg;
1370Sstevel@tonic-gate if (check_space_within_quote(aliases) == ERROR) {
1380Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_SPACE),
1395001Sjg aliases);
1400Sstevel@tonic-gate exit(1);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate break;
1430Sstevel@tonic-gate case 'l': /* private option */
1440Sstevel@tonic-gate l_flag++;
1450Sstevel@tonic-gate break;
1460Sstevel@tonic-gate case 'm':
1470Sstevel@tonic-gate m_flag++;
1480Sstevel@tonic-gate perms = optarg;
1490Sstevel@tonic-gate break;
1508565SJerry.Gilliam@Sun.COM case 'n':
1518565SJerry.Gilliam@Sun.COM n_flag++;
1528565SJerry.Gilliam@Sun.COM update_conf = 0;
1538565SJerry.Gilliam@Sun.COM break;
1540Sstevel@tonic-gate case 'p':
1550Sstevel@tonic-gate policy = optarg;
1560Sstevel@tonic-gate break;
1570Sstevel@tonic-gate case 'v':
1580Sstevel@tonic-gate verbose_flag++;
1590Sstevel@tonic-gate break;
1600Sstevel@tonic-gate case 'P':
1610Sstevel@tonic-gate priv = optarg;
1620Sstevel@tonic-gate break;
1630Sstevel@tonic-gate case '?' :
1640Sstevel@tonic-gate default:
1650Sstevel@tonic-gate usage();
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate * check for flags and extra args
1710Sstevel@tonic-gate */
1720Sstevel@tonic-gate if ((argv[optind] == NULL) || (optind + 1 != argc)) {
1730Sstevel@tonic-gate usage();
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate /*
1770Sstevel@tonic-gate * - cannot be adding and removing at the same time
1780Sstevel@tonic-gate * - if -a or -d is specified, it's an error if none of
1790Sstevel@tonic-gate * -i/-m/-p/-P is specified.
1800Sstevel@tonic-gate */
1810Sstevel@tonic-gate if ((a_flag && d_flag) ||
1820Sstevel@tonic-gate ((a_flag || d_flag) &&
1830Sstevel@tonic-gate !m_flag && !i_flag && priv == NULL && policy == NULL)) {
1840Sstevel@tonic-gate usage();
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate /*
1880Sstevel@tonic-gate * - with -d option or -a option either -i 'identify_name',
1890Sstevel@tonic-gate * -m 'permission', -p 'policy' or -P 'priv' should be specified
1900Sstevel@tonic-gate */
1910Sstevel@tonic-gate if (m_flag || i_flag || policy != NULL || priv != NULL) {
1920Sstevel@tonic-gate if (!(a_flag || d_flag))
1930Sstevel@tonic-gate usage();
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate driver_name = argv[optind];
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate /* set up update_drv filenames */
1990Sstevel@tonic-gate if ((build_filenames(basedir)) == ERROR) {
2000Sstevel@tonic-gate exit(1);
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate /* no lock is needed for listing minor perm entry */
2040Sstevel@tonic-gate if (l_flag) {
2050Sstevel@tonic-gate list_entry(minor_perm, driver_name, ":");
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate return (NOERR);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /* must be only running version of add_drv/update_drv/rem_drv */
2110Sstevel@tonic-gate enter_lock();
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate if ((check_perms_aliases(m_flag, i_flag)) == ERROR) {
2140Sstevel@tonic-gate err_exit();
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate /* update_drv doesn't modify /etc/name_to_major file */
2180Sstevel@tonic-gate if ((check_name_to_major(R_OK)) == ERROR)
2190Sstevel@tonic-gate err_exit();
2200Sstevel@tonic-gate
2218565SJerry.Gilliam@Sun.COM if ((n_flag == 0) &&
2228565SJerry.Gilliam@Sun.COM (basedir == NULL || (strcmp(basedir, "/") == 0)) &&
2238565SJerry.Gilliam@Sun.COM (priv != NULL) && check_priv_entry(priv, a_flag) != 0)
2240Sstevel@tonic-gate err_exit();
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate if (policy != NULL && (policy = check_plcy_entry(policy, driver_name,
2270Sstevel@tonic-gate d_flag ? B_TRUE : B_FALSE)) == NULL)
2280Sstevel@tonic-gate err_exit();
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate /*
2310Sstevel@tonic-gate * ADD: -a option
2320Sstevel@tonic-gate * i_flag: update /etc/driver_aliases
2330Sstevel@tonic-gate * m_flag: update /etc/minor_perm
2340Sstevel@tonic-gate * -p: update /etc/security/device_policy
2350Sstevel@tonic-gate * -P: update /etc/security/extra_privs
2360Sstevel@tonic-gate * if force_flag is specified continue w/ the next operation
2370Sstevel@tonic-gate */
2380Sstevel@tonic-gate if (a_flag) {
2390Sstevel@tonic-gate if (m_flag) {
2400Sstevel@tonic-gate /* check if the permissions are valid */
2410Sstevel@tonic-gate if ((error = check_perm_opts(perms)) == ERROR) {
2420Sstevel@tonic-gate if (force_flag == 0) { /* no force flag */
2430Sstevel@tonic-gate exit_unlock();
2440Sstevel@tonic-gate return (error);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate }
2470Sstevel@tonic-gate
2480Sstevel@tonic-gate /*
2490Sstevel@tonic-gate * update the file, if and only if
2500Sstevel@tonic-gate * we didn't run into error earlier.
2510Sstevel@tonic-gate */
2520Sstevel@tonic-gate if ((error != ERROR) &&
2530Sstevel@tonic-gate (error = update_minor_entry(driver_name, perms))) {
2540Sstevel@tonic-gate if (force_flag == 0) { /* no force flag */
2550Sstevel@tonic-gate exit_unlock();
2560Sstevel@tonic-gate return (error);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate cleanup_flag |= CLEAN_NAM_MAJ;
2600Sstevel@tonic-gate
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate * Notify running system of minor perm change
2630Sstevel@tonic-gate */
2648565SJerry.Gilliam@Sun.COM if ((n_flag == 0) &&
2658565SJerry.Gilliam@Sun.COM (basedir == NULL || (strcmp(basedir, "/") == 0))) {
2660Sstevel@tonic-gate rval = devfs_add_minor_perm(driver_name,
2670Sstevel@tonic-gate log_minorperm_error);
2680Sstevel@tonic-gate if (rval) {
2690Sstevel@tonic-gate (void) fprintf(stderr,
2700Sstevel@tonic-gate gettext(ERR_UPDATE_PERM),
2710Sstevel@tonic-gate driver_name);
2720Sstevel@tonic-gate }
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate if (priv != NULL) {
2770Sstevel@tonic-gate (void) append_to_file(driver_name, priv, extra_privs,
2785001Sjg ',', ":", 0);
2790Sstevel@tonic-gate cleanup_flag |= CLEAN_DRV_PRIV;
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate if (policy != NULL) {
2830Sstevel@tonic-gate if ((error = update_device_policy(device_policy,
2840Sstevel@tonic-gate policy, B_TRUE)) != 0) {
2850Sstevel@tonic-gate exit_unlock();
2860Sstevel@tonic-gate return (error);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate cleanup_flag |= CLEAN_DEV_POLICY;
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate if (i_flag) {
292579Scth found = get_major_no(driver_name, name_to_major);
293579Scth if (found == ERROR) {
294579Scth (void) fprintf(stderr, gettext(ERR_MAX_MAJOR),
295579Scth name_to_major);
296579Scth err_exit();
297579Scth }
298579Scth
299579Scth if (found == UNIQUE) {
300579Scth (void) fprintf(stderr,
301579Scth gettext(ERR_NOT_INSTALLED), driver_name);
302579Scth err_exit();
303579Scth }
304579Scth
305579Scth major_num = (major_t)found;
306579Scth
3078331SJerry.Gilliam@Sun.COM /*
3088331SJerry.Gilliam@Sun.COM * To ease the nuisance of using update_drv
3098331SJerry.Gilliam@Sun.COM * in packaging scripts, do not require that
3108331SJerry.Gilliam@Sun.COM * existing driver aliases be trimmed from
3118331SJerry.Gilliam@Sun.COM * the command line. If an invocation asks
3128331SJerry.Gilliam@Sun.COM * to add an alias and it's already there,
3138331SJerry.Gilliam@Sun.COM * drive on. We implement this by removing
3148331SJerry.Gilliam@Sun.COM * duplicates now and add the remainder.
3158331SJerry.Gilliam@Sun.COM */
3168331SJerry.Gilliam@Sun.COM error = trim_duplicate_aliases(driver_name,
3178331SJerry.Gilliam@Sun.COM aliases, &aliases2);
3188331SJerry.Gilliam@Sun.COM if (error == ERROR) {
3190Sstevel@tonic-gate exit_unlock();
3200Sstevel@tonic-gate return (error);
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate
3234145Scth /*
3248331SJerry.Gilliam@Sun.COM * if the list of aliases to be added is
3258331SJerry.Gilliam@Sun.COM * now empty, we're done.
3268331SJerry.Gilliam@Sun.COM */
3278331SJerry.Gilliam@Sun.COM if (aliases2 == NULL)
3288331SJerry.Gilliam@Sun.COM goto done;
3298331SJerry.Gilliam@Sun.COM
3308331SJerry.Gilliam@Sun.COM /*
3314145Scth * unless force_flag is specified check that
3324145Scth * path-oriented aliases we are adding exist
3334145Scth */
3348331SJerry.Gilliam@Sun.COM if ((force_flag == 0) && ((error =
3358331SJerry.Gilliam@Sun.COM aliases_paths_exist(aliases2)) == ERROR)) {
3364145Scth exit_unlock();
3374145Scth return (error);
3384145Scth }
3394145Scth
3400Sstevel@tonic-gate /* update the file */
3410Sstevel@tonic-gate if ((error = update_driver_aliases(driver_name,
3428331SJerry.Gilliam@Sun.COM aliases2)) == ERROR) {
3430Sstevel@tonic-gate exit_unlock();
3440Sstevel@tonic-gate return (error);
3450Sstevel@tonic-gate }
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate
3485001Sjg /* optionally update the running system - not -b */
3495001Sjg if (update_conf) {
3508831SJerry.Gilliam@Sun.COM /* paranoia - if we crash whilst configuring */
3518831SJerry.Gilliam@Sun.COM sync();
352*10842SJerry.Gilliam@Sun.COM config_flags = (verbose_flag) ?
353*10842SJerry.Gilliam@Sun.COM CONFIG_DRV_VERBOSE : 0;
3545001Sjg cleanup_flag |= CLEAN_DRV_ALIAS;
3555001Sjg if (config_driver(driver_name, major_num,
3568331SJerry.Gilliam@Sun.COM aliases2, NULL, cleanup_flag,
357*10842SJerry.Gilliam@Sun.COM config_flags) == ERROR) {
3585001Sjg err_exit();
3595001Sjg }
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate }
3638331SJerry.Gilliam@Sun.COM
3648331SJerry.Gilliam@Sun.COM done:
3655878Sjg if (update_conf && (i_flag || policy != NULL)) {
3660Sstevel@tonic-gate /* load the driver */
3670Sstevel@tonic-gate load_driver(driver_name, verbose_flag);
3685878Sjg }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate exit_unlock();
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate return (0);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate /*
3770Sstevel@tonic-gate * DELETE: -d option
3780Sstevel@tonic-gate * i_flag: update /etc/driver_aliases
3790Sstevel@tonic-gate * m_flag: update /etc/minor_perm
3800Sstevel@tonic-gate * -p: update /etc/security/device_policy
3810Sstevel@tonic-gate * -P: update /etc/security/extra_privs
382*10842SJerry.Gilliam@Sun.COM * if force_flag is specified continue w/ the next operation
3830Sstevel@tonic-gate */
3840Sstevel@tonic-gate if (d_flag) {
3850Sstevel@tonic-gate int err = NOERR;
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate if (m_flag) {
3880Sstevel@tonic-gate /*
3890Sstevel@tonic-gate * On a running system, we first need to
3900Sstevel@tonic-gate * remove devfs's idea of the minor perms.
3910Sstevel@tonic-gate * We don't have any ability to do this singly
3920Sstevel@tonic-gate * at this point.
3930Sstevel@tonic-gate */
3948565SJerry.Gilliam@Sun.COM if ((n_flag == 0) &&
3958565SJerry.Gilliam@Sun.COM (basedir == NULL || (strcmp(basedir, "/") == 0))) {
3960Sstevel@tonic-gate rval = devfs_rm_minor_perm(driver_name,
3970Sstevel@tonic-gate log_minorperm_error);
3980Sstevel@tonic-gate if (rval) {
3990Sstevel@tonic-gate (void) fprintf(stderr,
4000Sstevel@tonic-gate gettext(ERR_UPDATE_PERM),
4010Sstevel@tonic-gate driver_name);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if ((error = delete_entry(minor_perm,
4060Sstevel@tonic-gate driver_name, ":", perms)) != NOERR) {
4070Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_ENTRY),
4080Sstevel@tonic-gate driver_name, minor_perm);
4090Sstevel@tonic-gate err = error;
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate /*
4120Sstevel@tonic-gate * Notify running system of new minor perm state
4130Sstevel@tonic-gate */
4148565SJerry.Gilliam@Sun.COM if ((n_flag == 0) &&
4158565SJerry.Gilliam@Sun.COM (basedir == NULL || (strcmp(basedir, "/") == 0))) {
4160Sstevel@tonic-gate rval = devfs_add_minor_perm(driver_name,
4170Sstevel@tonic-gate log_minorperm_error);
4180Sstevel@tonic-gate if (rval) {
4190Sstevel@tonic-gate (void) fprintf(stderr,
4200Sstevel@tonic-gate gettext(ERR_UPDATE_PERM),
4210Sstevel@tonic-gate driver_name);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate if (i_flag) {
4278831SJerry.Gilliam@Sun.COM found = get_major_no(driver_name, name_to_major);
4288831SJerry.Gilliam@Sun.COM if (found == ERROR) {
4298831SJerry.Gilliam@Sun.COM (void) fprintf(stderr, gettext(ERR_MAX_MAJOR),
4308831SJerry.Gilliam@Sun.COM name_to_major);
4318831SJerry.Gilliam@Sun.COM err_exit();
4328831SJerry.Gilliam@Sun.COM }
4338831SJerry.Gilliam@Sun.COM
4348831SJerry.Gilliam@Sun.COM if (found == UNIQUE) {
4358831SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
4368831SJerry.Gilliam@Sun.COM gettext(ERR_NOT_INSTALLED), driver_name);
4378831SJerry.Gilliam@Sun.COM err_exit();
4388831SJerry.Gilliam@Sun.COM }
4398831SJerry.Gilliam@Sun.COM
4408831SJerry.Gilliam@Sun.COM major_num = (major_t)found;
4418831SJerry.Gilliam@Sun.COM
4428831SJerry.Gilliam@Sun.COM /*
4438831SJerry.Gilliam@Sun.COM * verify that the aliases to be deleted exist
4448831SJerry.Gilliam@Sun.COM * before removal. With -f, failing to
4458831SJerry.Gilliam@Sun.COM * remove an alias is not an error so we
4468831SJerry.Gilliam@Sun.COM * can continue on to update the kernel.
4478831SJerry.Gilliam@Sun.COM */
4488831SJerry.Gilliam@Sun.COM error = NOERR;
4499268SJerry.Gilliam@Sun.COM rval = aliases_exist(aliases);
4508831SJerry.Gilliam@Sun.COM if (rval == ERROR && (force_flag == 0)) {
4518831SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
4528831SJerry.Gilliam@Sun.COM gettext(ERR_ALIAS_NOT_BOUND),
4538831SJerry.Gilliam@Sun.COM driver_name);
4548831SJerry.Gilliam@Sun.COM if (err != NOERR)
4558831SJerry.Gilliam@Sun.COM err = rval;
4568831SJerry.Gilliam@Sun.COM }
4578831SJerry.Gilliam@Sun.COM if (rval == NOERR)
4588831SJerry.Gilliam@Sun.COM error = delete_entry(driver_aliases,
4598831SJerry.Gilliam@Sun.COM driver_name, ":", aliases);
4608831SJerry.Gilliam@Sun.COM if (error != NOERR && (force_flag == 0)) {
4610Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_ENTRY),
4620Sstevel@tonic-gate driver_name, driver_aliases);
4630Sstevel@tonic-gate if (err != NOERR)
4640Sstevel@tonic-gate err = error;
4650Sstevel@tonic-gate }
4668831SJerry.Gilliam@Sun.COM
4678831SJerry.Gilliam@Sun.COM /*
4688831SJerry.Gilliam@Sun.COM * optionally update the running system - not -b.
4698831SJerry.Gilliam@Sun.COM * Unless -f is specified, error if one or more
4708831SJerry.Gilliam@Sun.COM * devices remain bound to the alias.
4718831SJerry.Gilliam@Sun.COM */
4728831SJerry.Gilliam@Sun.COM if (err == NOERR && update_conf) {
4738831SJerry.Gilliam@Sun.COM /* paranoia - if we crash whilst configuring */
4748831SJerry.Gilliam@Sun.COM sync();
475*10842SJerry.Gilliam@Sun.COM
476*10842SJerry.Gilliam@Sun.COM config_flags = 0;
477*10842SJerry.Gilliam@Sun.COM if (verbose_flag)
478*10842SJerry.Gilliam@Sun.COM config_flags |= CONFIG_DRV_VERBOSE;
479*10842SJerry.Gilliam@Sun.COM if (force_flag)
480*10842SJerry.Gilliam@Sun.COM config_flags |= CONFIG_DRV_FORCE;
4818831SJerry.Gilliam@Sun.COM error = unconfig_driver(driver_name, major_num,
482*10842SJerry.Gilliam@Sun.COM aliases, config_flags);
4838831SJerry.Gilliam@Sun.COM if (error == ERROR && force_flag == 0) {
4848831SJerry.Gilliam@Sun.COM (void) fprintf(stderr,
4858831SJerry.Gilliam@Sun.COM gettext(ERR_DEV_IN_USE),
4868831SJerry.Gilliam@Sun.COM driver_name);
4878831SJerry.Gilliam@Sun.COM if (err != NOERR)
4888831SJerry.Gilliam@Sun.COM err = error;
4898831SJerry.Gilliam@Sun.COM }
4908831SJerry.Gilliam@Sun.COM }
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate
4930Sstevel@tonic-gate if (priv != NULL) {
4940Sstevel@tonic-gate if ((error = delete_entry(extra_privs, driver_name, ":",
4950Sstevel@tonic-gate priv)) != NOERR) {
4960Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_ENTRY),
4970Sstevel@tonic-gate driver_name, extra_privs);
4980Sstevel@tonic-gate if (err != NOERR)
4990Sstevel@tonic-gate err = error;
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate if (policy != NULL) {
5040Sstevel@tonic-gate if ((error = delete_plcy_entry(device_policy,
5055001Sjg policy)) != NOERR) {
5060Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_NO_ENTRY),
5070Sstevel@tonic-gate driver_name, device_policy);
5080Sstevel@tonic-gate if (err != NOERR)
5090Sstevel@tonic-gate err = error;
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate if (err == NOERR && update_conf) {
5140Sstevel@tonic-gate if (i_flag || m_flag) {
5150Sstevel@tonic-gate /* try to unload the driver */
5160Sstevel@tonic-gate (void) unload_drv(driver_name,
5170Sstevel@tonic-gate force_flag, verbose_flag);
5180Sstevel@tonic-gate }
5190Sstevel@tonic-gate /* reload the policy */
5200Sstevel@tonic-gate if (policy != NULL)
5210Sstevel@tonic-gate load_driver(driver_name, verbose_flag);
5220Sstevel@tonic-gate }
5230Sstevel@tonic-gate exit_unlock();
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate return (err);
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate /* driver name must exist (for update_conf stuff) */
5290Sstevel@tonic-gate major = get_major_no(driver_name, name_to_major);
5300Sstevel@tonic-gate if (major == ERROR) {
5310Sstevel@tonic-gate err_exit();
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate /*
5350Sstevel@tonic-gate * Update driver.conf file:
5360Sstevel@tonic-gate * First try to unload driver module. If it fails, there may
5370Sstevel@tonic-gate * be attached devices using the old driver.conf properties,
5380Sstevel@tonic-gate * so we cannot safely update driver.conf
5390Sstevel@tonic-gate *
5400Sstevel@tonic-gate * The user may specify -f to force a driver.conf update.
5410Sstevel@tonic-gate * In this case, we will update driver.conf cache. All attached
5420Sstevel@tonic-gate * devices still reference old driver.conf properties, including
5430Sstevel@tonic-gate * driver global properties. Devices attached in the future will
5440Sstevel@tonic-gate * referent properties in the updated driver.conf file.
5450Sstevel@tonic-gate */
5460Sstevel@tonic-gate if (update_conf) {
5470Sstevel@tonic-gate (void) unload_drv(driver_name, force_flag, verbose_flag);
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate if ((modctl(MODUNLOADDRVCONF, major) != 0) ||
550*10842SJerry.Gilliam@Sun.COM (modctl(MODLOADDRVCONF, major, 0) != 0)) {
5510Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_DRVCONF),
5520Sstevel@tonic-gate driver_name);
5530Sstevel@tonic-gate err_exit();
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate if (verbose_flag) {
5570Sstevel@tonic-gate (void) fprintf(stderr, gettext(DRVCONF_UPDATED),
5580Sstevel@tonic-gate driver_name);
5590Sstevel@tonic-gate }
5605878Sjg load_driver(driver_name, verbose_flag);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate
5630Sstevel@tonic-gate exit_unlock();
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate return (NOERR);
5660Sstevel@tonic-gate }
567