xref: /illumos-gate/usr/src/cmd/modload/add_drv.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <libelf.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/buf.h>
35 #include <wait.h>
36 #include <unistd.h>
37 #include <libintl.h>
38 #include <sys/modctl.h>
39 #include <sys/systeminfo.h>
40 #include <string.h>
41 #include <limits.h>
42 #include <locale.h>
43 #include <ftw.h>
44 #include <sys/sunddi.h>
45 #include <libdevinfo.h>
46 #include <sys/sysmacros.h>
47 #include <fcntl.h>
48 #include "addrem.h"
49 #include "errmsg.h"
50 #include "plcysubr.h"
51 
52 /*
53  * globals needed for libdevinfo - there is no way to pass
54  * private data to the find routine.
55  */
56 struct dev_list {
57 	int clone;
58 	char *dev_name;
59 	char *driver_name;
60 	struct dev_list *next;
61 };
62 
63 static char *kelf_desc = NULL;
64 static int kelf_type = ELFCLASSNONE;
65 
66 static char *new_drv;
67 static struct dev_list *conflict_lst = NULL;
68 
69 static int module_not_found(char *, char *, int, char **, int *);
70 static void usage();
71 static int update_minor_perm(char *, char *);
72 static int devfs_update_minor_perm(char *, char *, char *);
73 static int update_driver_classes(char *, char *);
74 static int drv_name_conflict(di_node_t);
75 static int devfs_node(di_node_t node, void *arg);
76 static int drv_name_match(char *, int, char *, char *);
77 static void print_drv_conflict_info(int);
78 static void check_dev_dir(int);
79 static int dev_node(const char *, const struct stat *, int, struct FTW *);
80 static void free_conflict_list(struct dev_list *);
81 static int clone(di_node_t node);
82 static int elf_type(char *, char **, int *);
83 static int correct_location(char *, char **, int *);
84 static int isaspec_drvmod_discovery();
85 static void remove_slashes(char *);
86 static int update_extra_privs(char *, char *privlist);
87 static int ignore_root_basedir();
88 
89 int
90 main(int argc, char *argv[])
91 {
92 	int opt;
93 	major_t major_num;
94 	char driver_name[FILENAME_MAX + 1];
95 	int driver_name_size = sizeof (driver_name);
96 	char path_driver_name[MAXPATHLEN];
97 	int path_driver_name_size = sizeof (path_driver_name);
98 	char *perms = NULL;
99 	char *aliases = NULL;
100 	char *classes = NULL;
101 	char *policy = NULL;
102 	char *priv = NULL;
103 	int noload_flag = 0;
104 	int verbose_flag = 0;
105 	int force_flag = 0;
106 	int i_flag = 0;
107 	int c_flag = 0;
108 	int m_flag = 0;
109 	int cleanup_flag = 0;
110 	int server = 0;
111 	char *basedir = NULL;
112 	int is_unique;
113 	char *slash;
114 	int conflict;
115 	di_node_t root_node;	/* for device tree snapshot */
116 	char *drvelf_desc = NULL;
117 	int drvelf_type = ELFCLASSNONE;
118 
119 	moddir = NULL;
120 
121 	(void) setlocale(LC_ALL, "");
122 #if	!defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
123 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
124 #endif
125 	(void) textdomain(TEXT_DOMAIN);
126 
127 	/*  must be run by root */
128 
129 	if (geteuid() != 0) {
130 		(void) fprintf(stderr, gettext(ERR_NOT_ROOT));
131 		exit(1);
132 	}
133 
134 	while ((opt = getopt(argc, argv, "vfm:ni:b:c:p:P:")) != EOF) {
135 		switch (opt) {
136 		case 'm' :
137 			m_flag = 1;
138 			perms = optarg;
139 			break;
140 		case 'f':
141 			force_flag++;
142 			break;
143 		case 'v':
144 			verbose_flag++;
145 			break;
146 		case 'n':
147 			noload_flag++;
148 			break;
149 		case 'i' :
150 			i_flag = 1;
151 			aliases = optarg;
152 			if (check_space_within_quote(aliases) == ERROR) {
153 				(void) fprintf(stderr, gettext(ERR_NO_SPACE),
154 					aliases);
155 				exit(1);
156 			}
157 			break;
158 		case 'b' :
159 			server = 1;
160 			basedir = optarg;
161 			if (strcmp(basedir, "/") == 0 &&
162 			    ignore_root_basedir()) {
163 				server = 0;
164 				basedir = NULL;
165 			}
166 			break;
167 		case 'c':
168 			c_flag = 1;
169 			classes = optarg;
170 			break;
171 		case 'p':
172 			policy = optarg;
173 			break;
174 		case 'P':
175 			priv = optarg;
176 			break;
177 		case '?' :
178 		default:
179 			usage();
180 			exit(1);
181 		}
182 	}
183 
184 
185 	if (argv[optind] != NULL) {
186 		if (strlcpy(driver_name, argv[optind], driver_name_size) >=
187 		    driver_name_size) {
188 			(void) fprintf(stderr, gettext(ERR_DRVNAME_TOO_LONG),
189 			    driver_name_size, argv[optind]);
190 			exit(1);
191 		}
192 
193 		/*
194 		 * check for extra args
195 		 */
196 		if ((optind + 1) != argc) {
197 			usage();
198 			exit(1);
199 		}
200 
201 	} else {
202 		usage();
203 		exit(1);
204 	}
205 
206 	/*
207 	 * Fail if add_drv was invoked with a pathname prepended to the
208 	 * driver_name argument.
209 	 *
210 	 * Check driver_name for any '/'s. If found, we assume that caller
211 	 * is trying to specify a pathname.
212 	 */
213 
214 	slash = strchr(driver_name, '/');
215 	if (slash) {
216 		remove_slashes(driver_name);
217 
218 		/* extract module name out of path */
219 		slash = strrchr(driver_name, '/');
220 
221 		if (slash != NULL) {
222 			(void) fprintf(stderr, gettext(ERR_PATH_SPEC),
223 			    driver_name);
224 			(void) fprintf(stderr, gettext(ERR_INSTALL_FAIL),
225 			    ++slash);
226 			exit(1);
227 		}
228 	}
229 	new_drv = driver_name;
230 
231 	/* set up add_drv filenames */
232 	if ((build_filenames(basedir)) == ERROR) {
233 		exit(1);
234 	}
235 
236 	/* must be only running version of add_drv/rem_drv */
237 	enter_lock();
238 
239 	if ((check_perms_aliases(m_flag, i_flag)) == ERROR)
240 		err_exit();
241 
242 	if ((check_name_to_major(R_OK | W_OK)) == ERROR)
243 		err_exit();
244 
245 	/*
246 	 * check validity of options
247 	 */
248 	if (m_flag) {
249 		if ((check_perm_opts(perms)) == ERROR) {
250 			usage();
251 			err_exit();
252 		}
253 	}
254 
255 	if (i_flag) {
256 		if (aliases != NULL)
257 			if ((aliases_unique(aliases)) == ERROR)
258 				err_exit();
259 	}
260 
261 	if (priv != NULL && check_priv_entry(priv, 1) != 0)
262 		err_exit();
263 
264 	if (policy != NULL &&
265 	    (policy = check_plcy_entry(policy, driver_name, B_FALSE)) == NULL) {
266 		err_exit();
267 	}
268 
269 	if ((unique_driver_name(driver_name, name_to_major,
270 	    &is_unique)) == ERROR)
271 		err_exit();
272 
273 	if (is_unique == NOT_UNIQUE) {
274 		(void) fprintf(stderr, gettext(ERR_NOT_UNIQUE), driver_name);
275 		err_exit();
276 	}
277 
278 	if (!server) {
279 		if (elf_type("/dev/ksyms", &kelf_desc, &kelf_type) == ERROR) {
280 			(void) fprintf(stderr, gettext(ERR_KERNEL_ISA));
281 			err_exit();
282 		}
283 
284 		if (module_not_found(driver_name, path_driver_name,
285 		    path_driver_name_size, &drvelf_desc, &drvelf_type) ==
286 		    ERROR) {
287 			(void) fprintf(stderr, gettext(ERR_NOMOD), driver_name);
288 			err_exit();
289 		}
290 
291 		/*
292 		 * If the driver location is incorrect but the kernel and driver
293 		 * are of the same ISA, suggest a fix.  If the driver location
294 		 * is incorrect and the ISA's mismatch, notify the user that
295 		 * this driver can not be loaded on this kernel.  In both cases,
296 		 * do not attempt to load the driver module.
297 		 */
298 
299 		if (correct_location(path_driver_name, &drvelf_desc,
300 		    (&drvelf_type)) == ERROR) {
301 			noload_flag = 1;
302 			if (kelf_type == drvelf_type) {
303 				(void) fprintf(stderr,
304 				    gettext(ERR_SOL_LOCATION), driver_name,
305 				    driver_name);
306 			} else {
307 				(void) fprintf(stderr,
308 				    gettext(ERR_NOT_LOADABLE),
309 				    drvelf_desc, driver_name, kelf_desc);
310 			}
311 
312 		/*
313 		 * The driver location is correct.  Verify that the kernel ISA
314 		 * and driver ISA match.  If they do not match, produce an error
315 		 * message and do not attempt to load the module.
316 		 */
317 
318 		} else if (kelf_type != drvelf_type) {
319 			noload_flag = 1;
320 			(void) fprintf(stderr, gettext(ERR_ISA_MISMATCH),
321 			    kelf_desc, driver_name, drvelf_desc);
322 			(void) fprintf(stderr, gettext(ERR_NOT_LOADABLE),
323 			    drvelf_desc, driver_name, kelf_desc);
324 		}
325 
326 
327 		/*
328 		 * Check for a more specific driver conflict - see
329 		 * PSARC/1995/239
330 		 * Note that drv_name_conflict() can return -1 for error
331 		 * or 1 for a conflict.  Since the default is to fail unless
332 		 * the -f flag is specified, we don't bother to differentiate.
333 		 */
334 		if ((root_node = di_init("/", DINFOSUBTREE | DINFOMINOR))
335 		    == DI_NODE_NIL) {
336 			(void) fprintf(stderr, gettext(ERR_DEVTREE));
337 			conflict = -1;
338 		} else {
339 			conflict = drv_name_conflict(root_node);
340 			di_fini(root_node);
341 		}
342 
343 		if (conflict) {
344 			/*
345 			 * if the force flag is not set, we fail here
346 			 */
347 			if (!force_flag) {
348 				(void) fprintf(stderr,
349 				    gettext(ERR_INSTALL_FAIL), driver_name);
350 				(void) fprintf(stderr, "Device managed by "
351 				    "another driver.\n");
352 				if (verbose_flag)
353 					print_drv_conflict_info(force_flag);
354 				err_exit();
355 			}
356 			/*
357 			 * The force flag was specified so we print warnings
358 			 * and install the driver anyways
359 			 */
360 			if (verbose_flag)
361 				print_drv_conflict_info(force_flag);
362 			free_conflict_list(conflict_lst);
363 		}
364 	}
365 
366 	if ((update_name_to_major(driver_name, &major_num, server)) == ERROR) {
367 		err_exit();
368 	}
369 
370 	cleanup_flag |= CLEAN_NAM_MAJ;
371 
372 
373 	if (m_flag) {
374 		cleanup_flag |= CLEAN_MINOR_PERM;
375 		if (update_minor_perm(driver_name, perms) == ERROR) {
376 			remove_entry(cleanup_flag, driver_name);
377 			err_exit();
378 		}
379 	}
380 
381 	if (i_flag) {
382 		cleanup_flag |= CLEAN_DRV_ALIAS;
383 		if (update_driver_aliases(driver_name, aliases) == ERROR) {
384 			remove_entry(cleanup_flag, driver_name);
385 			err_exit();
386 
387 		}
388 	}
389 
390 	if (c_flag) {
391 		cleanup_flag |= CLEAN_DRV_CLASSES;
392 		if (update_driver_classes(driver_name, classes) == ERROR) {
393 			remove_entry(cleanup_flag, driver_name);
394 			err_exit();
395 
396 		}
397 	}
398 
399 	if (priv != NULL) {
400 		cleanup_flag |= CLEAN_DRV_PRIV;
401 		if (update_extra_privs(driver_name, priv) == ERROR) {
402 			remove_entry(cleanup_flag, driver_name);
403 			err_exit();
404 		}
405 	}
406 
407 	if (policy != NULL) {
408 		cleanup_flag |= CLEAN_DEV_POLICY;
409 		if (update_device_policy(device_policy, policy, B_FALSE)
410 								== ERROR) {
411 			remove_entry(cleanup_flag, driver_name);
412 			err_exit();
413 		}
414 	}
415 
416 	if (server) {
417 		(void) fprintf(stderr, gettext(BOOT_CLIENT));
418 	} else {
419 		/*
420 		 * paranoia - if we crash whilst configuring the driver
421 		 * this might avert possible file corruption.
422 		 */
423 		sync();
424 
425 		if (config_driver(driver_name, major_num, aliases, classes,
426 		    cleanup_flag, verbose_flag) == ERROR) {
427 			err_exit();
428 		}
429 		if (m_flag) {
430 			if (devfs_update_minor_perm(basedir,
431 			    driver_name, perms) == ERROR) {
432 				err_exit();
433 			}
434 		}
435 		if (!noload_flag)
436 			load_driver(driver_name, verbose_flag);
437 		else
438 			(void) fprintf(stderr, gettext(ERR_CONFIG_NOLOAD),
439 			    driver_name);
440 	}
441 
442 	if (create_reconfig(basedir) == ERROR)
443 		(void) fprintf(stderr, gettext(ERR_CREATE_RECONFIG));
444 
445 	cleanup_moddir();
446 	exit_unlock();
447 
448 	if (verbose_flag) {
449 		(void) fprintf(stderr, gettext(DRIVER_INSTALLED), driver_name);
450 	}
451 
452 	return (NOERR);
453 }
454 
455 /*
456  *	Searches for the driver module along the module path (returned
457  *	from modctl) and returns a string (in drv_path) representing the path
458  *	where drv_name was found.  ERROR is returned if function is unable
459  *	to locate drv_name.
460  */
461 int
462 module_not_found(char *drv_name, char *drv_path, int drv_path_size,
463     char **drvelf_desc, int *drvelf_type_ptr)
464 {
465 	struct stat buf;
466 	char data [MAXMODPATHS];
467 	char pathsave [MAXMODPATHS];
468 	char *next = data;
469 	struct drvmod_dir *curdir = NULL;
470 	char foundpath[MAXPATHLEN];
471 
472 	if (modctl(MODGETPATH, NULL, data) != 0) {
473 		(void) fprintf(stderr, gettext(ERR_MODPATH));
474 		return (ERROR);
475 	}
476 	(void) strcpy(pathsave, data);
477 	next = strtok(data, MOD_SEP);
478 
479 	if (isaspec_drvmod_discovery() == ERROR)
480 		err_exit();
481 
482 	curdir = moddir;
483 	while (curdir != NULL) {
484 		while (next != NULL) {
485 			(void) snprintf(foundpath, sizeof (foundpath),
486 			    "%s/drv/%s/%s", next, curdir->direc, drv_name);
487 			if ((stat(foundpath, &buf) == 0) &&
488 			    ((buf.st_mode & S_IFMT) == S_IFREG)) {
489 				if (elf_type(foundpath, drvelf_desc,
490 				    drvelf_type_ptr) == ERROR) {
491 					(void) fprintf(stderr,
492 					    gettext(ERR_INSTALL_FAIL),
493 					    drv_name);
494 					err_exit();
495 				}
496 				remove_slashes(foundpath);
497 
498 				if (strlcpy(drv_path, foundpath, drv_path_size)
499 				    >= drv_path_size) {
500 					return (ERROR);
501 				}
502 
503 				return (NOERR);
504 			}
505 			next = strtok((char *)NULL, MOD_SEP);
506 		}
507 		(void) strcpy(data, pathsave);
508 		next = strtok(data, MOD_SEP);
509 		curdir = curdir->next;
510 	}
511 
512 	return (ERROR);
513 }
514 
515 static void
516 usage()
517 {
518 	(void) fprintf(stderr, gettext(USAGE));
519 }
520 
521 static int
522 update_driver_classes(
523 	char *driver_name,
524 	char *classes)
525 {
526 	/* make call to update the classes file */
527 	return (append_to_file(driver_name, classes, driver_classes,
528 	    ' ', "\t"));
529 }
530 
531 static int
532 update_minor_perm(
533 	char *driver_name,
534 	char *perm_list)
535 {
536 	return (append_to_file(driver_name, perm_list, minor_perm, ',', ":"));
537 }
538 
539 
540 /*
541  * Complete the minor perm update by communicating the minor perm
542  * data to the kernel.  This information is used by devfs to ensure
543  * that devices always have the correct permissions when attached.
544  * The minor perm file must be updated and the driver configured
545  * in the system for this step to complete correctly.
546  */
547 static int
548 devfs_update_minor_perm(
549 	char *basedir,
550 	char *driver_name,
551 	char *perm_list)
552 {
553 	int rval = 0;
554 
555 	if (basedir == NULL || (strcmp(basedir, "/") == 0)) {
556 		if (devfs_add_minor_perm(driver_name,
557 		    log_minorperm_error) != 0) {
558 			(void) fprintf(stderr,
559 			    gettext(ERR_UPDATE_PERM), driver_name);
560 		}
561 	}
562 	return (rval);
563 }
564 
565 static int
566 update_extra_privs(
567 	char *driver_name,
568 	char *privlist)
569 {
570 	return (append_to_file(driver_name, privlist, extra_privs, ',', ":"));
571 }
572 
573 /*
574  * Check to see if the driver we are adding is a more specific
575  * driver for a device already attached to a less specific driver.
576  * In other words, see if this driver comes earlier on the compatible
577  * list of a device already attached to another driver.
578  * If so, the new node will not be created (since the device is
579  * already attached) but when the system reboots, it will attach to
580  * the new driver but not have a node - we need to warn the user
581  * if this is the case.
582  */
583 static int
584 drv_name_conflict(di_node_t root_node)
585 {
586 	/*
587 	 * walk the device tree checking each node
588 	 */
589 	if (di_walk_node(root_node, DI_WALK_SIBFIRST, NULL, devfs_node) == -1) {
590 		free_conflict_list(conflict_lst);
591 		conflict_lst = (struct dev_list *)NULL;
592 		(void) fprintf(stderr, gettext(ERR_DEVTREE));
593 		return (-1);
594 	}
595 
596 	if (conflict_lst == NULL)
597 		/* no conflicts found */
598 		return (0);
599 	else
600 		/* conflicts! */
601 		return (1);
602 }
603 
604 /*
605  * called via di_walk_node().
606  * called for each node in the device tree.  We skip nodes that:
607  *	1. are not hw nodes (since they cannot have generic names)
608  *	2. that do not have a compatible property
609  *	3. whose node name = binding name.
610  *	4. nexus nodes - the name of a generic nexus node would
611  *	not be affected by a driver change.
612  * Otherwise, we parse the compatible property, if we find a
613  * match with the new driver before we find a match with the
614  * current driver, then we have a conflict and we save the
615  * node away.
616  */
617 /*ARGSUSED*/
618 static int
619 devfs_node(di_node_t node, void *arg)
620 {
621 	char *binding_name, *node_name, *compat_names, *devfsnm;
622 	struct dev_list *new_entry;
623 	char strbuf[MAXPATHLEN];
624 	int n_names;
625 
626 	/*
627 	 * if there is no compatible property, we don't
628 	 * have to worry about any conflicts.
629 	 */
630 	if ((n_names = di_compatible_names(node, &compat_names)) <= 0)
631 		return (DI_WALK_CONTINUE);
632 
633 	/*
634 	 * if the binding name and the node name match, then
635 	 * either no driver existed that could be bound to this node,
636 	 * or the driver name is the same as the node name.
637 	 */
638 	binding_name = di_binding_name(node);
639 	node_name = di_node_name(node);
640 	if ((binding_name == NULL) || (strcmp(node_name, binding_name) == 0))
641 		return (DI_WALK_CONTINUE);
642 
643 	/*
644 	 * we can skip nexus drivers since they do not
645 	 * have major/minor number info encoded in their
646 	 * /devices name and therefore won't change.
647 	 */
648 	if (di_driver_ops(node) & DI_BUS_OPS)
649 		return (DI_WALK_CONTINUE);
650 
651 	/*
652 	 * check for conflicts
653 	 * If we do find that the new driver is a more specific driver
654 	 * than the driver already attached to the device, we'll save
655 	 * away the node name for processing later.
656 	 */
657 	if (drv_name_match(compat_names, n_names, binding_name, new_drv)) {
658 		devfsnm = di_devfs_path(node);
659 		(void) sprintf(strbuf, "%s%s", DEVFS_ROOT, devfsnm);
660 		di_devfs_path_free(devfsnm);
661 		new_entry = (struct dev_list *)calloc(1,
662 		    sizeof (struct dev_list));
663 		if (new_entry == (struct dev_list *)NULL) {
664 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
665 			err_exit();
666 		}
667 		/* save the /devices name */
668 		if ((new_entry->dev_name = strdup(strbuf)) == NULL) {
669 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
670 			free(new_entry);
671 			err_exit();
672 		}
673 		/* save the driver name */
674 		if ((new_entry->driver_name = strdup(di_driver_name(node)))
675 		    == NULL) {
676 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
677 			free(new_entry->dev_name);
678 			free(new_entry);
679 			err_exit();
680 		}
681 		/* check to see if this is a clone device */
682 		if (clone(node))
683 			new_entry->clone = 1;
684 
685 		/* add it to the list */
686 		new_entry->next = conflict_lst;
687 		conflict_lst = new_entry;
688 	}
689 
690 	return (DI_WALK_CONTINUE);
691 }
692 
693 static int
694 clone(di_node_t node)
695 {
696 	di_minor_t minor = DI_MINOR_NIL;
697 
698 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
699 		if (di_minor_type(minor) == DDM_ALIAS)
700 			return (1);
701 	}
702 	return (0);
703 }
704 /*
705  * check to see if the new_name shows up on the compat list before
706  * the cur_name (driver currently attached to the device).
707  */
708 static int
709 drv_name_match(char *compat_names, int n_names, char *cur_name, char *new_name)
710 {
711 	int i, ret = 0;
712 
713 	if (strcmp(cur_name, new_name) == 0)
714 		return (0);
715 
716 	/* parse the coompatible list */
717 	for (i = 0; i < n_names; i++) {
718 		if (strcmp(compat_names, new_name) == 0) {
719 			ret = 1;
720 			break;
721 		}
722 		if (strcmp(compat_names, cur_name) == 0) {
723 			break;
724 		}
725 		compat_names += strlen(compat_names) + 1;
726 	}
727 	return (ret);
728 }
729 
730 /*
731  * A more specific driver is being added for a device already attached
732  * to a less specific driver.  Print out a general warning and if
733  * the force flag was passed in, give the user a hint as to what
734  * nodes may be affected in /devices and /dev
735  */
736 static void
737 print_drv_conflict_info(int force)
738 {
739 	struct dev_list *ptr;
740 
741 	if (conflict_lst == NULL)
742 		return;
743 	if (force) {
744 		(void) fprintf(stderr,
745 		    "\nA reconfiguration boot must be performed to "
746 		    "complete the\n");
747 		(void) fprintf(stderr, "installation of this driver.\n");
748 	}
749 
750 	if (force) {
751 		(void) fprintf(stderr,
752 		    "\nThe following entries in /devices will be "
753 		    "affected:\n\n");
754 	} else {
755 		(void) fprintf(stderr,
756 		    "\nDriver installation failed because the following\n");
757 		(void) fprintf(stderr,
758 		    "entries in /devices would be affected:\n\n");
759 	}
760 
761 	ptr = conflict_lst;
762 	while (ptr != NULL) {
763 		(void) fprintf(stderr, "\t%s", ptr->dev_name);
764 		if (ptr->clone)
765 			(void) fprintf(stderr, " (clone device)\n");
766 		else
767 			(void) fprintf(stderr, "[:*]\n");
768 		(void) fprintf(stderr, "\t(Device currently managed by driver "
769 		    "\"%s\")\n\n", ptr->driver_name);
770 		ptr = ptr->next;
771 	}
772 	check_dev_dir(force);
773 }
774 
775 /*
776  * use nftw to walk through /dev looking for links that match
777  * an entry in the conflict list.
778  */
779 static void
780 check_dev_dir(int force)
781 {
782 	int  walk_flags = FTW_PHYS | FTW_MOUNT;
783 	int ft_depth = 15;
784 
785 	if (force) {
786 		(void) fprintf(stderr, "\nThe following entries in /dev will "
787 		    "be affected:\n\n");
788 	} else {
789 		(void) fprintf(stderr, "\nThe following entries in /dev would "
790 		    "be affected:\n\n");
791 	}
792 
793 	(void) nftw("/dev", dev_node, ft_depth, walk_flags);
794 
795 	(void) fprintf(stderr, "\n");
796 }
797 
798 /*
799  * checks a /dev link to see if it matches any of the conlficting
800  * /devices nodes in conflict_lst.
801  */
802 /*ARGSUSED1*/
803 static int
804 dev_node(const char *node, const struct stat *node_stat, int flags,
805 	struct FTW *ftw_info)
806 {
807 	char linkbuf[MAXPATHLEN];
808 	struct dev_list *ptr;
809 
810 	if (readlink(node, linkbuf, MAXPATHLEN) == -1)
811 		return (0);
812 
813 	ptr = conflict_lst;
814 
815 	while (ptr != NULL) {
816 		if (strstr(linkbuf, ptr->dev_name) != NULL)
817 			(void) fprintf(stderr, "\t%s\n", node);
818 		ptr = ptr->next;
819 	}
820 	return (0);
821 }
822 
823 
824 static void
825 free_conflict_list(struct dev_list *list)
826 {
827 	struct dev_list *save;
828 
829 	/* free up any dev_list structs we allocated. */
830 	while (list != NULL) {
831 		save = list;
832 		list = list->next;
833 		free(save->dev_name);
834 		free(save);
835 	}
836 }
837 
838 int
839 elf_type(char *file, char **elfdesc, int *elf_type_ptr)
840 {
841 	int fd;
842 	Elf *elf;
843 	char *ident;
844 
845 	if ((fd = open(file, O_RDONLY)) < 0) {
846 		(void) fprintf(stderr, gettext(ERR_CANNOT_OPEN), file,
847 		    strerror(errno));
848 		return (ERROR);
849 	}
850 	if (elf_version(EV_CURRENT) == EV_NONE) {
851 		(void) fprintf(stderr, gettext(ERR_ELF_VERSION),
852 		    elf_errmsg(-1));
853 		(void) close(fd);
854 		return (ERROR);
855 	}
856 	elf = elf_begin(fd, ELF_C_READ, NULL);
857 	if (elf_kind(elf) != ELF_K_ELF) {
858 		(void) fprintf(stderr, gettext(ERR_ELF_KIND), file);
859 		(void) elf_end(elf);
860 		(void) close(fd);
861 		return (ERROR);
862 	}
863 	ident = elf_getident(elf, 0);
864 	if (ident[EI_CLASS] == ELFCLASS32) {
865 		*elfdesc = "32";
866 		*elf_type_ptr = ELFCLASS32;
867 	} else if (ident[EI_CLASS] == ELFCLASS64) {
868 		*elfdesc = "64";
869 		*elf_type_ptr = ELFCLASS64;
870 	} else {
871 		*elfdesc = "none";
872 		*elf_type_ptr = ELFCLASSNONE;
873 	}
874 	(void) elf_end(elf);
875 	(void) close(fd);
876 	return (NOERR);
877 }
878 
879 int
880 correct_location(char *drv_path, char **drvelf_desc, int *drvelf_type_ptr)
881 {
882 
883 	char copy_drv_path[MAXPATHLEN];
884 	char *token = copy_drv_path;
885 
886 	(void) strcpy(copy_drv_path, drv_path);
887 
888 	if (elf_type(drv_path, drvelf_desc, drvelf_type_ptr) == ERROR) {
889 		err_exit();
890 	}
891 	token = strtok(copy_drv_path, DIR_SEP);
892 	while (token != NULL) {
893 		if (strcmp("drv", token) == 0) {
894 			token = strtok((char *)NULL, DIR_SEP);
895 			if (strcmp(DRVDIR64, token) == 0) {
896 				if (*drvelf_type_ptr == ELFCLASS64)
897 					return (NOERR);
898 				(void) fprintf(stderr, gettext(ERR_LOCATION),
899 				    *drvelf_desc, drv_path);
900 				return (ERROR);
901 			} else {
902 				if (*drvelf_type_ptr == ELFCLASS32)
903 					return (NOERR);
904 				(void) fprintf(stderr, gettext(ERR_LOCATION),
905 				    *drvelf_desc, drv_path);
906 				return (ERROR);
907 			}
908 		} else {
909 			token = strtok((char *)NULL, DIR_SEP);
910 		}
911 	}
912 	return (ERROR);
913 }
914 
915 /*
916  * Creates a two-element linked list of isa-specific subdirectories to
917  * search for each driver, which is is used by the function
918  * module_not_found() to convert the isa-independent modpath into an
919  * isa-specific path .  The list is ordered depending on the machine
920  * architecture and instruction set architecture, corresponding to the
921  * order in which module_not_found() will search for the driver.  This
922  * routine relies on an architecture not having more than two
923  * sub-architectures (e.g., sparc/sparcv9 or i386/amd64).
924  */
925 int
926 isaspec_drvmod_discovery()
927 {
928 	char arch[SYS_NMLN];
929 
930 	moddir = (struct drvmod_dir *)calloc(1, sizeof (struct drvmod_dir));
931 	if (moddir == NULL) {
932 		(void) fprintf(stderr, gettext(ERR_NO_MEM));
933 		return (ERROR);
934 	}
935 
936 	if (sysinfo(SI_ARCHITECTURE, arch, sizeof (arch)) == -1) {
937 		(void) fprintf(stderr, gettext(ERR_SYSINFO_ARCH));
938 		return (ERROR);
939 	}
940 
941 	if (strcmp(arch, "sparc") == 0 || strcmp(arch, "i386") == 0) {
942 		moddir->next = (struct drvmod_dir *)
943 		    calloc(1, sizeof (struct drvmod_dir));
944 		if (moddir->next == NULL) {
945 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
946 			return (ERROR);
947 		}
948 		if (kelf_type == ELFCLASS64) {
949 			(void) strcpy(moddir->direc, DRVDIR64);
950 			(void) strcpy(moddir->next->direc, "");
951 		} else {
952 			(void) strcpy(moddir->direc, "");
953 			(void) strcpy(moddir->next->direc, DRVDIR64);
954 		}
955 		moddir->next->next = NULL;
956 		return (NOERR);
957 	} else {
958 		(void) fprintf(stderr, gettext(ERR_ARCH_NOT_SUPPORTED), arch);
959 		return (ERROR);
960 	}
961 }
962 
963 void
964 remove_slashes(char *path)
965 {
966 	char *slash = path;
967 	char *remain_str;
968 	int pathlen;
969 
970 	while ((slash = strchr(slash, '/')) != NULL) {
971 		remain_str = ++slash;
972 		while (*remain_str == '/')
973 			++remain_str;
974 		if (slash != remain_str)
975 			(void) strcpy(slash, remain_str);
976 	}
977 
978 	pathlen = strlen(path);
979 	if ((pathlen > 1) && path[pathlen - 1] == '/')
980 		path[pathlen - 1] = '\0';
981 }
982 
983 /*
984  * This is for ITU floppies to add packages to the miniroot
985  */
986 static int
987 ignore_root_basedir(void)
988 {
989 	struct stat statbuf;
990 
991 	return (stat("/ADD_DRV_IGNORE_ROOT_BASEDIR", &statbuf) == 0);
992 }
993