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