diff options
author | Jerry Gilliam <Jerry.Gilliam@Sun.COM> | 2009-07-13 19:06:47 -0700 |
---|---|---|
committer | Jerry Gilliam <Jerry.Gilliam@Sun.COM> | 2009-07-13 19:06:47 -0700 |
commit | 24492170008a257707ba12f4ae2f2af9bdf925a9 (patch) | |
tree | 24ca94821512c6ccb36855b9fc93c0d75bb8e9ce /usr/src/ucbcmd | |
parent | 4634c44f9aff3ceaf027e46cee4258d7ab23b40f (diff) | |
download | illumos-joyent-24492170008a257707ba12f4ae2f2af9bdf925a9.tar.gz |
PSARC/2009/346 EOF UCB Device Names
6850098 EOF ucb compatibility device names
Diffstat (limited to 'usr/src/ucbcmd')
-rw-r--r-- | usr/src/ucbcmd/Makefile | 3 | ||||
-rw-r--r-- | usr/src/ucbcmd/ucblinks/Makefile | 63 | ||||
-rw-r--r-- | usr/src/ucbcmd/ucblinks/ucblinks.awk | 214 | ||||
-rw-r--r-- | usr/src/ucbcmd/ucblinks/ucblinks.c | 1502 | ||||
-rw-r--r-- | usr/src/ucbcmd/ucblinks/ucblinks.sh | 237 |
5 files changed, 1 insertions, 2018 deletions
diff --git a/usr/src/ucbcmd/Makefile b/usr/src/ucbcmd/Makefile index c3372038a2..fa2da2685b 100644 --- a/usr/src/ucbcmd/Makefile +++ b/usr/src/ucbcmd/Makefile @@ -60,7 +60,6 @@ COMMON_SUBDIRS= \ touch \ tr \ tset \ - ucblinks \ users \ vipw \ whereis \ @@ -71,7 +70,7 @@ sparc_SUBDIRS= sbcp SUBDIRS= $(COMMON_SUBDIRS) $($(MACH)_SUBDIRS) # commands messaged -MSGSUBDIRS = biff install.d mkstr rusage shutdown ucblinks +MSGSUBDIRS = biff install.d mkstr rusage shutdown BWOSDIRS= diff --git a/usr/src/ucbcmd/ucblinks/Makefile b/usr/src/ucbcmd/ucblinks/Makefile deleted file mode 100644 index 57938b8f64..0000000000 --- a/usr/src/ucbcmd/ucblinks/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 1998,2001 by Sun Microsystems, Inc. -# All rights reserved. -# -#ident "%Z%%M% %I% %E% SMI" - -PROG= ucblinks -OBJS= $(PROG).o - -SHLIBEXFILES= ucblinks.sh -SHLIBFILES= ucblinks.awk - -include ../Makefile.ucbcmd - -ROOTLIBEXFILES= $(ROOTLIB)/$(SHLIBEXFILES) -ROOTLIBFILES= $(ROOTLIB)/$(SHLIBFILES) -GROUP = sys -$(ROOTLIBEXFILES) := FILEMODE = 555 -$(ROOTLIBFILES) := FILEMODE = 644 -$(ROOTLIB) := GROUP = bin -$(PROG) := GROUP = bin - -LDLIBS += -ldevinfo - -CLEANFILES += $(OBJS) - - -.KEEP_STATE: - -all: $(PROG) $(SHLIBEXFILES) $(SHLIBFILES) - -install: all $(ROOTPROG) $(ROOTLIB) $(ROOTLIBEXFILES) $(ROOTLIBFILES) - -$(ROOTLIB): - $(INS.dir) - -clean: - $(RM) $(CLEANFILES) - -lint: - -include ../Makefile.ucbtarg diff --git a/usr/src/ucbcmd/ucblinks/ucblinks.awk b/usr/src/ucbcmd/ucblinks/ucblinks.awk deleted file mode 100644 index fa54ea99f3..0000000000 --- a/usr/src/ucbcmd/ucblinks/ucblinks.awk +++ /dev/null @@ -1,214 +0,0 @@ -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -#ident "%Z%%M% %I% %E% SMI" -# -# This awk-script is the rule-base used in previous release for creating -# compatibility-mode names. -# -# WARNING: these rules are no longer used by default. ucblinks -# is now a binary, not a script. This rule-base can still -# be used, however, by running ucblinks with the option -# "-e /usr/ucblib/ucblinks.awk". See the ucblinks(1B) man -# page for more information. -# -# The idea is to create the names as symbolic links to their SunOS5 -# counterparts by preference. If no counterpart exists a direct link to the -# devfs "/devices" directory is made. -# -# It does this base on input of the existing devices in the system. -# The format of the input file is: -# -# driver-name \t minor number \t [b|c] \t /devices-name \t first-minor-component -# -# That is, -# -# $1 driver-name -# $2 minor number -# $3 b(lock) or c(haracter) device -# $4 devices-directory name; relative to /dev (../devices/xxx) -# $5 first minor component name (string between ':' and nextr ',' -# in last path-component of the /devices-name) -# -# and these are referred to throughout the script. -# -# The output of the script-rules are lines of the form: -# -# devname["device-link-fullname"] = "compatname"; -# devdir["device-link-fullname"] = "compatdir"; -# -# The device-link-fullname should be relative to the directory in which the -# SunOS5 link is expected to be found. 'compatdir' is that directory name, -# FOLLOWED BY A SLASH. 'compatname' is the compatability name that should be -# generated. -# - -#--------------------------------------------------------------------------- -# DATABASE: Only modify below this line! -# -# -# -# The following devices need no changes, since the 4.x and 5.x names -# are the same: -# -# console tty mem kmem null zero drum mouse klog kbd dump tcp udp -# mbmem mbio -# -# nit vd eeprom openprom des pp* vp* vpc* - -$3 == "b" && $1 == "fd" { - if ($5 == "c") - out(sprintf("%s%d%s", $1, $2/8, $5), "./", - sprintf("%s%d", $1, $2/8)); - else - out(sprintf("%s%d%s", $1, $2/8, $5), "./"); - } -$3 == "c" && $1 == "fd" { - if ($5 == "c") - out(sprintf("r%s%d%s", $1, $2/8, $5), "./", - sprintf("r%s%d", $1, $2/8)); - else - out(sprintf("r%s%d%s", $1, $2/8, $5), "./"); - } - - -# -# Standard disks (all bar IPI) -# -# Note special 'cddev' array test to make sure device is not a CD device -# in the case of a SCSI disk -# -$3 == "b" && (($1 == "sd" && !cddev[$4]) || $1 == "xd" || $1 == "xy") { - if ($2 < 8) - out(sprintf("%s%d%s", $1, 3, $5), "dsk/"); - else if ($2 >= 24 && $2 < 32) - out(sprintf("%s%d%s", $1, 0, $5), "dsk/"); - else - out(sprintf("%s%d%s", $1, $2/8, $5), "dsk/"); - } -$3 == "c" && (($1 == "sd" && !cddev[$4]) || $1 == "xd" || $1 == "xy") { - if ($2 < 8) - out(sprintf("r%s%d%s", $1, 3, $5), "rdsk/"); - else if ($2 >= 24 && $2 < 32) - out(sprintf("r%s%d%s", $1, 0, $5), "rdsk/"); - else - out(sprintf("r%s%d%s", $1, $2/8, $5), "rdsk/"); - } -# -# SCSI CD drive -# -$1 == "sd" && cddev[$4] && $5 == "c" { - if (cdnum[$2] "" == "") cdnum[$2] = cdno++; - if ($3 == "c") pfx = "r"; else pfx = ""; - out(pfx "sr" cdnum[$2], pfx "dsk/"); - } -# -# Next assumes IPI unit number entirely within minor -# (that is, 5.0 numbering rather than 4.1 numbering) -# -$3 == "b" && $1 == "id" { - out(sprintf("id%x%s", $2, $5), "dsk/"); - } -$3 == "c" && $1 == "id" { - out(sprintf("rid%x%s", $2, $5), "rdsk/"); - } -# -# Tape drives -# -# SCSI and XT Tape Drives -# -($1 == "st" || $1 == "xt") && NF == 5 && $5 !~ /^[bn]/ { - if (($2 % 128) < 64) break; # Not BSD-flavour - drive = ($2%4) + ((int($2/128)%32) * 4); - den = int($2/8) % 4; - if ($1 == "xt") $1 == "mt"; # xt drives appear as mt devices - if ($5 ~ /n$/) pfx = "nr"; else pfx = "r"; - link = pfx $1 ((den * 8) + drive); - if (tapelink[link] "" == "") { - out(link, "rmt/"); - tapelink[link] = 1; - } - } -# -# Obsolete drive entries -# -$1 == "mt" { - if (($2 % 8) >= 4) { - link = "rmt" $2; - if (tapelink[link] "" == "") { - out(link, "rmt/", "nrmt" ($2 - 4)); - tapelink[link] = 1; - } - } - else { - link = "rmt" $2; - if (tapelink[link] "" == "") { - out(link, "rmt/"); - tapelink[link] = 1; - } - } - } - -# -# Wierd Archive tape stuff -# -$1 == "ar" && NF == 5 && $5 !~ /n$/ { - link = "rar" ($2/4); - if (tapelink[link] "" == "") { - out(link, "rmt/"); - tapelink[link] = 1; - } - } -$1 == "ar" && NF == 5 && $5 ~ /n$/ { - link = "nrar" (($2-16)/4); - if (tapelink[link] "" == "") { - out(link, "rmt/"); - tapelink[link] = 1; - } - } -# -# Screen-buffers are easy -# -$1 == "bwtwo" || $1 == "cgthree" || $1 == "cgsix" || $1 == "cgfour" || $1 == "cgfourteen" || $1 == "cgeight" || $1 == "cgnine" || $1 == "cgtwelve" { - out("" $5, "fbs/"); - } -# -# This catches the on-board ports, the 1st and second SCSI-board uarts, -# as well as the newer fast-serial "se" ports. -# Depends on the driver creating the right names. -# -($1 == "zs" || $1 == "se" || $1 == "su") && $4 !~ /,cu$/ && ttbeenhere != 1 { - ttbeenhere = 1; - system("x=`ls term`; for i in $x ; do rm -f tty$i; ln -s term/$i tty$i ; done"); - } -# -# XXX Bus device support yet to go in, so the following are TBD: -# -# sbus vme16d16 vme24d16 vme32d16 vme32d32 -# -# -# XXX Other device support to be added as drivers are added: -# -# mcp oct mti -# diff --git a/usr/src/ucbcmd/ucblinks/ucblinks.c b/usr/src/ucbcmd/ucblinks/ucblinks.c deleted file mode 100644 index 92e3357ed3..0000000000 --- a/usr/src/ucbcmd/ucblinks/ucblinks.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * ucblinks - create 4.x /dev compatibility names - * - * The basic algorithm is: - * - * find block and character special files in /devices with major - * numbers of devices that need compatibility names - * - * determine compatibility names from minor number, driver name, and - * /devices name - * - * create symlinks for the compatibility names to 5.x /dev - * entries if possible or /devices entries if necessary - * - * The name space that ucblinks creates has a number of problems. - * Unfortunately people have, to an unknown extent, come to depend - * on the broken name space. Fixing ucblinks to be more compatible - * with 4.x would make it less compatible with previous releases of - * 5.x. The places were it is broken are noted throughout the code - * and summarized here: - * - * 1157501 ucblinks creates completely broken 4.x links for IPI - * 1157616 ucblinks does 0 <-> 3 swap for disks when it shouldn't - * 1157617 ucblinks creates /dev/rxt* names instead of /dev/rmt* - * 1157970 ucblinks creates incompatible and overlapping links for tapes - */ - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <ftw.h> -#include <sys/types.h> -#include <sys/mkdev.h> -#include <sys/param.h> -#include <locale.h> -#include <libdevinfo.h> - -static char *progname; -static char *rootdir = NULL; /* an alternate root to / */ -static int debug = 0; /* only print what is right and wrong */ -static int depth; /* num descriptors to use for nftw() */ - -/* - * Each block or character device entry in /devices is - * represented by one of these structures. - */ -struct devices_ent { - char *devicename; /* /devices name */ - char *min_comp; /* minor component of name */ - int minor; /* minor number */ - int israw; /* character device? */ - int iscd; /* cdrom? */ - int issd; /* simple sd use? */ - int csum; /* checksum of name */ - struct symlink *linksto; /* symlinks to this name */ - struct drvinfo *drp; /* driver for this name */ - struct devices_ent *next; /* for hash table */ -}; - -/* - * There are a set of devices for which we'll create - * compatibility names. Each driver for the devices - * is represented by a drvinfo structure. The rule_func - * field points to a rule function for that driver. - */ -typedef void (rule_func_t)(struct devices_ent *); - -struct drvinfo { - char *name; /* driver name from name_to_major */ - int major; /* major number */ - int index; /* index, for sorting */ - rule_func_t *rule_func; /* rule for this driver */ -}; - -/* - * The rules for the drivers. - */ -static rule_func_t rule_ar; /* Archive tapes */ -static rule_func_t rule_atapicd; /* PCI cdrom drive */ -static rule_func_t rule_fbs; /* frame buffers */ -static rule_func_t rule_fd; /* floppy disk */ -static rule_func_t rule_id; /* IPI disks */ -static rule_func_t rule_mt; /* mt tapes */ -static rule_func_t rule_sd; /* scsi disks */ -static rule_func_t rule_stxt; /* scsi and xt tapes */ -static rule_func_t rule_xdxy; /* xd and xy disks */ -static rule_func_t rule_zs; /* zs serial */ - -#define NOMAJ (-1) /* no entry in /etc/name_to_major */ - -/* - * Below are the devices for which we create compatibility - * links. Some are obsolete as they have no /etc/name_to_major - * entry, but they're here to be compatible with the awk-based - * version of ucblinks. This list should be in alphabetical - * order with the index field set for the position in the array - * (we could compute it at runtime, but we know it so we set - * it here). See dcomp() for more about sort order. - */ -static struct drvinfo drvs[] = { - { "ar", NOMAJ, 0, rule_ar }, /* obsolete */ - { "atapicd", NOMAJ, 1, rule_atapicd }, - { "bwtwo", NOMAJ, 1, rule_fbs }, - { "cgeight", NOMAJ, 2, rule_fbs }, - { "cgfour", NOMAJ, 3, rule_fbs }, /* obsolete */ - { "cgfourteen", NOMAJ, 4, rule_fbs }, /* obsolete */ - { "cgnine", NOMAJ, 5, rule_fbs }, - { "cgsix", NOMAJ, 6, rule_fbs }, - { "cgthree", NOMAJ, 7, rule_fbs }, - { "cgtwelve", NOMAJ, 8, rule_fbs }, /* obsolete */ - { "fd", NOMAJ, 9, rule_fd }, - { "id", NOMAJ, 10, rule_id }, - { "mt", NOMAJ, 11, rule_mt }, /* obsolete */ - { "sd", NOMAJ, 12, rule_sd }, - { "st", NOMAJ, 13, rule_stxt }, - { "xd", NOMAJ, 14, rule_xdxy }, - { "xt", NOMAJ, 15, rule_stxt }, - { "xy", NOMAJ, 16, rule_xdxy }, - { "zs", NOMAJ, 17, rule_zs }, - { "se", NOMAJ, 18, rule_zs }, /* Fast serial */ - { "su", NOMAJ, 19, rule_zs }, /* PC/16550 serial */ - { NULL }, -}; - -/* - * Each symlink in /dev is represented by a symlink structure. - * We record all of them, not just those that point to interesting - * /devices entries, because when we have determined what a - * compatibility link should point to we want to know if it - * already points to the correct target and it is much cheaper to - * look it up in our list than to make a system call. - */ -struct symlink { - char *linkname; /* name of link */ - char *target; /* what the link points to */ - int csum; /* checksum of linkname */ - int already; /* link already made */ - struct symlink *hashnext; /* next on hash list */ - struct symlink *deventnext; /* next on /devices ent list */ -}; - -/* - * The /devices entries and the /dev symlinks are kept in - * (separate) hash tables. HASHSIZE was pulled out of the - * air although it seems to work ok and we get a good - * distribution. Some theory says this should be prime, - * but I don't understand why and that would make "% HASHSIZE" - * a call to mod routine rather than a simple bit-wise and. - */ -#define HASHSIZE 256 -static struct devices_ent *de_hashtab[HASHSIZE]; -static struct devices_ent **devices_list; -static int num_devices_ents; - -static struct symlink *link_hashtab[HASHSIZE]; - -/* - * Buffers used by the rule functions to construct link names. - */ -static char namebuf[MAXPATHLEN + 1]; -static char namebuf2[MAXPATHLEN + 1]; - -/* - * Handle used for the link database - */ -static di_devlink_handle_t link_handle; - -static void exec_script(char **argv); -static void get_major_nums(void); -static void set_depth(void); -static void get_devices(void); -static void get_dev_links(void); -static void call_device_rules(void); -static int is_blank(char *); - -/* - * The command-line arguments to ucblinks are: - * - * -r specify a root relative to which ./devices and ./dev - * are used to create links. - * - * -e the awk-based ucblinks had a default rule-base and - * allowed alternate rule-bases with -e. If the user - * specifies a rule-base we run the awk-based ucblinks - * and pass all the args to it. - * - * -d undocumented debug option (like the awk-based version); - * print what would be created, fixed, or is already correct. - */ -int -main(int argc, char **argv) -{ - int c; - int err = 0; - - (void) setlocale(LC_ALL, ""); -#if !defined(TEXT_DOMAIN) -#define TEXT_DOMAIN "SYS_TEST" -#endif - (void) textdomain(TEXT_DOMAIN); - - progname = argv[0]; /* save program name for error messages */ - - while ((c = getopt(argc, argv, "r:e:d")) != EOF) { - switch (c) { - case 'r': - rootdir = optarg; - break; - case 'e': - exec_script(argv); - /* exec_script doesn't return */ - break; - case 'd': - debug = 1; - break; - case '?': - default: - err = 1; - break; - } - } - - if (err || (optind != argc)) { - (void) fprintf(stderr, gettext("usage: %s [ -r rootdir ] " - "[ -e rulebase ]\n"), progname); - exit(1); - } - - get_major_nums(); - - set_depth(); - - get_devices(); - - get_dev_links(); - - call_device_rules(); - - return (0); -} - -/* - * A utility function so we don't have to check the return - * value of malloc for NULL all over the place. - */ -static void * -xmalloc(size_t size) -{ - void *p; - - p = malloc(size); - if (p != NULL) - return (p); - else { - (void) fprintf(stderr, gettext("%s: malloc failed, " - "out of memory\n"), progname); - exit(1); -#ifdef lint - return (NULL); -#endif - } -} - -/* - * A utility function so we don't have to check the return - * value of strdup (which gets space from malloc) for NULL - * all over the place. - */ -static char * -xstrdup(const char *s1) -{ - char *s2; - - s2 = strdup(s1); - if (s2 != NULL) - return (s2); - else { - (void) fprintf(stderr, gettext("%s: malloc failed, " - "out of memory\n"), progname); - exit(1); -#ifdef lint - return (NULL); -#endif - } -} - -/* - * A utility function that prepends the program name to - * perror output. - */ -static void -xperror(const char *errstr) -{ - int len1, len2; - char *msg; - - len1 = strlen(progname); - len2 = strlen(errstr); - - msg = xmalloc(len1 + 2 + len2 + 1); - (void) sprintf(msg, "%s: %s", progname, errstr); - perror(msg); - free(msg); -} - -/* - * The awk-based ucblinks allowed an alternate rule-base with - * the -e option. Obviously we don't do awk, so pass off all - * our command-line arguments to the awk-based version which - * was moved from /usr/ucb to /usr/ucblib. - */ -#define SCRIPT "/usr/ucblib/ucblinks.sh" - -static void -exec_script(char **argv) -{ - argv[0] = SCRIPT; - if (execv(SCRIPT, argv) == -1) - xperror(gettext("cannot execute " SCRIPT)); - exit(1); -} - -/* - * Construct a name with the rootdir, if specified with -r, - * prepended. Don't free this because when rootdir isn't - * set we return what was passed in (this is called at most - * four times so it's no big deal to not free it). - */ -static char * -root_name(char *name) -{ - int len1, len2; - char *buf; - - if (rootdir == NULL) - return (name); - else { - len1 = strlen(rootdir); - len2 = strlen(name); - buf = xmalloc(len1 + len2 + 1); - - (void) strcpy(buf, rootdir); - (void) strcpy(buf + len1, name); - return (buf); - } -} - -/* - * Read /etc/name_to_major to find the major numbers associated - * with the names in the drvinfo array. We silently ignore - * what we don't understand. - */ -static void -get_major_nums(void) -{ - FILE *fp; - char line[FILENAME_MAX*2 + 1]; /* use the same size as add_drv does */ - char *name, *maj, *end, *cp; - int majnum; - struct drvinfo *drp; - - fp = fopen("/etc/name_to_major", "r"); - if (fp == NULL) { - (void) fprintf(stderr, gettext("%s: cannot open " - "/etc/name_to_major\n"), progname); - exit(1); - } - - while (fgets(line, sizeof (line), fp) != NULL) { - /* cut off comments starting with '#' */ - if ((cp = strchr(line, '#')) != NULL) - *cp = '\0'; - /* ignore comment or blank lines */ - if (is_blank(line)) - continue; - name = strtok(line, " \t"); /* must not be NULL */ - if ((maj = strtok(NULL, "\n")) == NULL) - continue; - majnum = strtol(maj, &end, 10); - if (end == maj) - continue; - /* - * Compare against our list and set the major - * number it it's a name we care about. - */ - for (drp = drvs; drp->name != NULL; drp++) { - if (strcmp(name, drp->name) == 0) { - drp->major = majnum; - break; - } - } - } - - (void) fclose(fp); -} - -/* - * Pick some reasonable number of file descriptors to let nftw() - * have open at a time. The number shouldn't be more than the - * currently available file descriptors but should be at least equal - * to the depth of the trees we're traversing for efficiency. Of - * course we don't know how deep the trees are before hand, so - * just use half the allowable descriptors which usually comes - * out to 32 which is usually more than enough. Using a depth - * smaller than the tree depth doesn't prevent traversal of the tree, - * it just makes it slower. sysconf() can't fail, but if it does - * use a depth of 1. - */ -static void -set_depth(void) -{ - long num; - - num = sysconf(_SC_OPEN_MAX); - if (num == -1) - depth = 1; - else - depth = num / 2; -} - -/* - * Given a major number look it up in our list to see if it - * is associated with a device that needs a compatibility - * link. We cache the last lookup to avoid going through - * the list each time. - */ -static struct drvinfo * -interesting_major(int major) -{ - struct drvinfo *drp; - static int last_major = -1; - static struct drvinfo *last_result = NULL; - - if (major == last_major) - return (last_result); - last_major = major; - - for (drp = drvs; drp->name != NULL; drp++) { - if (major == drp->major) { - last_result = drp; - return (drp); - } - } - - last_result = NULL; - return (NULL); -} - -/* - * Find the minor component of the device name which is what - * comes between the ':' and ',' in the last component of - * the pathname; make a copy and return a pointer to it. - */ -static char * -find_min_comp(char *name) -{ - char *cp1, *cp2; - int len; - char *buf; - - cp1 = strrchr(name, '/'); - if (cp1 == NULL) - cp1 = name; - else - cp1++; /* skip '/' */ - cp1 = strchr(cp1, ':'); - if (cp1 == NULL) - return (""); - - cp1++; /* skip ':' */ - cp2 = cp1; - while (*cp2 != ',' && *cp2 != '\0') - cp2++; - len = cp2 - cp1; - if (len == 0) - return (""); - - buf = xmalloc(len + 1); - (void) strncpy(buf, cp1, len); - buf[len] = '\0'; - return (buf); -} - -/* - * To get an index into the hash table we compute a checksum - * of the string and mod HASHSIZE. The checksum came from - * awk, although we do a shift and subtract to implement - * multiplication by 31. We return the index as well as - * the whole checksum. The checksum is useful for efficient - * symbol lookup because the hash table will contain long strings - * that can be the same for the first 70 characters or more, so - * we compare checksums first before using strcmp(). - */ -static int -hash_sym(char *name, int *csp) -{ - char c; - unsigned int csum = 0; - - while ((c = *name++) != '\0') - csum = ((csum << 5) - csum) + c; - - *csp = csum; - return (csum % HASHSIZE); -} - -/* - * Insert a /devices entry symbol into the devices entry - * hash table. - */ -static void -insert_devices_sym(struct devices_ent *dep) -{ - int hash; - struct devices_ent **pp; - - hash = hash_sym(dep->devicename, &dep->csum); - pp = &de_hashtab[hash]; - dep->next = *pp; - *pp = dep; -} - -/* - * Lookup a symbol in the devices entry hash table. Use - * the checksum to reduce the number of strcmp() calls. - */ -static struct devices_ent * -lookup_devices_sym(char *devicename) -{ - int hash; - struct devices_ent *dep; - int csum; - - hash = hash_sym(devicename, &csum); - dep = de_hashtab[hash]; - while (dep != NULL) { - if (csum == dep->csum) { - if (strcmp(devicename, dep->devicename) == 0) - return (dep); - } - dep = dep->next; - } - - return (NULL); -} - -/* - * This routine is called from nftw() for each /devices entry. - * If it isn't a device special file or doesn't have the major - * number of something we care about, don't do anything. - * Otherwise, allocate a structure for it and put it in the - * hash table. - */ -/* ARGSUSED2 */ -static int -devices_entry(const char *name, const struct stat *sp, - int flags, struct FTW *ftwp) -{ - int type; - struct drvinfo *drp; - struct devices_ent *dep; - - if (flags == FTW_NS) { /* couldn't stat the file */ - (void) fprintf(stderr, gettext("%s: cannot stat %s\n"), - progname, name); - return (0); - } - if (flags == FTW_DNR) { /* couldn't read a directory */ - (void) fprintf(stderr, gettext("%s: cannot read " - "directory %s\n"), progname, name); - return (0); - } - - type = sp->st_mode & S_IFMT; - if (!(type == S_IFCHR || type == S_IFBLK)) - return (0); - - drp = interesting_major(major(sp->st_rdev)); - if (drp == NULL) - return (0); - - name += 2; /* skip "./" */ - dep = xmalloc(sizeof (struct devices_ent)); - dep->devicename = xstrdup(name); - dep->min_comp = find_min_comp(dep->devicename); - dep->minor = minor(sp->st_rdev); - dep->israw = (type == S_IFCHR); - dep->iscd = 0; - dep->issd = 0; - dep->linksto = NULL; - dep->drp = drp; - - insert_devices_sym(dep); - num_devices_ents++; - - return (0); -} - -/* - * dcomp is the sort function called from qsort(). When comparing - * two device entries we sort by alphabetical order of the device's - * driver name, then minor number, then block vs. character, then - * the name of the device entry itself. - */ -static int -dcomp(const void *p1, const void *p2) -{ - struct devices_ent *dep1 = *((struct devices_ent **)p1); - struct devices_ent *dep2 = *((struct devices_ent **)p2); - - if (dep1->drp->index == dep2->drp->index) { - if (dep1->minor == dep2->minor) { - if (dep1->israw == dep2->israw) { - return (strcoll(dep1->devicename, - dep2->devicename)); - } else { - return (dep1->israw - dep2->israw); - } - } else { - return (dep1->minor - dep2->minor); - } - } else { - return (dep1->drp->index - dep2->drp->index); - } -} - -/* - * Go to the /devices directory and recursively find all - * the device special files (with the handy library function - * nftw). nftw() will call devices_entry() which will put - * the entry in the hash table. After we find all the - * entries allocate a table and put pointers in it so - * we can sort the entries. - */ -static void -get_devices(void) -{ - char *dir; - int i; - struct devices_ent *dep, **pht, **pdep; - - dir = root_name("/devices"); - if (chdir(dir) == -1) { - xperror(dir); - exit(1); - } - - /* - * Errors related to access permissions are handled - * by devices_entry() and devices_entry doesn't return - * non-zero so the only thing left is some other type - * of error. - */ - if (nftw(".", devices_entry, depth, FTW_PHYS) == -1) - xperror("nftw()"); - - devices_list = xmalloc(sizeof (struct devices_ent *) * - num_devices_ents); - - pdep = devices_list; - pht = de_hashtab; - for (i = 0; i < HASHSIZE; i++) { - dep = *pht; - while (dep != NULL) { - *pdep++ = dep; - dep = dep->next; - } - pht++; - } - - /* - * After all the /devices entries are put in the hash - * table we sort the entries. We do this for two - * reasons: the rule functions may count on the order of - * devices it is called with (like the cdrom stuff in - * rule_sd) and if the rules create overlapping names the - * links will be made in an order based on sorted entries - * rather than be dependent on the order the entries - * happen to be in in a directory. - */ - qsort((void *) devices_list, num_devices_ents, - sizeof (struct devices_ent *), dcomp); -} - -/* - * Like insert_devices_sym, but for link names and symlink - * structures. - */ -static void -insert_link_sym(struct symlink *slp) -{ - int hash; - struct symlink **pp; - - hash = hash_sym(slp->linkname, &slp->csum); - pp = &link_hashtab[hash]; - slp->hashnext = *pp; - *pp = slp; -} - -/* - * Like lookup_devices_sym, but for link names and symlink - * structures. - */ -static struct symlink * -lookup_link_sym(char *linkname) -{ - int hash; - struct symlink *slp; - int csum; - - hash = hash_sym(linkname, &csum); - slp = link_hashtab[hash]; - while (slp != NULL) { - if (csum == slp->csum) { - if (strcmp(linkname, slp->linkname) == 0) - return (slp); - } - slp = slp->hashnext; - } - - return (NULL); -} - -/* - * Check this symlink to see if it points to an interesting - * /devices entry and hang it off the entry if it does. - */ -static void -check_link(struct symlink *slp) -{ - int dirs; - char *cp; - int len; - char *devices = "../devices/"; - char *buf; - int i, off; - struct devices_ent *dep; - - if (*slp->target != '.') - return; - - /* - * Figure out how many directories deep the entry is - * so we can see if its link has the right number of - * ".."s to point to the /devices directory. - */ - dirs = 0; - cp = strchr(slp->linkname, '/'); - while (cp != NULL) { - dirs++; - cp = strchr(cp + 1, '/'); - } - len = strlen(devices); - buf = xmalloc(dirs * 3 + len + 1); - for (i = 0, off = 0; i < dirs; i++, off += 3) - (void) strcpy(buf + off, "../"); - (void) strcpy(buf + off, devices); - off += len; - - /* - * The correct prefix of the path has been built up - * in "buf", compare it to the link and return - * if it doesn't match. - */ - if (strncmp(slp->target, buf, strlen(buf)) != 0) { - free(buf); - return; - } - free(buf); - - /* - * Look up the /devices path (minus the prefix) and - * return if not found. - */ - dep = lookup_devices_sym(slp->target + off); - if (dep == NULL) - return; - - /* hang it off the /devices entry */ - slp->deventnext = dep->linksto; - dep->linksto = slp; - -} - -/* - * This routine is called from nftw() for each /dev entry. - * We record all of the symlinks, not just those that point to - * interesting /devices entries, because when we have determined - * what a compatibility link should point to we want to know - * if it already points to the correct target and it is much - * cheaper to look it up in out list than to make a system call. - */ -/* ARGSUSED2 */ -static int -dev_entry(const char *name, const struct stat *sp, - int flags, struct FTW *ftwp) -{ - int type; - char target[MAXPATHLEN + 1]; - int targetlen; - struct symlink *slp; - - if (flags == FTW_NS) { /* couldn't stat the file */ - (void) fprintf(stderr, gettext("%s: cannot stat %s\n"), - progname, name); - return (0); - } - if (flags == FTW_DNR) { /* couldn't read a directory */ - (void) fprintf(stderr, gettext("%s: cannot read " - "directory %s\n"), progname, name); - return (0); - } - - type = sp->st_mode & S_IFMT; - if (type != S_IFLNK) - return (0); - - name += 2; /* skip "./" */ - targetlen = readlink(name, target, sizeof (target)); - if (targetlen == -1) - xperror(name); - - target[targetlen] = '\0'; - - slp = xmalloc(sizeof (struct symlink)); - slp->linkname = xstrdup(name); - slp->target = xstrdup(target); - slp->already = 0; - insert_link_sym(slp); - check_link(slp); - - return (0); -} - -/* - * Go to the /dev directory and recursively find all the - * symlinks. nftw() will call dev_entry() which will put - * the entry in the hash table. - */ -static void -get_dev_links(void) -{ - char *devdir; - - devdir = root_name("/dev"); - if (chdir(devdir) == -1) { - xperror(devdir); - exit(1); - } - - /* - * Errors related to access permissions are handled - * by dev_entry() and dev_entry doesn't return non-zero - * so the only thing left is some other type of error. - */ - if (nftw(".", dev_entry, depth, FTW_PHYS) == -1) - xperror("nftw()"); -} - -/* - * Spin through our sorted list of /devices entries and call - * the rule function for each. - */ -static void -call_device_rules(void) -{ - struct devices_ent **pdep; - struct devices_ent *dep; - int i; - char *root_etc; - - root_etc = root_name("/etc"); - link_handle = di_devlink_open(root_etc, 0); - - pdep = devices_list; - for (i = 0; i < num_devices_ents; i++) { - dep = *pdep++; - dep->drp->rule_func(dep); - } - - di_devlink_close(&link_handle, 0); -} - -static void -update_db(char *compat_link, char *target, int link_type) -{ - if (debug) { - (void) printf("adding %s link to database: %s -> %s\n", - link_type == DI_PRIMARY_LINK ? "primary" : "secondary", - compat_link, target); - } else { - (void) di_devlink_add_link(link_handle, compat_link, target, - link_type); - } -} - -/* - * Create a symlink called compat_link that points to target. - * If it already exists correctly don't do anything. If it - * exists but is incorrect, delete the link and make it. If - * it doesn't exist just make it. - */ -static void -make_link( - char *compat_link, - char *target, - struct symlink *compat_slp, - int link_type) -{ - if (compat_slp->target != NULL) { - if (strcmp(target, compat_slp->target) == 0) { - if (debug) - (void) printf("already %s -> %s\n", - compat_link, compat_slp->target); - update_db(compat_link, target, link_type); - return; - } else { - if (debug) - (void) printf("remove %s, link wrong (%s)\n", - compat_link, compat_slp->target); - else { - if (unlink(compat_link) == -1) - xperror(compat_link); - else - (void) di_devlink_rm_link(link_handle, - compat_link); - } - compat_slp->target = target; - } - } else - compat_slp->target = target; - - if (debug) - (void) printf("link %s -> %s\n", compat_link, target); - else { - if (symlink(target, compat_link) == -1) - xperror(compat_link); - else - update_db(compat_link, target, link_type); - } -} - -/* - * addlink is called from the rule functions when they want a - * compatibility link made. At this point we only know the - * link name, the /devices entry, and the prefix of a 5.x /dev - * name (that points to the /devices entry) that the rule would - * prefer the compatibility link point to. If a symlink already - * exists with the required prefix that points to the /devices - * entry, make the compatibility link point to that link. - * If a link with the required prefix doesn't exist, make the - * link point directly to the /devices entry. The idea is that - * someone looking at a compatibility link will be reminded of - * the "real" 5.x /dev name. For example, ls -l will show sd0a -> - * dsk/c0t3d0s0. - * - * If the symlink we're creating isn't already in the hash - * table we add it for possible future use by make_link. - * If multiple /devices entries exist with the same major - * and minor numbers this prevents problems with trying to - * make the link twice. Generally, though, there shouldn't - * be multiple /devices entries of the same type, major, and - * minor, except for tape devices. The tape rules pass 1 for - * the unique argument (all others pass 0) so we keep track - * and only create the first link for a particular compatibility - * name. - */ -static void -addlink(char *compat_link, char *prefix, struct devices_ent *dep, int unique) -{ - int len, link_type = 0; - struct symlink *devent_slp; - struct symlink *compat_slp; - char *target = NULL; - char linkbuf[MAXPATHLEN + 1]; - - compat_slp = lookup_link_sym(compat_link); - if (compat_slp == NULL) { - compat_slp = xmalloc(sizeof (struct symlink)); - compat_slp->linkname = xstrdup(compat_link); - compat_slp->target = NULL; - compat_slp->already = 0; - insert_link_sym(compat_slp); - } - - if (unique) { - if (compat_slp->already) - return; - else - compat_slp->already = 1; - } - - /* - * Look for a name with the correct prefix. - */ - len = strlen(prefix); - devent_slp = dep->linksto; - while (devent_slp != NULL) { - if (strncmp(prefix, devent_slp->linkname, len) == 0) { - target = devent_slp->linkname; - link_type = DI_SECONDARY_LINK; - break; - } - devent_slp = devent_slp->deventnext; - } - - /* - * If we didn't find one with the prefix, point directly - * to the /devices entry. - */ - if (target == NULL) { - link_type = DI_PRIMARY_LINK; - (void) sprintf(linkbuf, "../devices/%s", dep->devicename); - target = xstrdup(linkbuf); - } - make_link(compat_link, target, compat_slp, link_type); -} - -/* - * This is like addlink(), but it doesn't try to find a 5.x - * link to point to. It is used by the rule functions to add - * additional links to links already created with addlink(). - */ -static void -addlink_nolookup(char *compat_link, char *target, int unique) -{ - struct symlink *slp; - char *oldtarg; - - slp = lookup_link_sym(compat_link); - if (slp == NULL) { - slp = xmalloc(sizeof (struct symlink)); - slp->linkname = xstrdup(compat_link); - slp->target = NULL; - slp->already = 0; - insert_link_sym(slp); - } - oldtarg = slp->target; - - if (unique) { - if (slp->already) - return; - else - slp->already = 1; - } - - make_link(compat_link, target, slp, DI_SECONDARY_LINK); - - /* - * If it didn't exist or pointed to the wrong - * thing we need to duplicate the target and - * note that the symlink now points to it. - */ - if (slp->target != oldtarg) - slp->target = xstrdup(target); -} - -/* - * The rest of this file is rule functions and support routines - * for the rules. Each rule is passed a pointer to a devices_ent - * struct which should be all it needs to determine what - * compatibility link is needed. The rule functions use - * addlink() and addlink_nolookup() to have the links - * made. - */ - -/* - * Rule for Archive tapes. "ar" isn't in name_to_major but - * the awk-based version had a rule so it is here too. The - * rule works the same as the awk rule, but who knows if it - * is correct. - */ -static void -rule_ar(struct devices_ent *dep) -{ - char *min_comp = dep->min_comp; - - if (*min_comp != '\0') { - if (min_comp[strlen(min_comp) - 1] == 'n') - (void) sprintf(namebuf, "%s%d", "nrar", - (dep->minor - 16) / 4); - else - (void) sprintf(namebuf, "%s%d", "rar", dep->minor / 4); - - addlink(namebuf, "rmt/", dep, 1); - } -} - -/* - * Rule for frame buffers. - */ -static void -rule_fbs(struct devices_ent *dep) -{ - addlink(dep->min_comp, "fbs/", dep, 0); -} - -/* - * Rule for floppy drivers. - */ -static void -rule_fd(struct devices_ent *dep) -{ - int c_slice; - int minor = dep->minor; - char *link_pfx; - char *targ_pfx; - - c_slice = (strcmp(dep->min_comp, "c") == 0); - - if (dep->israw) { - link_pfx = "r"; - targ_pfx = "rdiskette"; - } else { - link_pfx = ""; - targ_pfx = "diskette"; - } - - (void) sprintf(namebuf, "%sfd%d%s", link_pfx, minor / 8, - dep->min_comp); - addlink(namebuf, targ_pfx, dep, 0); - if (c_slice) { - (void) sprintf(namebuf2, "%sfd%d", link_pfx, minor / 8); - addlink_nolookup(namebuf2, namebuf, 0); - } -} - -/* - * Rule for IPI disks. This is hopelessly broken (see bug 1157501) - * but someone may have come to depend on the broken names. - */ -static void -rule_id(struct devices_ent *dep) -{ - char *targ_pfx; - char *link_pfx; - - if (dep->israw) { - link_pfx = "r"; - targ_pfx = "rdsk/"; - } else { - link_pfx = ""; - targ_pfx = "dsk/"; - } - - (void) sprintf(namebuf, "%sid%x%s", link_pfx, dep->minor, - dep->min_comp); - addlink(namebuf, targ_pfx, dep, 0); -} - -/* - * Rule for obsolete mt devices. It works like the awk rule, - * but unknown if correct. - */ -static void -rule_mt(struct devices_ent *dep) -{ - int minor = dep->minor; - - if ((minor % 8) >= 4) { - (void) sprintf(namebuf, "rmt%d", minor); - addlink(namebuf, "rmt/", dep, 1); - (void) sprintf(namebuf2, "nrmt%d", minor - 4); - addlink_nolookup(namebuf2, namebuf, 1); - } else { - (void) sprintf(namebuf, "rmt%d", minor); - addlink(namebuf, "rmt/", dep, 1); - } -} - -static int -find_cd_nodes(di_node_t node, di_minor_t minor, void *arg) -{ - char *path; - char devpath[MAXPATHLEN]; - struct devices_ent *dep; - - path = di_devfs_path(node); - - if (*path == '/') { - (void) strcpy(devpath, path+1); - (void) strcat(devpath, ":"); - (void) strcat(devpath, di_minor_name(minor)); - - dep = lookup_devices_sym(devpath); - if (dep != NULL) { - dep->iscd = 1; - } - } - - di_devfs_path_free(path); - - return (DI_WALK_CONTINUE); -} - -static int -find_sd_nodes(di_node_t node, di_minor_t minor, void *arg) -{ - char *path; - char devpath[MAXPATHLEN]; - struct devices_ent *dep; - - path = di_devfs_path(node); - - if (*path == '/') { - (void) strcpy(devpath, path+1); - (void) strcat(devpath, ":"); - (void) strcat(devpath, di_minor_name(minor)); - - dep = lookup_devices_sym(devpath); - if (dep != NULL) { - dep->issd = 1; - } - } - - di_devfs_path_free(path); - - return (DI_WALK_CONTINUE); -} - -/* - * The rule for scsi disks uses this to determine if the /devices - * entry corresponds to a cdrom drive. Use libdevinfo to walk - * the device tree: - * calling find_cd_nodes() for each minor node of type DDI_NT_CD. - * calling find_sd_nodes() for each minor node of type DDI_NT_BLOCK_CHAN. - */ -static void -find_cdsd(void) -{ - di_node_t root_node; - - root_node = di_init("/", DINFOSUBTREE|DINFOMINOR); - if (root_node == DI_NODE_NIL) { - return; - } - di_walk_minor(root_node, DDI_NT_CD, 0, NULL, find_cd_nodes); - di_walk_minor(root_node, DDI_NT_BLOCK_CHAN, 0, NULL, find_sd_nodes); - di_fini(root_node); -} - - -/* - * Rule for scsi disks. If the entry is for a cdrom drive - * we create srN and rsrN where N is logically numbered - * starting at 0 in order of minor number. For regular - * disks we do the 0 <-> 3 swap, i.e., sd0a will point - * to c0t3d0s0 and sd3a will point to c0t0d0s0. This should - * only be done on sun4m machines to be compatible - * with 4.x (see bug 1157616) but we're probably stuck with it - * being done on all machines because people may be used - * to using the swapped names on other machines. - */ -static void -rule_sd(struct devices_ent *dep) -{ - static int first = 1; - static int cdnum = -1; - static int last_minor = -1; - char *min_comp = dep->min_comp; - int minor = dep->minor; - char *targ_pfx; - char *link_pfx; - - if (first) { - find_cdsd(); - first = 0; - } - - if (dep->iscd) { - if (strcmp(min_comp, "c") == 0) { - if (minor != last_minor) { - cdnum++; - last_minor = minor; - } - if (dep->israw) { - (void) sprintf(namebuf, "rsr%d", cdnum); - addlink(namebuf, "rdsk/", dep, 0); - } else { - (void) sprintf(namebuf, "sr%d", cdnum); - addlink(namebuf, "dsk/", dep, 0); - } - } - return; - } - - if (!dep->issd) - return; - - if (dep->israw) { - link_pfx = "r"; - targ_pfx = "rdsk/"; - } else { - link_pfx = ""; - targ_pfx = "dsk/"; - } - - if (minor < 8) - (void) sprintf(namebuf, "%ssd%d%s", link_pfx, 3, min_comp); - else if (minor >= 24 && minor < 32) - (void) sprintf(namebuf, "%ssd%d%s", link_pfx, 0, min_comp); - else - (void) sprintf(namebuf, "%ssd%d%s", link_pfx, minor / 8, - min_comp); - - addlink(namebuf, targ_pfx, dep, 0); -} - -/* - * Rule for PCI cdrom drives. - */ -static void -rule_atapicd(struct devices_ent *dep) -{ - static int last_minor = -1; - static int cdnum = -1; - char *min_comp = dep->min_comp; - int minor = dep->minor; - - if (strcmp(min_comp, "c") == 0) { - if (minor != last_minor) { - cdnum++; - last_minor = minor; - } - if (dep->israw) { - (void) sprintf(namebuf, "rsr%d", cdnum); - addlink(namebuf, "rdsk/", dep, 0); - } else { - (void) sprintf(namebuf, "sr%d", cdnum); - addlink(namebuf, "dsk/", dep, 0); - } - } -} - -/* - * Rule for scsi and xt tapes. The tape name space has several - * problems (see bug 1157970) and the xt names should really appear - * as an "mt" name (see bug 1157617) but, again, we probably shouldn't - * change this now as it will break compatibility with earlier - * 5.x releases. - */ - -#include <sys/mtio.h> -/* - * MTUNIT() and MT_DENSITY() use getminor(), but we already have - * the minor number and including sysmacros.h to get getminor() - * conflicts with mkdev.h. Barf. - */ -#define getminor(d) (d) - -static void -rule_stxt(struct devices_ent *dep) -{ - char *min_comp = dep->min_comp; - int minor = dep->minor; - int drive, den; - char *link_pfx; - - if (*min_comp != 'b' && *min_comp != 'n') { - if ((minor & MT_BSD) == 0) - return; /* not BSD-style */ - - drive = MTUNIT(minor); - den = MT_DENSITY(minor); - - if (min_comp[strlen(min_comp) - 1] == 'n') - link_pfx = "nr"; - else - link_pfx = "r"; - (void) sprintf(namebuf, "%s%s%d", link_pfx, dep->drp->name, - (den * 8) + drive); - addlink(namebuf, "rmt/", dep, 1); - } -} - -/* - * Rule for xd and xy disks. This is broken because it does - * the 0 <-> 3 swap that should only be done for scsi disks - * on sun4m (see bug 1157616). Again, we probably - * can't change this now. - */ -static void -rule_xdxy(struct devices_ent *dep) -{ - char *min_comp = dep->min_comp; - char *majname = dep->drp->name; - int minor = dep->minor; - char *targ_pfx; - char *link_pfx; - - if (dep->israw) { - link_pfx = "r"; - targ_pfx = "rdsk/"; - } else { - link_pfx = ""; - targ_pfx = "dsk/"; - } - - if (minor < 8) - (void) sprintf(namebuf, "%s%s%d%s", link_pfx, majname, 3, - min_comp); - else if (minor >= 24 && minor < 32) - (void) sprintf(namebuf, "%s%s%d%s", link_pfx, majname, 0, - min_comp); - else - (void) sprintf(namebuf, "%s%s%d%s", link_pfx, majname, - minor / 8, min_comp); - - addlink(namebuf, targ_pfx, dep, 0); -} - -/* - * Rule for zs (serial) devices. This rule is different from - * the rest because it doesn't create a link based on the - * /devices entry. It just uses the /devices entry to trigger - * the rule to create ttyN -> dev/term/N for all dev/term - * entries. - */ -#include <dirent.h> - -static void -rule_zs(struct devices_ent *dep) -{ - static int beenhere = 0; - int len; - DIR *dirp; - struct dirent *direntp; - char *termdir; - char *entry; - char *devicename = dep->devicename; - - len = strlen(devicename); - if (strncmp(&devicename[len - 3], ",cu", 3) == 0) - return; - - if (beenhere) - return; - else - beenhere = 1; - - termdir = root_name("/dev/term"); - - dirp = opendir(termdir); - if (dirp == NULL) { - xperror(termdir); - return; - } - while ((direntp = readdir(dirp)) != NULL) { - entry = direntp->d_name; - if (entry[0] == '.') - continue; - (void) sprintf(namebuf, "tty%s", direntp->d_name); - (void) sprintf(namebuf2, "term/%s", direntp->d_name); - addlink_nolookup(namebuf, namebuf2, 0); - } - - (void) closedir(dirp); -} - -/* - * is_blank() returns 1 (true) if a line specified is composed of - * whitespace characters only. otherwise, it returns 0 (false). - * - * Note. the argument (line) must be null-terminated. - */ -static int -is_blank(char *line) -{ - for (/* nothing */; *line != '\0'; line++) - if (!isspace(*line)) - return (0); - return (1); -} diff --git a/usr/src/ucbcmd/ucblinks/ucblinks.sh b/usr/src/ucbcmd/ucblinks/ucblinks.sh deleted file mode 100644 index ce5f5a88f7..0000000000 --- a/usr/src/ucbcmd/ucblinks/ucblinks.sh +++ /dev/null @@ -1,237 +0,0 @@ -#!/bin/sh -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" - -PATH=/sbin:/usr/sbin:/usr/bin:/etc -export PATH - -RULEBASE=/usr/ucblib/ucblinks.awk - -# Name of device-type list produced by "devlinks" -DEVTYPES=/etc/.obp_devices - -USAGE="Usage: `basename $0` [-r rootdir] [-e rulebase] [-d]" -DOIT_CMD="sh -s" - -while getopts 'de:r:' flag -do - case $flag in - d) DOIT_CMD="cat -" - ;; - e) - RULEBASE=$OPTARG; - case "$RULEBASE" in - /*) ;; - *) RULEBASE="`pwd`/$RULEBASE";; - esac - ;; - r) ROOTDIR=$OPTARG; - ;; - \?) echo "$USAGE" >&2 - exit 2; - ;; - esac -done - -shift `expr $OPTIND - 1` - -# -# The rest of this script looks a mess. But in fact underneath all the -# 'sed's and 'awk's it is quite simple. -# -# First it creates a list of all the device nodes in the /devices directory -# (by cd'ing to /dev, then doing a 'find' of all special files in ../devices -# doing an 'ls -l' of these files, and sedding the output to produce a list -# of the form 'major minor type name'). -# -# As an added wrinkle it changes 'major' from a number to a driver-name using -# sed rules produced from the "/etc/name_to_major file. -# -# Then it runs the awk rules in the rule-base on this list to produce a list -# of compatability-links that must be created. However, this does not produce -# the links themselves because of the next stage: -# -# Finally this list of compatability-links is inspected and where possible links -# to the SunOS5 names are created instead of links directly to the /devices -# directory -# (by 'find'ing all the symbolic links under /dev, ancomparing the -# subdirectory they occur in, and the file to which they point, to -# the comaptability-link information built above. If a match is found -# a command to make a link to the 5.0 link, rather than to the /devices -# entry, is created. If not, a direct link is created) -# And then the list of link command is executed by a shell, or printed on stdout -# (in debugging mode) -# -# See -- not so complicated! However the syntax of all these rules makes -# the code below nearly incomprehensible. Fear not; the only part you need -# to change for extra devices is located in the 'RULEBASE' file. - -cd $ROOTDIR/dev - -GENSED=/tmp/mkcompat.sed$$ -GENAWK=/tmp/mkcompat.awk$$ -GENRULE=/tmp/mkcompat.rule$$ - -rm -f $GENSED $GENAWK $GENRULE - -trap "rm -f $GENSED $GENAWK $GENRULE" 0 - -# -# First generate full rulebase. This is done to keep common functions -# out of the rulebase - - -cat - >$GENRULE <<\!EOD -function out(dev, dir, extraname) { - c = split(dir, junk, "/") - 1; - - if (junk[1] == ".") - c--; - - fulldevfs = ""; - - while ( c > 0) { - fulldevfs = "../" fulldevfs; - c--; - } - fulldevfs = fulldevfs $4; - - printf "devname[\"" fulldevfs "\"] = \"" dev "\";"; - - if (length(dir) > 0) - printf " devdir[\"" fulldevfs "\"] = \"" dir "\";"; - - if (length(extraname) > 0) - printf " devextra[\"" fulldevfs "\"] = \"" extraname "\";"; - printf "\n"; - } - -!EOD - -# -# Now see if we need to do CD drive special handling. The SCSI CD and disk -# drivers have been merged in SunOS5, so we cannot do the normal differentiation -# on major number with these devices. However the "disks" program does write -# a list of all OBP cd device names in a pecial file; by massaging this file -# we are able to construct rules which correctly differentiate between sd and sr -# devices. - -if [ -s $DEVTYPES ] -then - echo "BEGIN {" >>$GENRULE - sed -ne '/^ddi_block:cdrom[: ]/s-^[^ ]*[ ]\{1,\}\(.*\)$- cddev["../devices/\1"] = 1;-p' <$DEVTYPES >>$GENRULE - echo " }" >>$GENRULE -fi - -cat $RULEBASE >>$GENRULE - - -# -#---------------------------------------------------------------------- -# -# Construct sedscr ... a script to massage the output of an 'ls -l' -# of all the special files in the '../devices' directory. -# -# First 3 lines of scr change line to format "maj min [b|c] name -# -cat <<\!EOD >$GENSED -1,$s/^\(.\).*[ ]\([0-9][0-9]*\), *\([0-9][0-9]*\)[ ].*[ ]\([^ ][^ ]*\)$/\2 \3 \1 \4/ -/:[^ ,][^ ,]*$/s/^\(.*\):\([^ ,]*\)$/\1:\2 \2/ -/:[^ ,][^ ,]*,[^ ]*$/s/^\(.*\):\([^ ,]*\),\([^ ]*\)$/\1:\2,\3 \2/ -!EOD - -# Next lines are generated from the "/etc/name_to_major file; they change the -# "major number" field into its corresponding 'name'. This is so that -# the difference in major-numbers among different machines can be hidden. -# -nawk -v del='#' '$1 !~ /^#|^$/ { \ - num = split($2, maj, del); \ - if (num > 1) { printf("/^%s\t/ s/^%s\t/%s\t/\n", maj[1], maj[1], $1) } \ - else { printf("/^%s\t/ s/^%s\t/%s\t/\n", $2, $2, $1) } \ -} ' /etc/name_to_major >> $GENSED - -# -#---------------------------------------------------------------------- -# -# Have finished generating sedscr. Now we generate 'nawkscr'; first we insert -# the header ... - -cat >$GENAWK <<\!EOD -BEGIN { -!EOD - -# and then we find all the symbolic-links under /dev, massage the output of -# an 'ls -l' with the sed script we generated above, and then 'nawk' the output -# using the actual link data table script. This generates the heart of our -# link-creating 'nawk' script. - -echo "Scanning /devices/ directory tree..." >&2 - -ls -l `find ../devices \( -type b -o -type c \) -print` | sed -f $GENSED |\ -sort -b +0 -1 +1n -2 +4 -5 | nawk -f $GENRULE >>$GENAWK - -cat >>$GENAWK <<\!EOD - } -$2 in devname { - if (length(devdir[$2]) <= 0) - next; - if (devdir[$2] == "./") { - if ($1 == devname[$2]) - next; - } - else if (match($1, "^" devdir[$2] "[^/]*$") == 0) - next; - - printf "rm -f %s; ln -s %s %s\n", devname[$2], $1, devname[$2]; - if (length(devextra[$2]) > 0) { - printf "rm -f %s; ln -s %s %s\n", devextra[$2], - devname[$2], devextra[$2]; - delete devextra[$2]; - } - delete devname[$2]; - delete devdir[$2]; - } -END { - for (dev in devname) { - printf "rm -f %s; ln -s %s %s\n", devname[dev], - substr(dev, match(dev, "\.\./devices/"), 999), - devname[dev]; - if (length(devextra[dev]) > 0) - printf "rm -f %s; ln -s %s %s\n", devextra[dev], - devname[dev], devextra[dev]; - } - } -!EOD - -# -#---------------------------------------------------------------------- -# -echo "Scanning /dev/ directory tree..." >&2 - -ls -l `find . -type l -print` |\ - sed -e '1,$s/^.* \.\/\([^ ][^ ]*\) -> \([^ ][^ ]*\)$/\1 \2/' |\ - nawk -f $GENAWK |\ - $DOIT_CMD |