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