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