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