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_minor_perm(driver_name, perm_list, minor_perm)); 542 } 543 544 545 /* 546 * Complete the minor perm update by communicating the minor perm 547 * data to the kernel. This information is used by devfs to ensure 548 * that devices always have the correct permissions when attached. 549 * The minor perm file must be updated and the driver configured 550 * in the system for this step to complete correctly. 551 */ 552 static int 553 devfs_update_minor_perm( 554 char *basedir, 555 char *driver_name) 556 { 557 int rval = 0; 558 559 if (basedir == NULL || (strcmp(basedir, "/") == 0)) { 560 if (devfs_add_minor_perm(driver_name, 561 log_minorperm_error) != 0) { 562 (void) fprintf(stderr, 563 gettext(ERR_UPDATE_PERM), driver_name); 564 } 565 } 566 return (rval); 567 } 568 569 static int 570 update_extra_privs( 571 char *driver_name, 572 char *privlist) 573 { 574 return (append_to_file(driver_name, privlist, extra_privs, 575 ',', ":", 0)); 576 } 577 578 /* 579 * Check to see if the driver we are adding is a more specific 580 * driver for a device already attached to a less specific driver. 581 * In other words, see if this driver comes earlier on the compatible 582 * list of a device already attached to another driver. 583 * If so, the new node will not be created (since the device is 584 * already attached) but when the system reboots, it will attach to 585 * the new driver but not have a node - we need to warn the user 586 * if this is the case. 587 */ 588 static int 589 drv_name_conflict(di_node_t root_node) 590 { 591 /* 592 * walk the device tree checking each node 593 */ 594 if (di_walk_node(root_node, DI_WALK_SIBFIRST, NULL, devfs_node) == -1) { 595 free_conflict_list(conflict_lst); 596 conflict_lst = (struct dev_list *)NULL; 597 (void) fprintf(stderr, gettext(ERR_DEVTREE)); 598 return (-1); 599 } 600 601 if (conflict_lst == NULL) 602 /* no conflicts found */ 603 return (0); 604 else 605 /* conflicts! */ 606 return (1); 607 } 608 609 /* 610 * called via di_walk_node(). 611 * called for each node in the device tree. We skip nodes that: 612 * 1. are not hw nodes (since they cannot have generic names) 613 * 2. that do not have a compatible property 614 * 3. whose node name = binding name. 615 * 4. nexus nodes - the name of a generic nexus node would 616 * not be affected by a driver change. 617 * Otherwise, we parse the compatible property, if we find a 618 * match with the new driver before we find a match with the 619 * current driver, then we have a conflict and we save the 620 * node away. 621 */ 622 /*ARGSUSED*/ 623 static int 624 devfs_node(di_node_t node, void *arg) 625 { 626 char *binding_name, *node_name, *compat_names, *devfsnm; 627 struct dev_list *new_entry; 628 char strbuf[MAXPATHLEN]; 629 int n_names; 630 631 /* 632 * if there is no compatible property, we don't 633 * have to worry about any conflicts. 634 */ 635 if ((n_names = di_compatible_names(node, &compat_names)) <= 0) 636 return (DI_WALK_CONTINUE); 637 638 /* 639 * if the binding name and the node name match, then 640 * either no driver existed that could be bound to this node, 641 * or the driver name is the same as the node name. 642 */ 643 binding_name = di_binding_name(node); 644 node_name = di_node_name(node); 645 if ((binding_name == NULL) || (strcmp(node_name, binding_name) == 0)) 646 return (DI_WALK_CONTINUE); 647 648 /* 649 * we can skip nexus drivers since they do not 650 * have major/minor number info encoded in their 651 * /devices name and therefore won't change. 652 */ 653 if (di_driver_ops(node) & DI_BUS_OPS) 654 return (DI_WALK_CONTINUE); 655 656 /* 657 * check for conflicts 658 * If we do find that the new driver is a more specific driver 659 * than the driver already attached to the device, we'll save 660 * away the node name for processing later. 661 */ 662 if (drv_name_match(compat_names, n_names, binding_name, new_drv)) { 663 devfsnm = di_devfs_path(node); 664 (void) snprintf(strbuf, sizeof (strbuf), 665 "%s%s", DEVFS_ROOT, devfsnm); 666 di_devfs_path_free(devfsnm); 667 new_entry = (struct dev_list *)calloc(1, 668 sizeof (struct dev_list)); 669 if (new_entry == (struct dev_list *)NULL) { 670 (void) fprintf(stderr, gettext(ERR_NO_MEM)); 671 err_exit(); 672 } 673 /* save the /devices name */ 674 if ((new_entry->dev_name = strdup(strbuf)) == NULL) { 675 (void) fprintf(stderr, gettext(ERR_NO_MEM)); 676 free(new_entry); 677 err_exit(); 678 } 679 /* save the driver name */ 680 if ((new_entry->driver_name = strdup(di_driver_name(node))) 681 == NULL) { 682 (void) fprintf(stderr, gettext(ERR_NO_MEM)); 683 free(new_entry->dev_name); 684 free(new_entry); 685 err_exit(); 686 } 687 /* check to see if this is a clone device */ 688 if (clone(node)) 689 new_entry->clone = 1; 690 691 /* add it to the list */ 692 new_entry->next = conflict_lst; 693 conflict_lst = new_entry; 694 } 695 696 return (DI_WALK_CONTINUE); 697 } 698 699 static int 700 clone(di_node_t node) 701 { 702 di_minor_t minor = DI_MINOR_NIL; 703 704 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 705 if (di_minor_type(minor) == DDM_ALIAS) 706 return (1); 707 } 708 return (0); 709 } 710 /* 711 * check to see if the new_name shows up on the compat list before 712 * the cur_name (driver currently attached to the device). 713 */ 714 static int 715 drv_name_match(char *compat_names, int n_names, char *cur_name, char *new_name) 716 { 717 int i, ret = 0; 718 719 if (strcmp(cur_name, new_name) == 0) 720 return (0); 721 722 /* parse the coompatible list */ 723 for (i = 0; i < n_names; i++) { 724 if (strcmp(compat_names, new_name) == 0) { 725 ret = 1; 726 break; 727 } 728 if (strcmp(compat_names, cur_name) == 0) { 729 break; 730 } 731 compat_names += strlen(compat_names) + 1; 732 } 733 return (ret); 734 } 735 736 /* 737 * A more specific driver is being added for a device already attached 738 * to a less specific driver. Print out a general warning and if 739 * the force flag was passed in, give the user a hint as to what 740 * nodes may be affected in /devices and /dev 741 */ 742 static void 743 print_drv_conflict_info(int force) 744 { 745 struct dev_list *ptr; 746 747 if (conflict_lst == NULL) 748 return; 749 if (force) { 750 (void) fprintf(stderr, 751 "\nA reconfiguration boot must be performed to " 752 "complete the\n"); 753 (void) fprintf(stderr, "installation of this driver.\n"); 754 } 755 756 if (force) { 757 (void) fprintf(stderr, 758 "\nThe following entries in /devices will be " 759 "affected:\n\n"); 760 } else { 761 (void) fprintf(stderr, 762 "\nDriver installation failed because the following\n"); 763 (void) fprintf(stderr, 764 "entries in /devices would be affected:\n\n"); 765 } 766 767 ptr = conflict_lst; 768 while (ptr != NULL) { 769 (void) fprintf(stderr, "\t%s", ptr->dev_name); 770 if (ptr->clone) 771 (void) fprintf(stderr, " (clone device)\n"); 772 else 773 (void) fprintf(stderr, "[:*]\n"); 774 (void) fprintf(stderr, "\t(Device currently managed by driver " 775 "\"%s\")\n\n", ptr->driver_name); 776 ptr = ptr->next; 777 } 778 check_dev_dir(force); 779 } 780 781 /* 782 * use nftw to walk through /dev looking for links that match 783 * an entry in the conflict list. 784 */ 785 static void 786 check_dev_dir(int force) 787 { 788 int walk_flags = FTW_PHYS | FTW_MOUNT; 789 int ft_depth = 15; 790 791 if (force) { 792 (void) fprintf(stderr, "\nThe following entries in /dev will " 793 "be affected:\n\n"); 794 } else { 795 (void) fprintf(stderr, "\nThe following entries in /dev would " 796 "be affected:\n\n"); 797 } 798 799 (void) nftw("/dev", dev_node, ft_depth, walk_flags); 800 801 (void) fprintf(stderr, "\n"); 802 } 803 804 /* 805 * checks a /dev link to see if it matches any of the conlficting 806 * /devices nodes in conflict_lst. 807 */ 808 /*ARGSUSED1*/ 809 static int 810 dev_node(const char *node, const struct stat *node_stat, int flags, 811 struct FTW *ftw_info) 812 { 813 char linkbuf[MAXPATHLEN]; 814 struct dev_list *ptr; 815 816 if (readlink(node, linkbuf, MAXPATHLEN) == -1) 817 return (0); 818 819 ptr = conflict_lst; 820 821 while (ptr != NULL) { 822 if (strstr(linkbuf, ptr->dev_name) != NULL) 823 (void) fprintf(stderr, "\t%s\n", node); 824 ptr = ptr->next; 825 } 826 return (0); 827 } 828 829 830 static void 831 free_conflict_list(struct dev_list *list) 832 { 833 struct dev_list *save; 834 835 /* free up any dev_list structs we allocated. */ 836 while (list != NULL) { 837 save = list; 838 list = list->next; 839 free(save->dev_name); 840 free(save); 841 } 842 } 843 844 int 845 elf_type(char *file, char **elfdesc, int *elf_type_ptr) 846 { 847 int fd; 848 Elf *elf; 849 char *ident; 850 851 if ((fd = open(file, O_RDONLY)) < 0) { 852 (void) fprintf(stderr, gettext(ERR_CANNOT_OPEN), file, 853 strerror(errno)); 854 return (ERROR); 855 } 856 if (elf_version(EV_CURRENT) == EV_NONE) { 857 (void) fprintf(stderr, gettext(ERR_ELF_VERSION), 858 elf_errmsg(-1)); 859 (void) close(fd); 860 return (ERROR); 861 } 862 elf = elf_begin(fd, ELF_C_READ, NULL); 863 if (elf_kind(elf) != ELF_K_ELF) { 864 (void) fprintf(stderr, gettext(ERR_ELF_KIND), file); 865 (void) elf_end(elf); 866 (void) close(fd); 867 return (ERROR); 868 } 869 ident = elf_getident(elf, 0); 870 if (ident[EI_CLASS] == ELFCLASS32) { 871 *elfdesc = "32"; 872 *elf_type_ptr = ELFCLASS32; 873 } else if (ident[EI_CLASS] == ELFCLASS64) { 874 *elfdesc = "64"; 875 *elf_type_ptr = ELFCLASS64; 876 } else { 877 *elfdesc = "none"; 878 *elf_type_ptr = ELFCLASSNONE; 879 } 880 (void) elf_end(elf); 881 (void) close(fd); 882 return (NOERR); 883 } 884 885 int 886 correct_location(char *drv_path, char **drvelf_desc, int *drvelf_type_ptr) 887 { 888 889 char copy_drv_path[MAXPATHLEN]; 890 char *token = copy_drv_path; 891 892 (void) strcpy(copy_drv_path, drv_path); 893 894 if (elf_type(drv_path, drvelf_desc, drvelf_type_ptr) == ERROR) { 895 err_exit(); 896 } 897 token = strtok(copy_drv_path, DIR_SEP); 898 while (token != NULL) { 899 if (strcmp("drv", token) == 0) { 900 token = strtok((char *)NULL, DIR_SEP); 901 if (strcmp(DRVDIR64, token) == 0) { 902 if (*drvelf_type_ptr == ELFCLASS64) 903 return (NOERR); 904 (void) fprintf(stderr, gettext(ERR_LOCATION), 905 *drvelf_desc, drv_path); 906 return (ERROR); 907 } else { 908 if (*drvelf_type_ptr == ELFCLASS32) 909 return (NOERR); 910 (void) fprintf(stderr, gettext(ERR_LOCATION), 911 *drvelf_desc, drv_path); 912 return (ERROR); 913 } 914 } else { 915 token = strtok((char *)NULL, DIR_SEP); 916 } 917 } 918 return (ERROR); 919 } 920 921 /* 922 * Creates a two-element linked list of isa-specific subdirectories to 923 * search for each driver, which is is used by the function 924 * module_not_found() to convert the isa-independent modpath into an 925 * isa-specific path . The list is ordered depending on the machine 926 * architecture and instruction set architecture, corresponding to the 927 * order in which module_not_found() will search for the driver. This 928 * routine relies on an architecture not having more than two 929 * sub-architectures (e.g., sparc/sparcv9 or i386/amd64). 930 */ 931 int 932 isaspec_drvmod_discovery() 933 { 934 char arch[SYS_NMLN]; 935 936 moddir = (struct drvmod_dir *)calloc(1, sizeof (struct drvmod_dir)); 937 if (moddir == NULL) { 938 (void) fprintf(stderr, gettext(ERR_NO_MEM)); 939 return (ERROR); 940 } 941 942 if (sysinfo(SI_ARCHITECTURE, arch, sizeof (arch)) == -1) { 943 (void) fprintf(stderr, gettext(ERR_SYSINFO_ARCH)); 944 return (ERROR); 945 } 946 947 if (strcmp(arch, "sparc") == 0 || strcmp(arch, "i386") == 0) { 948 moddir->next = (struct drvmod_dir *) 949 calloc(1, sizeof (struct drvmod_dir)); 950 if (moddir->next == NULL) { 951 (void) fprintf(stderr, gettext(ERR_NO_MEM)); 952 return (ERROR); 953 } 954 if (kelf_type == ELFCLASS64) { 955 (void) strcpy(moddir->direc, DRVDIR64); 956 (void) strcpy(moddir->next->direc, ""); 957 } else { 958 (void) strcpy(moddir->direc, ""); 959 (void) strcpy(moddir->next->direc, DRVDIR64); 960 } 961 moddir->next->next = NULL; 962 return (NOERR); 963 } else { 964 (void) fprintf(stderr, gettext(ERR_ARCH_NOT_SUPPORTED), arch); 965 return (ERROR); 966 } 967 } 968 969 void 970 remove_slashes(char *path) 971 { 972 char *slash = path; 973 char *remain_str; 974 int pathlen; 975 976 while ((slash = strchr(slash, '/')) != NULL) { 977 remain_str = ++slash; 978 while (*remain_str == '/') 979 ++remain_str; 980 if (slash != remain_str) 981 (void) strcpy(slash, remain_str); 982 } 983 984 pathlen = strlen(path); 985 if ((pathlen > 1) && path[pathlen - 1] == '/') 986 path[pathlen - 1] = '\0'; 987 } 988 989 /* 990 * This is for ITU floppies to add packages to the miniroot 991 */ 992 static int 993 ignore_root_basedir(void) 994 { 995 struct stat statbuf; 996 997 return (stat("/ADD_DRV_IGNORE_ROOT_BASEDIR", &statbuf) == 0); 998 } 999