252N/A/*
252N/A* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
252N/A*
252N/A* U.S. Government Rights - Commercial software. Government users are subject
252N/A* to the Sun Microsystems, Inc. standard license agreement and applicable
252N/A* provisions of the FAR and its supplements.
252N/A*
252N/A*
252N/A* This distribution may include materials developed by third parties. Sun,
252N/A* Sun Microsystems, the Sun logo and Solaris are trademarks or registered
252N/A* trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
252N/A*
252N/A*/
252N/A
252N/A
252N/A#include <stdio.h>
252N/A#include <stdlib.h>
252N/A#include <unistd.h>
252N/A#include <dirent.h>
252N/A#include <sys/types.h>
252N/A#include <sys/stat.h>
252N/A#include <limits.h>
252N/A#include <string.h>
252N/A#include <ctype.h>
252N/A#include <fcntl.h>
252N/A#include <sys/mnttab.h>
252N/A#include <sys/systeminfo.h>
252N/A#include <sys/dklabel.h>
252N/A#include <sys/dkio.h>
252N/A
252N/Atypedef struct nms {
252N/A char *dsk;
252N/A int dnum;
252N/A char *dty;
252N/A char *real;
252N/A int devtype;
252N/A struct nms *next;
252N/A} nms_t;
252N/A
252N/Atypedef struct list_of_disks {
252N/A char *dtype;
252N/A int dnum;
252N/A char *dsk;
252N/A char *dpart[NDKMAP];
252N/A struct list_of_disks *next;
252N/A} disk_list_t;
252N/A
252N/Astatic nms_t *rummage_dev_dsk(void);
252N/Astatic void do_snm(char *, char *);
252N/Astatic int look_up_name(const char *, nms_t *);
252N/Astatic void make_an_entry(char *, const char *, nms_t **, int);
252N/Astatic char *trim(char *);
252N/Astatic void rummage_path_to_inst(nms_t *);
252N/Astatic nms_t *find_str(const char *, nms_t *);
252N/Astatic int pline(char *, nms_t *);
252N/Astatic void insert_dlist_ent(const char *, const int, const char *,
252N/A int, disk_list_t **);
252N/Astatic void mk_list_of_disks(nms_t *, disk_list_t **);
252N/Astatic int str_is_digit(char *);
252N/A
252N/Aextern void *build_disk_list(void *);
252N/Aextern char *lookup_ks_name(char *, void *);
252N/A
252N/A#define DISK 0
252N/A#define TAPE 1
252N/A
252N/A#define MAX_TYPES 2
252N/A
252N/A
252N/A/*
252N/A * Build a list of disks attached to the system. if a previous list is passed
252N/A * in, delete that list before building the new list.
252N/A */
252N/A
252N/Avoid *
252N/Abuild_disk_list(void *v)
252N/A{
252N/A nms_t *list;
252N/A nms_t *t;
252N/A disk_list_t *rv=NULL;
252N/A disk_list_t *p;
252N/A int i;
252N/A
252N/A p = (disk_list_t *)v;
252N/A if (p != (disk_list_t *)NULL) {
252N/A disk_list_t *t;
252N/A while (p) {
252N/A (void) free(p->dtype);
252N/A (void) free(p->dsk);
252N/A for (i = 0; i < NDKMAP; i++)
252N/A (void) free(p->dpart[i]);
252N/A t = p;
252N/A p = p->next;
252N/A (void) free(t);
252N/A }
252N/A }
252N/A /*
252N/A * Build the list of devices connected to the system.
252N/A */
252N/A list = rummage_dev_dsk();
252N/A rummage_path_to_inst(list);
252N/A mk_list_of_disks(list, &rv);
252N/A t = list;
252N/A while (t) {
252N/A nms_t *f;
252N/A (void) free(t->real);
252N/A f = t;
252N/A t = t->next;
252N/A if (t != list) {
252N/A (void) free(f);
252N/A }
252N/A }
252N/A return (rv);
252N/A}
252N/A
252N/A
252N/A/*
252N/A * Currently it isn't necessary to look below the cntndn level....
252N/A */
252N/A
252N/Astatic nms_t *
252N/Arummage_dev_dsk(void)
252N/A{
252N/A nms_t *list = (nms_t *)0;
252N/A DIR *dskp;
252N/A int i;
252N/A
252N/A for (i = 0; i < MAX_TYPES; i++) {
252N/A switch (i) {
252N/A
252N/A case DISK:
252N/A dskp = opendir("/dev/dsk");
252N/A break;
252N/A case TAPE:
252N/A dskp = opendir("/dev/rmt");
252N/A break;
252N/A default:
252N/A dskp = NULL;
252N/A break;
252N/A }
252N/A
252N/A if (dskp != NULL) {
252N/A struct dirent *bpt;
252N/A while ((bpt = readdir(dskp)) != NULL) {
252N/A struct stat sbuf;
252N/A char dnmbuf[1025];
252N/A char snm[256];
252N/A char lnm[256];
252N/A char *npt;
252N/A char nmbuf[1025];
252N/A
252N/A if (bpt->d_name[0] == '.')
252N/A continue;
252N/A
252N/A if (i == DISK) {
252N/A (void) strcpy(lnm, bpt->d_name);
252N/A do_snm(bpt->d_name, snm);
252N/A } else {
252N/A /*
252N/A * don't want all rewind/etc
252N/A * devices for a tape
252N/A */
252N/A if (!str_is_digit(bpt->d_name))
252N/A continue;
252N/A (void) sprintf(snm, "rmt/%s",
252N/A bpt->d_name);
252N/A (void) sprintf(lnm, "rmt/%s",
252N/A bpt->d_name);
252N/A }
252N/A if (look_up_name(snm, list) != 0)
252N/A continue;
252N/A
252N/A if (i == DISK) {
252N/A (void) sprintf(dnmbuf,
252N/A "/dev/dsk/%s", bpt->d_name);
252N/A } else {
252N/A (void) sprintf(dnmbuf,
252N/A "/dev/rmt/%s", bpt->d_name);
252N/A }
252N/A if (lstat(dnmbuf, &sbuf) != -1) {
252N/A int cnt;
252N/A if ((sbuf.st_mode & S_IFMT)
252N/A == S_IFLNK) {
252N/A
252N/A nmbuf[0] = '\0';
252N/A if ((cnt = readlink(dnmbuf, nmbuf, sizeof (nmbuf))) != 1) {
252N/A nmbuf[cnt] = '\0';
252N/A npt = nmbuf;
252N/A } else
252N/A npt = (char *)0;
252N/A } else
252N/A npt = lnm;
252N/A if (npt)
252N/A make_an_entry(npt, snm,
252N/A &list, i);
252N/A }
252N/A }
252N/A (void) closedir(dskp);
252N/A }
252N/A }
252N/A return (list);
252N/A}
252N/A
252N/A
252N/Astatic int
252N/Alook_up_name(const char *nm, nms_t *list)
252N/A{
252N/A int rv = 0;
252N/A
252N/A while (list != (nms_t *)NULL) {
252N/A if (strcmp(list->dsk, nm) != 0)
252N/A list = list->next;
252N/A else {
252N/A rv++;
252N/A break;
252N/A }
252N/A }
252N/A return (rv);
252N/A}
252N/A
252N/A
252N/Astatic void
252N/Ado_snm(char *orig, char *shortnm)
252N/A{
252N/A while (*orig != 's' && *orig != 'p')
252N/A *shortnm++ = *orig++;
252N/A *shortnm = '\0';
252N/A}
252N/A
252N/A
252N/Astatic void
252N/Amake_an_entry(char *lname, const char *shortnm, nms_t **list, int devtype)
252N/A{
252N/A nms_t *entry;
252N/A
252N/A entry = (nms_t *)malloc(sizeof (nms_t));
252N/A if (entry != (nms_t *)NULL) {
252N/A int len;
252N/A char *nlnm;
252N/A
252N/A nlnm = trim(lname);
252N/A len = strlen(nlnm);
252N/A len++;
252N/A entry->real = (char *)malloc(len);
252N/A if (entry->real) {
252N/A (void) strcpy(entry->real, nlnm);
252N/A len = strlen(shortnm);
252N/A len++;
252N/A entry->dsk = (char *)malloc(len);
252N/A if (entry->dsk) {
252N/A (void) strcpy(entry->dsk, shortnm);
252N/A entry->dnum = -1;
252N/A entry->dty = (char *)NULL;
252N/A entry->next = (nms_t *)NULL;
252N/A entry->devtype = devtype;
252N/A if (*list != (nms_t *)NULL) {
252N/A entry->next = *list;
252N/A *list = entry;
252N/A } else
252N/A *list = entry;
252N/A } else {
252N/A (void) free(entry->real);
252N/A (void) free(entry);
252N/A }
252N/A } else
252N/A (void) free(entry);
252N/A }
252N/A}
252N/A
252N/A
252N/Astatic char *
252N/Atrim(char *fnm)
252N/A{
252N/A char *ptr;
252N/A char *lname = "../../devices";
252N/A
252N/A while (*lname == *fnm) {
252N/A lname++;
252N/A fnm++;
252N/A }
252N/A if ((ptr = strrchr(fnm, (int)':')) != (char *)NULL)
252N/A *ptr = '\0';
252N/A return (fnm);
252N/A}
252N/A
252N/A
252N/Astatic void
252N/Arummage_path_to_inst(nms_t *list)
252N/A{
252N/A FILE *inpt;
252N/A
252N/A inpt = fopen("/etc/path_to_inst", "r");
252N/A if (inpt) {
252N/A char ibuf[1024];
252N/A
252N/A while (fgets(ibuf, sizeof (ibuf), inpt) != (char *)NULL) {
252N/A if (ibuf[0] != '#') {
252N/A (void) pline(ibuf, list);
252N/A }
252N/A }
252N/A (void) fclose(inpt);
252N/A }
252N/A}
252N/A
252N/A
252N/A/*
252N/A * Process an /etc/path_to_inst line. The line is of the format:
252N/A * "/pathname/device@unit,instance" devicenumber We want to extract the
252N/A * devicenumber and the device from this string if it is one of the ones in
252N/A * /dev/dsk.
252N/A */
252N/A
252N/A
252N/Astatic int
252N/Apline(char *ib, nms_t *list)
252N/A{
252N/A char *rpt;
252N/A char *bpt;
252N/A nms_t *entry;
252N/A int rv = 0;
252N/A int done;
252N/A int len;
252N/A char *v;
252N/A /*
252N/A * Skip over any stuff at the beginning of the line before a leading
252N/A * '/' If we don't find a '/', the line is malformed and we just skip
252N/A * it.
252N/A */
252N/A while (*ib) {
252N/A if (*ib != '/')
252N/A ib++;
252N/A else
252N/A break;
252N/A }
252N/A if (!(*ib))
252N/A goto done;
252N/A
252N/A /*
252N/A * Find the trailing '"' in the line. If not found, we just
252N/A * skip the line.
252N/A */
252N/A
252N/A rpt = strchr(ib, (int)'""');
252N/A if (rpt != NULL)
252N/A rpt = strchr(rpt, (int)'""');
252N/A
252N/A /*
252N/A * Find a matching entry in the list of names from /dev/dsk.
252N/A * If no match, we're not interested.
252N/A */
252N/A if (!rpt)
252N/A goto done;
252N/A
252N/A *rpt = '\0';
252N/A
252N/A
252N/A if ((entry = find_str(ib, list)) == (nms_t *)NULL)
252N/A goto done;
252N/A
252N/A bpt = rpt;
252N/A /*
252N/A * Extract the device number at the end of
252N/A * the line. We expect whitespace followed by
252N/A * the beginning of the currently numeric
252N/A * device id string;
252N/A */
252N/A rpt++;
252N/A done = 0;
252N/A while (!done) {
252N/A if (*rpt) {
252N/A if (*rpt != '\n') {
252N/A if (isspace((int)*rpt))
252N/A rpt++;
252N/A else
252N/A done++;
252N/A } else
252N/A done++;
252N/A } else
252N/A done++;
252N/A }
252N/A /*
252N/A * Should now be at the beginning of the
252N/A * device number. Point entry->dn at the
252N/A * string.
252N/A */
252N/A if (*rpt) {
252N/A v = rpt;
252N/A len = 0;
252N/A while (v) {
252N/A if (*v != '\n') {
252N/A v++;
252N/A len++;
252N/A } else {
252N/A *v = '\0';
252N/A v = (char *)NULL;
252N/A }
252N/A }
252N/A if (len) {
252N/A entry->dnum = atoi(rpt);
252N/A while (bpt > ib) {
252N/A if (*bpt != '@')
252N/A bpt--;
252N/A else
252N/A break;
252N/A }
252N/A if (bpt > ib) {
252N/A *bpt-- = '\0';
252N/A len = 0;
252N/A while (bpt > ib) {
252N/A if (*bpt != '/') {
252N/A bpt--;
252N/A len++;
252N/A } else
252N/A break;
252N/A }
252N/A if (bpt > ib) {
252N/A bpt++;
252N/A len++;
252N/A entry->dty = (char *)malloc(len);
252N/A if (entry->dty) {
252N/A (void) strcpy(entry->dty, bpt);
252N/A rv++;
252N/A }
252N/A }
252N/A }
252N/A }
252N/A }
252N/Adone:
252N/A return (rv);
252N/A}
252N/A
252N/A
252N/A
252N/Astatic nms_t *
252N/Afind_str(const char *inbuf, nms_t *list)
252N/A{
252N/A while (list) {
252N/A if (strcmp(inbuf, list->real) != 0)
252N/A list = list->next;
252N/A else
252N/A break;
252N/A }
252N/A return (list);
252N/A}
252N/A
252N/A
252N/A
252N/Astatic void
252N/Amk_list_of_disks(nms_t *list, disk_list_t **hd)
252N/A{
252N/A while (list) {
252N/A insert_dlist_ent(list->dsk, list->dnum, list->dty,
252N/A list->devtype, hd);
252N/A list = list->next;
252N/A }
252N/A}
252N/A
252N/A
252N/A
252N/A/*
252N/A * Determine if a name is already in the list of disks. If not, insert the
252N/A * name in the list.
252N/A */
252N/A
252N/A
252N/Astatic void
252N/Ainsert_dlist_ent(const char *nm, const int dn, const char *dty,
252N/A int devtype, disk_list_t ** hd)
252N/A{
252N/A disk_list_t *stuff;
252N/A int i, len;
252N/A
252N/A if (dty == NULL)
252N/A return;
252N/A
252N/A stuff = *hd;
252N/A while (stuff) {
252N/A if (strcmp(nm, stuff->dsk) != 0)
252N/A stuff = stuff->next;
252N/A else
252N/A break;
252N/A }
252N/A if (!stuff) {
252N/A disk_list_t *entry;
252N/A int mv;
252N/A
252N/A entry = (disk_list_t *)malloc(
252N/A sizeof (disk_list_t));
252N/A if (entry) {
252N/A entry->dnum = dn;
252N/A entry->dsk = (char *)nm;
252N/A entry->dtype = (char *)dty;
252N/A
252N/A len = strlen(nm) + 4;
252N/A for (i = 0; i < NDKMAP; i++) {
252N/A if (devtype == DISK) {
252N/A entry->dpart[i] = (char *)malloc(len);
252N/A if (entry->dpart[i]) {
252N/A (void) sprintf(entry->dpart[i],
252N/A "%ss%d\0", nm, i);
252N/A }
252N/A } else
252N/A entry->dpart[i] = NULL;
252N/A }
252N/A /*
252N/A * Figure out where to insert the name. The list is
252N/A * ostensibly in sorted order.
252N/A */
252N/A if (*hd != (disk_list_t *)NULL) {
252N/A disk_list_t *follw;
252N/A stuff = *hd;
252N/A
252N/A /*
252N/A * Look through the list. While the strcmp
252N/A * value is less than the current value,
252N/A */
252N/A while (stuff) {
252N/A if ((mv = strcmp(entry->dtype,
252N/A stuff->dtype)) < 0) {
252N/A follw = stuff;
252N/A stuff = stuff->next;
252N/A } else
252N/A break;
252N/A }
252N/A if (mv == 0) {
252N/A while (stuff) {
252N/A if (strcmp(entry->dtype,
252N/A stuff->dtype) != 0)
252N/A break;
252N/A if (dn > stuff->dnum) {
252N/A follw = stuff;
252N/A stuff = stuff->next;
252N/A } else
252N/A break;
252N/A }
252N/A }
252N/A /*
252N/A * We should now be ready to insert an
252N/A * entry...
252N/A */
252N/A if (mv >= 0) {
252N/A if (stuff == *hd) {
252N/A entry->next = stuff;
252N/A *hd = entry;
252N/A } else {
252N/A entry->next = follw->next;
252N/A follw->next = entry;
252N/A }
252N/A } else {
252N/A /*
252N/A * insert at the end of the
252N/A * list
252N/A */
252N/A follw->next = entry;
252N/A entry->next = (disk_list_t *)NULL;
252N/A }
252N/A } else {
252N/A *hd = entry;
252N/A entry->next = (disk_list_t *)NULL;
252N/A }
252N/A }
252N/A }
252N/A}
252N/A
252N/A
252N/A
252N/Achar *
252N/Alookup_ks_name(char *dev_nm, void *val)
252N/A{
252N/A char *rv = (char *)0;
252N/A int dv;
252N/A char *device;
252N/A int len;
252N/A char cmpbuf[1024];
252N/A struct list_of_disks *list;
252N/A char nmbuf[1024];
252N/A char *tmpnm;
252N/A char *nm;
252N/A int partition;
252N/A
252N/A tmpnm = nm = nmbuf;
252N/A while ((*dev_nm) && (*dev_nm != ',')) {
252N/A *tmpnm++ = *dev_nm++;
252N/A }
252N/A *tmpnm = '\0';
252N/A
252N/A if (*dev_nm == ',') {
252N/A dev_nm++;
252N/A partition = (int)(*dev_nm - 'a');
252N/A if ((partition < 0) || (partition > NDKMAP))
252N/A partition = -1;
252N/A } else
252N/A partition = -1;
252N/A
252N/A list = (disk_list_t *)val;
252N/A device = nm;
252N/A len = 0;
252N/A while (*nm) {
252N/A if (isalpha((int)*nm)) {
252N/A nm++;
252N/A len++;
252N/A } else
252N/A break;
252N/A }
252N/A (void) strncpy(cmpbuf, device, len);
252N/A cmpbuf[len] = '\0';
252N/A
252N/A if (*nm) {
252N/A int mv;
252N/A
252N/A dv = atoi(nm);
252N/A while (list) {
252N/A if ((mv = strcmp(cmpbuf, list->dtype)) < 0)
252N/A list = list->next;
252N/A else
252N/A break;
252N/A }
252N/A if (mv == 0) {
252N/A while (list) {
252N/A if (list->dnum < dv)
252N/A list = list->next;
252N/A else
252N/A break;
252N/A }
252N/A if(list) {
252N/A if (list->dnum == dv) {
252N/A if ((partition != -1) &&
252N/A (list->dpart[partition] != NULL))
252N/A rv = list->dpart[partition];
252N/A else
252N/A rv = list->dsk;
252N/A }
252N/A }
252N/A }
252N/A }
252N/A return (rv);
252N/A}
252N/A
252N/A
252N/A
252N/Astatic int
252N/Astr_is_digit(char *str)
252N/A{
252N/A int i;
252N/A int j = 0;
252N/A
252N/A for (i = 0; i < (int)strlen(str); i++) {
252N/A if (isdigit(str[i])) j++;
252N/A }
252N/A
252N/A if (j == strlen(str))
252N/A return (1);
252N/A else
252N/A return (0);
252N/A}
252N/A