mkdevalloc.c revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e
/*
* 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"
/*
* scan /dev directory for mountable objects and construct device_allocate
* file for allocate....
*
* devices are:
* tape (cartridge)
* /dev/rst*
* /dev/nrst*
* /dev/rmt/...
* audio
* /dev/audio
* /dev/audioctl
* /dev/sound/...
* floppy
* /dev/diskette
* /dev/fd*
* /dev/rdiskette
* /dev/rfd*
* CD
* /dev/sr*
* /dev/nsr*
* /dev/dsk/c?t?d0s?
* /dev/rdsk/c?t?d0s?
*
*/
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h> /* for stat(2), etc. */
#include <sys/stat.h>
#include <dirent.h> /* for readdir(3), etc. */
#include <unistd.h> /* for readlink(2) */
#include <stropts.h>
#include <string.h> /* for strcpy(3), etc. */
#include <strings.h> /* for bcopy(3C), etc. */
#include <stdio.h> /* for perror(3) */
#include <stdlib.h> /* for atoi(3) */
#include <sys/dkio.h>
#include <locale.h>
#include <libintl.h>
#include <libdevinfo.h>
#include <secdb.h>
#include <auth_attr.h>
#include <auth_list.h>
#include <bsm/devices.h>
#include <bsm/devalloc.h>
#include <tsol/label.h>
#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SUNW_OST_OSCMD"
#endif
#define MKDEVALLOC "mkdevalloc"
#define MKDEVMAPS "mkdevmaps"
#define DELTA 5 /* array size delta when full */
#define SECLIB "/etc/security/lib"
/* "/dev/rst...", "/dev/nrst...", "/dev/rmt/..." */
struct tape {
char *name;
char *device;
int number;
} *tape;
#define DFLT_NTAPE 10 /* size of initial array */
#define SIZE_OF_RST 3 /* |rmt| */
#define SIZE_OF_NRST 4 /* |nrmt| */
#define SIZE_OF_TMP 4 /* |/tmp| */
#define SIZE_OF_RMT 8 /* |/dev/rmt| */
#define TAPE_CLEAN SECLIB"/st_clean"
/* "/dev/audio", "/dev/audioctl", "/dev/sound/..." */
struct audio {
char *name;
char *device;
int number;
} *audio;
#define DFLT_NAUDIO 10 /* size of initial array */
#define SIZE_OF_SOUND 10 /* |/dev/sound| */
#define AUDIO_CLEAN SECLIB"/audio_clean"
/* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */
struct cd {
char *name;
char *device;
int id;
int controller;
int number;
} *cd;
#define DFLT_NCD 10 /* size of initial array */
#define SIZE_OF_SR 2 /* |sr| */
#define SIZE_OF_RSR 3 /* |rsr| */
#define SIZE_OF_DSK 8 /* |/dev/dsk| */
#define SIZE_OF_RDSK 9 /* |/dev/rdsk| */
#define CD_CLEAN SECLIB"/sr_clean"
/* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */
struct rmdisk {
char *name;
char *device;
int id;
int controller;
int number;
} *rmdisk, *rmdisk_r;
#define DFLT_RMDISK 10 /* size of initial array */
/* "/dev/fd0*", "/dev/rfd0*", "/dev/fd1*", "/dev/rfd1*" */
struct fp {
char *name;
char *device;
int number;
} *fp;
#define DFLT_NFP 10 /* size of initial array */
#define SIZE_OF_FD0 3 /* |fd0| */
#define SIZE_OF_RFD0 4 /* |rfd0| */
#define FLOPPY_CLEAN SECLIB"/fd_clean"
static void dotape();
static void doaudio();
static void dofloppy();
static int docd();
static void dormdisk(int);
static void initmem();
static int expandmem(int, void **, int);
static void no_memory(void);
int system_labeled = 0;
int do_devalloc = 0;
int do_devmaps = 0;
int do_files = 0;
devlist_t devlist;
int
main(int argc, char **argv)
{
int cd_count = 0;
char *progname;
struct stat tx_stat;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;
if (strcmp(progname, MKDEVALLOC) == 0)
do_devalloc = 1;
else if (strcmp(progname, MKDEVMAPS) == 0)
do_devmaps = 1;
else
exit(1);
system_labeled = is_system_labeled();
if (system_labeled == 0) {
/*
* is_system_labeled() will return false in case we are
* starting before the first reboot after Trusted Extensions
* is installed. we check for a well known TX binary to
* to see if TX is installed.
*/
if (stat(DA_LABEL_CHECK, &tx_stat) == 0)
system_labeled = 1;
}
if (system_labeled && do_devalloc && (argc == 2) &&
(strcmp(argv[1], DA_IS_LABELED) == 0)) {
/*
* write device entries to device_allocate and device_maps.
* default is to print them on stdout.
*/
do_files = 1;
}
initmem(); /* initialize memory */
dotape();
doaudio();
dofloppy();
cd_count = docd();
if (system_labeled)
dormdisk(cd_count);
return (0);
}
static void
dotape()
{
DIR *dirp;
struct dirent *dep; /* directory entry pointer */
int i, j;
char *nm; /* name/device of special device */
char linkvalue[2048]; /* symlink value */
struct stat stat; /* determine if it's a symlink */
int sz; /* size of symlink value */
char *cp; /* pointer into string */
int ntape; /* max array size */
int tape_count;
int first = 0;
char *dname, *dtype, *dclean;
da_args dargs;
deventry_t *entry;
ntape = DFLT_NTAPE;
/*
* look for rst* and nrst*
*/
if ((dirp = opendir("/dev")) == NULL) {
perror(gettext("open /dev failure"));
exit(1);
}
i = 0;
while (dep = readdir(dirp)) {
/* ignore if neither rst* nor nrst* */
if (strncmp(dep->d_name, "rst", SIZE_OF_RST) &&
strncmp(dep->d_name, "nrst", SIZE_OF_NRST))
continue;
/* if array full, then expand it */
if (i == ntape) {
/* will exit(1) if insufficient memory */
ntape = expandmem(i, (void **)&tape,
sizeof (struct tape));
}
/* save name (/dev + / + d_name + \0) */
nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/");
(void) strcat(nm, dep->d_name);
tape[i].name = nm;
/* ignore if not symbolic link (note i not incremented) */
if (lstat(tape[i].name, &stat) < 0) {
perror("stat(2) failed ");
exit(1);
}
if ((stat.st_mode & S_IFMT) != S_IFLNK)
continue;
/* get name from symbolic link */
if ((sz = readlink(tape[i].name, linkvalue,
sizeof (linkvalue))) < 0)
continue;
nm = (char *)malloc(sz + 1);
if (nm == NULL)
no_memory();
(void) strncpy(nm, linkvalue, sz);
nm[sz] = '\0';
tape[i].device = nm;
/* get device number */
cp = strrchr(tape[i].device, '/');
cp++; /* advance to device # */
(void) sscanf(cp, "%d", &tape[i].number);
i++;
}
(void) closedir(dirp);
/*
* scan /dev/rmt and add entry to table
*/
if ((dirp = opendir("/dev/rmt")) == NULL) {
perror(gettext("open /dev failure"));
exit(1);
}
while (dep = readdir(dirp)) {
/* skip . .. etc... */
if (strncmp(dep->d_name, ".", 1) == NULL)
continue;
/* if array full, then expand it */
if (i == ntape) {
/* will exit(1) if insufficient memory */
ntape = expandmem(i, (void **)&tape,
sizeof (struct tape));
}
/* save name (/dev/rmt + / + d_name + \0) */
nm = (char *)malloc(SIZE_OF_RMT + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/rmt/");
(void) strcat(nm, dep->d_name);
tape[i].name = nm;
/* save device name (rmt/ + d_name + \0) */
nm = (char *)malloc(SIZE_OF_TMP + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "rmt/");
(void) strcat(nm, dep->d_name);
tape[i].device = nm;
(void) sscanf(dep->d_name, "%d", &tape[i].number);
i++;
}
tape_count = i;
(void) closedir(dirp);
/* remove duplicate entries */
for (i = 0; i < tape_count - 1; i++) {
for (j = i + 1; j < tape_count; j++) {
if (strcmp(tape[i].device, tape[j].device))
continue;
tape[j].number = -1;
}
}
if (system_labeled) {
dname = DA_TAPE_NAME;
dtype = DA_TAPE_TYPE;
dclean = DA_DEFAULT_TAPE_CLEAN;
} else {
dname = "st";
dtype = "st";
dclean = TAPE_CLEAN;
}
for (i = 0; i < 8; i++) {
for (j = 0; j < tape_count; j++) {
if (tape[j].number != i)
continue;
if (do_files) {
(void) da_add_list(&devlist, tape[j].name, i,
DA_TAPE);
} else if (do_devalloc) {
/* print device_allocate for tape devices */
if (system_labeled) {
(void) printf("%s%d%s\\\n",
dname, i, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_TAPE_TYPE, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DEFAULT_DEV_ALLOC_AUTH,
KV_DELIMITER);
(void) printf("\t%s\n\n", dclean);
} else {
(void) printf(
"st%d;st;reserved;reserved;%s;",
i, DEFAULT_DEV_ALLOC_AUTH);
(void) printf("%s%s\n", SECLIB,
"/st_clean");
}
break;
} else if (do_devmaps) {
/* print device_maps for tape devices */
if (first) {
(void) printf(" ");
} else {
if (system_labeled) {
(void) printf("%s%d%s\\\n",
dname, i, KV_TOKEN_DELIMIT);
(void) printf("\t%s%s\\\n",
dtype, KV_TOKEN_DELIMIT);
(void) printf("\t");
} else {
(void) printf("st%d:\\\n", i);
(void) printf("\trmt:\\\n");
(void) printf("\t");
}
first++;
}
(void) printf("%s", tape[j].name);
}
}
if (do_devmaps && first) {
(void) printf("\n\n");
first = 0;
}
}
if (do_files && tape_count) {
dargs.rootdir = NULL;
dargs.devnames = NULL;
dargs.optflag = DA_ADD;
for (entry = devlist.tape; entry != NULL; entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
}
}
static void
doaudio()
{
DIR *dirp;
struct dirent *dep; /* directory entry pointer */
int i, j;
char *nm; /* name/device of special device */
char linkvalue[2048]; /* symlink value */
struct stat stat; /* determine if it's a symlink */
int sz; /* size of symlink value */
char *cp; /* pointer into string */
int naudio; /* max array size */
int audio_count = 0;
int len, slen;
int first = 0;
char dname[128];
char *dclean;
da_args dargs;
deventry_t *entry;
naudio = DFLT_NAUDIO;
if ((dirp = opendir("/dev")) == NULL) {
perror(gettext("open /dev failure"));
exit(1);
}
i = 0;
while (dep = readdir(dirp)) {
if (strcmp(dep->d_name, "audio") &&
strcmp(dep->d_name, "audioctl"))
continue;
/* if array full, then expand it */
if (i == naudio) {
/* will exit(1) if insufficient memory */
naudio = expandmem(i, (void **)&audio,
sizeof (struct audio));
}
/* save name (/dev + 1 + d_name + \0) */
nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/");
(void) strcat(nm, dep->d_name);
audio[i].name = nm;
/* ignore if not symbolic link (note i not incremented) */
if (lstat(audio[i].name, &stat) < 0) {
perror(gettext("stat(2) failed "));
exit(1);
}
if ((stat.st_mode & S_IFMT) != S_IFLNK)
continue;
/* get name from symbolic link */
if ((sz = readlink(audio[i].name, linkvalue,
sizeof (linkvalue))) < 0)
continue;
nm = (char *)malloc(sz + 1);
if (nm == NULL)
no_memory();
(void) strncpy(nm, linkvalue, sz);
nm[sz] = '\0';
audio[i].device = nm;
cp = strrchr(audio[i].device, '/');
cp++; /* advance to device # */
(void) sscanf(cp, "%d", &audio[i].number);
i++;
}
(void) closedir(dirp);
if ((dirp = opendir("/dev/sound")) == NULL) {
goto skip;
}
while (dep = readdir(dirp)) {
/* skip . .. etc... */
if (strncmp(dep->d_name, ".", 1) == NULL)
continue;
/* if array full, then expand it */
if (i == naudio) {
/* will exit(1) if insufficient memory */
naudio = expandmem(i, (void **)&audio,
sizeof (struct audio));
}
/* save name (/dev/sound + / + d_name + \0) */
nm = (char *)malloc(SIZE_OF_SOUND + 1 +
strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/sound/");
(void) strcat(nm, dep->d_name);
audio[i].name = nm;
nm = (char *)malloc(SIZE_OF_SOUND + 1 +
strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/sound/");
(void) strcat(nm, dep->d_name);
audio[i].device = nm;
(void) sscanf(dep->d_name, "%d", &audio[i].number);
i++;
}
(void) closedir(dirp);
skip:
audio_count = i;
/* remove duplicate entries */
for (i = 0; i < audio_count - 1; i++) {
for (j = i + 1; j < audio_count; j++) {
if (strcmp(audio[i].device, audio[j].device))
continue;
audio[j].number = -1;
}
}
/* print out device_allocate entries for audio devices */
(void) strcpy(dname, DA_AUDIO_NAME);
slen = strlen(DA_AUDIO_NAME);
len = sizeof (dname) - slen;
dclean = system_labeled ? DA_DEFAULT_AUDIO_CLEAN : AUDIO_CLEAN;
for (i = 0; i < 8; i++) {
for (j = 0; j < audio_count; j++) {
if (audio[j].number != i)
continue;
if (system_labeled)
(void) snprintf(dname+slen, len, "%d", i);
if (do_files) {
(void) da_add_list(&devlist, audio[j].name,
i, DA_AUDIO);
} else if (do_devalloc) {
/* print device_allocate for audio devices */
if (system_labeled) {
(void) printf("%s%s\\\n",
dname, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_AUDIO_TYPE, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DEFAULT_DEV_ALLOC_AUTH,
KV_DELIMITER);
(void) printf("\t%s\n\n", dclean);
} else {
(void) printf("audio;audio;");
(void) printf("reserved;reserved;%s;",
DEFAULT_DEV_ALLOC_AUTH);
(void) printf("%s%s\n", SECLIB,
"/audio_clean");
}
break;
} else if (do_devmaps) {
/* print device_maps for audio devices */
if (first) {
(void) printf(" ");
} else {
if (system_labeled) {
(void) printf("%s%s\\\n",
dname, KV_TOKEN_DELIMIT);
(void) printf("\t%s%s\\\n",
DA_AUDIO_TYPE,
KV_TOKEN_DELIMIT);
(void) printf("\t");
} else {
(void) printf("audio:\\\n");
(void) printf("\taudio:\\\n");
(void) printf("\t");
}
first++;
}
(void) printf("%s", audio[j].name);
}
}
if (do_devmaps && first) {
(void) printf("\n\n");
first = 0;
}
}
if (do_files && audio_count) {
dargs.rootdir = NULL;
dargs.devnames = NULL;
dargs.optflag = DA_ADD;
for (entry = devlist.audio; entry != NULL;
entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
}
}
static void
dofloppy()
{
DIR *dirp;
struct dirent *dep; /* directory entry pointer */
int i, j;
char *nm; /* name/device of special device */
char linkvalue[2048]; /* symlink value */
struct stat stat; /* determine if it's a symlink */
int sz; /* size of symlink value */
char *cp; /* pointer into string */
int nfp; /* max array size */
int floppy_count = 0;
int first = 0;
char *dname, *dclean;
da_args dargs;
deventry_t *entry;
nfp = DFLT_NFP;
/*
* look for fd* and rfd*
*/
if ((dirp = opendir("/dev")) == NULL) {
perror(gettext("open /dev failure"));
exit(1);
}
i = 0;
while (dep = readdir(dirp)) {
/* ignore if neither rst* nor nrst* */
if (strncmp(dep->d_name, "fd0", SIZE_OF_FD0) &&
strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0) &&
strncmp(dep->d_name, "fd1", SIZE_OF_FD0) &&
strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0))
continue;
/* if array full, then expand it */
if (i == nfp) {
/* will exit(1) if insufficient memory */
nfp = expandmem(i, (void **)&fp, sizeof (struct fp));
}
/* save name (/dev + 1 + d_name + \0) */
nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/");
(void) strcat(nm, dep->d_name);
fp[i].name = nm;
/* ignore if not symbolic link (note i not incremented) */
if (lstat(fp[i].name, &stat) < 0) {
perror(gettext("stat(2) failed "));
exit(1);
}
if ((stat.st_mode&S_IFMT) != S_IFLNK)
continue;
/* get name from symbolic link */
if ((sz = readlink(fp[i].name, linkvalue,
sizeof (linkvalue))) < 0)
continue;
nm = (char *)malloc(sz+1);
if (nm == NULL)
no_memory();
(void) strncpy(nm, linkvalue, sz);
nm[sz] = '\0';
fp[i].device = nm;
/* get device number */
cp = strchr(fp[i].name, 'd');
cp++; /* advance to device # */
cp = strchr(cp, 'd');
cp++; /* advance to device # */
(void) sscanf(cp, "%d", &fp[i].number);
i++;
}
(void) closedir(dirp);
floppy_count = i;
/* print out device_allocate entries for floppy devices */
if (system_labeled) {
dname = DA_FLOPPY_NAME;
dclean = DA_DEFAULT_DISK_CLEAN;
} else {
dname = "fd";
dclean = FLOPPY_CLEAN;
}
for (i = 0; i < 8; i++) {
for (j = 0; j < floppy_count; j++) {
if (fp[j].number != i)
continue;
if (do_files) {
(void) da_add_list(&devlist, fp[j].name, i,
DA_FLOPPY);
} else if (do_devalloc) {
/* print device_allocate for floppy devices */
if (system_labeled) {
(void) printf("%s%d%s\\\n",
dname, i, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_FLOPPY_TYPE, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DEFAULT_DEV_ALLOC_AUTH,
KV_DELIMITER);
(void) printf("\t%s\n\n", dclean);
} else {
(void) printf(
"fd%d;fd;reserved;reserved;%s;",
i, DEFAULT_DEV_ALLOC_AUTH);
(void) printf("%s%s\n", SECLIB,
"/fd_clean");
}
break;
} else if (do_devmaps) {
/* print device_maps for floppy devices */
if (first) {
(void) printf(" ");
} else {
if (system_labeled) {
(void) printf("%s%d%s\\\n",
dname, i, KV_TOKEN_DELIMIT);
(void) printf("\t%s%s\\\n",
DA_FLOPPY_TYPE,
KV_TOKEN_DELIMIT);
(void) printf("\t");
} else {
(void) printf("fd%d:\\\n", i);
(void) printf("\tfd:\\\n");
(void) printf("\t");
}
if (i == 0) {
(void) printf("/dev/diskette ");
(void) printf(
"/dev/rdiskette ");
}
first++;
}
(void) printf("%s", fp[j].name);
}
}
if (do_devmaps && first) {
(void) printf("\n\n");
first = 0;
}
}
if (do_files && floppy_count) {
dargs.rootdir = NULL;
dargs.devnames = NULL;
dargs.optflag = DA_ADD;
for (entry = devlist.floppy; entry != NULL;
entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
}
}
static int
docd()
{
DIR *dirp;
struct dirent *dep; /* directory entry pointer */
int i, j;
char *nm; /* name/device of special device */
char linkvalue[2048]; /* symlink value */
struct stat stat; /* determine if it's a symlink */
int sz; /* size of symlink value */
char *cp; /* pointer into string */
int id; /* disk id */
int ctrl; /* disk controller */
int ncd; /* max array size */
int cd_count = 0;
int first = 0;
char *dname, *dclean;
da_args dargs;
deventry_t *entry;
ncd = DFLT_NCD;
/*
* look for sr* and rsr*
*/
if ((dirp = opendir("/dev")) == NULL) {
perror(gettext("open /dev failure"));
exit(1);
}
i = 0;
while (dep = readdir(dirp)) {
/* ignore if neither sr* nor rsr* */
if (strncmp(dep->d_name, "sr", SIZE_OF_SR) &&
strncmp(dep->d_name, "rsr", SIZE_OF_RSR))
continue;
/* if array full, then expand it */
if (i == ncd) {
/* will exit(1) if insufficient memory */
ncd = expandmem(i, (void **)&cd, sizeof (struct cd));
}
/* save name (/dev + / + d_name + \0) */
nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/");
(void) strcat(nm, dep->d_name);
cd[i].name = nm;
/* save id # */
if (dep->d_name[0] == 'r')
(void) sscanf(dep->d_name, "rsr%d", &cd[i].id);
else
(void) sscanf(dep->d_name, "sr%d", &cd[i].id);
/* ignore if not symbolic link (note i not incremented) */
if (lstat(cd[i].name, &stat) < 0) {
perror(gettext("stat(2) failed "));
exit(1);
}
if ((stat.st_mode & S_IFMT) != S_IFLNK)
continue;
/* get name from symbolic link */
if ((sz = readlink(cd[i].name, linkvalue, sizeof (linkvalue))) <
0)
continue;
nm = (char *)malloc(sz + 1);
if (nm == NULL)
no_memory();
(void) strncpy(nm, linkvalue, sz);
nm[sz] = '\0';
cd[i].device = nm;
cp = strrchr(cd[i].device, '/');
cp++; /* advance to device # */
(void) sscanf(cp, "c%dt%d", &cd[i].controller, &cd[i].number);
i++;
}
cd_count = i;
(void) closedir(dirp);
/*
* scan /dev/dsk for cd devices
*/
if ((dirp = opendir("/dev/dsk")) == NULL) {
perror("gettext(open /dev/dsk failure)");
exit(1);
}
while (dep = readdir(dirp)) {
/* skip . .. etc... */
if (strncmp(dep->d_name, ".", 1) == NULL)
continue;
/* get device # (disk #) */
if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
continue;
/* see if this is one of the cd special devices */
for (j = 0; j < cd_count; j++) {
if (cd[j].number == id && cd[j].controller == ctrl)
goto found;
}
continue;
/* add new entry to table (/dev/dsk + / + d_name + \0) */
found:
/* if array full, then expand it */
if (i == ncd) {
/* will exit(1) if insufficient memory */
ncd = expandmem(i, (void **)&cd, sizeof (struct cd));
}
nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/dsk/");
(void) strcat(nm, dep->d_name);
cd[i].name = nm;
cd[i].id = cd[j].id;
cd[i].device = "";
cd[i].number = id;
i++;
}
(void) closedir(dirp);
/*
* scan /dev/rdsk for cd devices
*/
if ((dirp = opendir("/dev/rdsk")) == NULL) {
perror(gettext("open /dev/dsk failure"));
exit(1);
}
while (dep = readdir(dirp)) {
/* skip . .. etc... */
if (strncmp(dep->d_name, ".", 1) == NULL)
continue;
/* get device # (disk #) */
if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) != 2)
continue;
/* see if this is one of the cd special devices */
for (j = 0; j < cd_count; j++) {
if (cd[j].number == id && cd[j].controller == ctrl)
goto found1;
}
continue;
/* add new entry to table (/dev/rdsk + / + d_name + \0) */
found1:
/* if array full, then expand it */
if (i == ncd) {
/* will exit(1) if insufficient memory */
ncd = expandmem(i, (void **)&cd, sizeof (struct cd));
}
nm = (char *)malloc(SIZE_OF_RDSK + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/rdsk/");
(void) strcat(nm, dep->d_name);
cd[i].name = nm;
cd[i].id = cd[j].id;
cd[i].device = "";
cd[i].number = id;
cd[i].controller = ctrl;
i++;
}
(void) closedir(dirp);
cd_count = i;
if (system_labeled) {
dname = DA_CD_NAME;
dclean = DA_DEFAULT_DISK_CLEAN;
} else {
dname = "sr";
dclean = CD_CLEAN;
}
for (i = 0; i < 8; i++) {
for (j = 0; j < cd_count; j++) {
if (cd[j].id != i)
continue;
if (do_files) {
(void) da_add_list(&devlist, cd[j].name, i,
DA_CD);
} else if (do_devalloc) {
/* print device_allocate for cd devices */
if (system_labeled) {
(void) printf("%s%d%s\\\n",
dname, i, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_CD_TYPE, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DEFAULT_DEV_ALLOC_AUTH,
KV_DELIMITER);
(void) printf("\t%s\n\n", dclean);
} else {
(void) printf(
"sr%d;sr;reserved;reserved;%s;",
i, DEFAULT_DEV_ALLOC_AUTH);
(void) printf("%s%s\n", SECLIB,
"/sr_clean");
}
break;
} else if (do_devmaps) {
/* print device_maps for cd devices */
if (first) {
(void) printf(" ");
} else {
if (system_labeled) {
(void) printf("%s%d%s\\\n",
dname, i, KV_TOKEN_DELIMIT);
(void) printf("\t%s%s\\\n",
DA_CD_TYPE,
KV_TOKEN_DELIMIT);
(void) printf("\t");
} else {
(void) printf("sr%d:\\\n", i);
(void) printf("\tsr:\\\n");
(void) printf("\t");
}
first++;
}
(void) printf("%s", cd[j].name);
}
}
if (do_devmaps && first) {
(void) printf("\n\n");
first = 0;
}
}
if (do_files && cd_count) {
dargs.rootdir = NULL;
dargs.devnames = NULL;
dargs.optflag = DA_ADD;
for (entry = devlist.cd; entry != NULL; entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
}
return (cd_count);
}
static void
dormdisk(int cd_count)
{
DIR *dirp;
struct dirent *dep; /* directory entry pointer */
int i, j;
char *nm; /* name/device of special device */
int id; /* disk id */
int ctrl; /* disk controller */
int nrmdisk; /* max array size */
int fd = -1;
int rmdisk_count;
int first = 0;
int is_cd;
int checked;
int removable;
char path[MAXPATHLEN];
da_args dargs;
deventry_t *entry;
nrmdisk = DFLT_RMDISK;
i = rmdisk_count = 0;
/*
* scan /dev/dsk for rmdisk devices
*/
if ((dirp = opendir("/dev/dsk")) == NULL) {
perror("gettext(open /dev/dsk failure)");
exit(1);
}
while (dep = readdir(dirp)) {
is_cd = 0;
checked = 0;
removable = 0;
/* skip . .. etc... */
if (strncmp(dep->d_name, ".", 1) == NULL)
continue;
/* get device # (disk #) */
if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
continue;
/* see if we've already examined this device */
for (j = 0; j < i; j++) {
if (id == rmdisk[j].id &&
ctrl == rmdisk[j].controller &&
(strcmp(dep->d_name, rmdisk[j].name) == 0)) {
checked = 1;
break;
}
if (id == rmdisk[j].id && ctrl != rmdisk[j].controller)
/*
* c2t0d0s0 is a different rmdisk than c3t0d0s0.
*/
id = rmdisk[j].id + 1;
}
if (checked)
continue;
/* ignore if this is a cd */
for (j = 0; j < cd_count; j++) {
if (id == cd[j].number && ctrl == cd[j].controller) {
is_cd = 1;
break;
}
}
if (is_cd)
continue;
/* see if device is removable */
(void) snprintf(path, sizeof (path), "%s%s", "/dev/rdsk/",
dep->d_name);
if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0)
continue;
(void) ioctl(fd, DKIOCREMOVABLE, &removable);
(void) close(fd);
if (removable == 0)
continue;
/*
* add new entry to table (/dev/dsk + / + d_name + \0)
* if array full, then expand it
*/
if (i == nrmdisk) {
/* will exit(1) if insufficient memory */
nrmdisk = expandmem(i, (void **)&rmdisk,
sizeof (struct rmdisk));
}
nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
no_memory();
(void) strcpy(nm, "/dev/dsk/");
(void) strcat(nm, dep->d_name);
rmdisk[i].name = nm;
rmdisk[i].id = id;
rmdisk[i].controller = ctrl;
rmdisk[i].device = "";
rmdisk[i].number = id;
rmdisk_r[i].name = strdup(path);
i++;
}
rmdisk_count = i;
(void) closedir(dirp);
for (i = 0, j = rmdisk_count; i < rmdisk_count; i++, j++) {
if (j == nrmdisk) {
/* will exit(1) if insufficient memory */
nrmdisk = expandmem(j, (void **)&rmdisk,
sizeof (struct rmdisk));
}
rmdisk[j].name = rmdisk_r[i].name;
rmdisk[j].id = rmdisk[i].id;
rmdisk[j].controller = rmdisk[i].controller;
rmdisk[j].device = rmdisk[i].device;
rmdisk[j].number = rmdisk[i].number;
}
rmdisk_count = j;
for (i = 0; i < 8; i++) {
for (j = 0; j < rmdisk_count; j++) {
if (rmdisk[j].id != i)
continue;
if (do_files) {
(void) da_add_list(&devlist, rmdisk[j].name, i,
DA_RMDISK);
} else if (do_devalloc) {
/* print device_allocate for rmdisk devices */
(void) printf("%s%d%s\\\n",
DA_RMDISK_NAME, i, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RMDISK_TYPE, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DA_RESERVED, KV_DELIMITER);
(void) printf("\t%s%s\\\n",
DEFAULT_DEV_ALLOC_AUTH, KV_DELIMITER);
(void) printf("\t%s\n", DA_DEFAULT_DISK_CLEAN);
break;
} else if (do_devmaps) {
/* print device_maps for rmdisk devices */
if (first) {
(void) printf(" ");
} else {
(void) printf("%s%d%s\\\n",
DA_RMDISK_NAME, i,
KV_TOKEN_DELIMIT);
(void) printf("\t%s%s\\\n",
DA_RMDISK_TYPE, KV_TOKEN_DELIMIT);
(void) printf("\t");
first++;
}
(void) printf("%s", rmdisk[j].name);
}
}
if (do_devmaps && first) {
(void) printf("\n\n");
first = 0;
}
}
if (do_files && rmdisk_count) {
dargs.rootdir = NULL;
dargs.devnames = NULL;
dargs.optflag = DA_ADD;
for (entry = devlist.rmdisk; entry != NULL;
entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
}
}
/* set default array sizes */
static void
initmem()
{
tape = (struct tape *)calloc(DFLT_NTAPE, sizeof (struct tape));
audio = (struct audio *)calloc(DFLT_NAUDIO, sizeof (struct audio));
cd = (struct cd *)calloc(DFLT_NCD, sizeof (struct cd));
fp = (struct fp *)calloc(DFLT_NFP, sizeof (struct fp));
if (system_labeled) {
rmdisk = (struct rmdisk *)calloc(DFLT_RMDISK,
sizeof (struct rmdisk));
if (rmdisk == NULL)
no_memory();
rmdisk_r = (struct rmdisk *)calloc(DFLT_RMDISK,
sizeof (struct rmdisk));
if (rmdisk_r == NULL)
no_memory();
}
if (tape == NULL || audio == NULL || cd == NULL || fp == NULL)
no_memory();
devlist.audio = devlist.cd = devlist.floppy = devlist.rmdisk =
devlist.tape = NULL;
}
/* note n will be # elments in array (and could be 0) */
static int
expandmem(int n, void **array, int size)
{
void *old = *array;
void *new;
/* get new array space (n + DELTA) */
new = (void *)calloc(n + DELTA, size);
if (new == NULL) {
perror("memory allocation failed");
exit(1);
}
/* copy old array into new space */
bcopy(old, new, n * size);
/* now release old arrary */
free(old);
*array = new;
return (n + DELTA);
}
static void
no_memory(void)
{
(void) fprintf(stderr, "%s: %s\n", "mkdevalloc",
gettext("out of memory"));
exit(1);
/* NOT REACHED */
}