xref: /titanic_41/usr/src/cmd/allocate/mkdevalloc.c (revision 7010c12ad3ac2cada55cf126121a8c46957d3632)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * scan /dev directory for mountable objects and construct device_allocate
31  * file for allocate....
32  *
33  * devices are:
34  *	tape (cartridge)
35  *		/dev/rst*
36  *		/dev/nrst*
37  *		/dev/rmt/...
38  *	audio
39  *		/dev/audio
40  *		/dev/audioctl
41  *		/dev/sound/...
42  *	floppy
43  *		/dev/diskette
44  *		/dev/fd*
45  *		/dev/rdiskette
46  *		/dev/rfd*
47  *	CD
48  *		/dev/sr*
49  *		/dev/nsr*
50  *		/dev/dsk/c?t?d0s?
51  *		/dev/rdsk/c?t?d0s?
52  *
53  */
54 
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <sys/types.h>	/* for stat(2), etc. */
58 #include <sys/stat.h>
59 #include <dirent.h>	/* for readdir(3), etc. */
60 #include <unistd.h>	/* for readlink(2) */
61 #include <stropts.h>
62 #include <string.h>	/* for strcpy(3), etc. */
63 #include <strings.h>	/* for bcopy(3C), etc. */
64 #include <stdio.h>	/* for perror(3) */
65 #include <stdlib.h>	/* for atoi(3) */
66 #include <sys/dkio.h>
67 #include <locale.h>
68 #include <libintl.h>
69 #include <libdevinfo.h>
70 #include <secdb.h>
71 #include <auth_attr.h>
72 #include <auth_list.h>
73 #include <bsm/devices.h>
74 #include <bsm/devalloc.h>
75 #include <tsol/label.h>
76 
77 #ifndef TEXT_DOMAIN
78 #define	TEXT_DOMAIN	"SUNW_OST_OSCMD"
79 #endif
80 
81 #define	MKDEVALLOC	"mkdevalloc"
82 #define	MKDEVMAPS	"mkdevmaps"
83 
84 #define	DELTA	5	/* array size delta when full */
85 #define	SECLIB	"/etc/security/lib"
86 
87 /* "/dev/rst...", "/dev/nrst...", "/dev/rmt/..." */
88 struct tape {
89 	char	*name;
90 	char	*device;
91 	int	number;
92 } *tape;
93 #define	DFLT_NTAPE  10		/* size of initial array */
94 #define	SIZE_OF_RST  3		/* |rmt| */
95 #define	SIZE_OF_NRST 4		/* |nrmt| */
96 #define	SIZE_OF_TMP  4		/* |/tmp| */
97 #define	SIZE_OF_RMT  8		/* |/dev/rmt| */
98 #define	TAPE_CLEAN    SECLIB"/st_clean"
99 
100 /* "/dev/audio", "/dev/audioctl", "/dev/sound/..." */
101 struct audio {
102 	char	*name;
103 	char	*device;
104 	int	number;
105 } *audio;
106 #define	DFLT_NAUDIO   10	/* size of initial array */
107 #define	SIZE_OF_SOUND 10	/* |/dev/sound| */
108 #define	AUDIO_CLEAN   SECLIB"/audio_clean"
109 
110 /* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */
111 struct cd {
112 	char	*name;
113 	char	*device;
114 	int	id;
115 	int	controller;
116 	int	number;
117 } *cd;
118 #define	DFLT_NCD    10		/* size of initial array */
119 #define	SIZE_OF_SR   2		/* |sr| */
120 #define	SIZE_OF_RSR  3		/* |rsr| */
121 #define	SIZE_OF_DSK  8		/* |/dev/dsk| */
122 #define	SIZE_OF_RDSK 9		/* |/dev/rdsk| */
123 #define	CD_CLEAN    SECLIB"/sr_clean"
124 
125 /* "/dev/sr", "/dev/nsr", "/dev/dsk/c?t?d0s?", "/dev/rdsk/c?t?d0s?" */
126 struct rmdisk {
127 	char	*name;
128 	char	*device;
129 	int	id;
130 	int	controller;
131 	int	number;
132 } *rmdisk, *rmdisk_r;
133 #define	DFLT_RMDISK	10	/* size of initial array */
134 
135 /* "/dev/fd0*", "/dev/rfd0*", "/dev/fd1*", "/dev/rfd1*" */
136 struct fp {
137 	char *name;
138 	char *device;
139 	int number;
140 } *fp;
141 #define	DFLT_NFP    10		/* size of initial array */
142 #define	SIZE_OF_FD0  3		/* |fd0| */
143 #define	SIZE_OF_RFD0 4		/* |rfd0| */
144 #define	FLOPPY_CLEAN SECLIB"/fd_clean"
145 
146 static void dotape();
147 static void doaudio();
148 static void dofloppy();
149 static int docd();
150 static void dormdisk(int);
151 static void initmem();
152 static int  expandmem(int, void **, int);
153 static void no_memory(void);
154 
155 int		system_labeled = 0;
156 int		do_devalloc = 0;
157 int		do_devmaps = 0;
158 int		do_files = 0;
159 devlist_t	devlist;
160 
161 int
162 main(int argc, char **argv)
163 {
164 	int		cd_count = 0;
165 	char		*progname;
166 	struct stat	tx_stat;
167 
168 	(void) setlocale(LC_ALL, "");
169 	(void) textdomain(TEXT_DOMAIN);
170 
171 	if ((progname = strrchr(argv[0], '/')) == NULL)
172 		progname = argv[0];
173 	else
174 		progname++;
175 	if (strcmp(progname, MKDEVALLOC) == 0)
176 		do_devalloc = 1;
177 	else if (strcmp(progname, MKDEVMAPS) == 0)
178 		do_devmaps = 1;
179 	else
180 		exit(1);
181 
182 	system_labeled = is_system_labeled();
183 
184 	/* test hook: see also devfsadm.c and allocate.c */
185 	if (!system_labeled) {
186 		system_labeled = is_system_labeled_debug(&tx_stat);
187 		if (system_labeled) {
188 			fprintf(stderr, "/ALLOCATE_FORCE_LABEL is set,\n"
189 			    "forcing system label on for testing...\n");
190 		}
191 	}
192 
193 	if (system_labeled == 0) {
194 		/*
195 		 * is_system_labeled() will return false in case we are
196 		 * starting before the first reboot after Trusted Extensions
197 		 * is installed. we check for a well known TX binary to
198 		 * to see if TX is installed.
199 		 */
200 		if (stat(DA_LABEL_CHECK, &tx_stat) == 0)
201 			system_labeled = 1;
202 	}
203 
204 	if (system_labeled && do_devalloc && (argc == 2) &&
205 	    (strcmp(argv[1], DA_IS_LABELED) == 0)) {
206 		/*
207 		 * write device entries to device_allocate and device_maps.
208 		 * default is to print them on stdout.
209 		 */
210 		do_files = 1;
211 	}
212 
213 	initmem();		/* initialize memory */
214 	dotape();
215 	doaudio();
216 	dofloppy();
217 	cd_count = docd();
218 	if (system_labeled)
219 		dormdisk(cd_count);
220 
221 	return (0);
222 }
223 
224 static void
225 dotape()
226 {
227 	DIR *dirp;
228 	struct dirent *dep;	/* directory entry pointer */
229 	int	i, j;
230 	char	*nm;		/* name/device of special device */
231 	char	linkvalue[2048];	/* symlink value */
232 	struct stat stat;	/* determine if it's a symlink */
233 	int	sz;		/* size of symlink value */
234 	char	*cp;		/* pointer into string */
235 	int	ntape;		/* max array size */
236 	int	tape_count;
237 	int	first = 0;
238 	char	*dname, *dtype, *dclean;
239 	da_args	dargs;
240 	deventry_t *entry;
241 
242 	ntape = DFLT_NTAPE;
243 
244 	/*
245 	 * look for rst* and nrst*
246 	 */
247 
248 	if ((dirp = opendir("/dev")) == NULL) {
249 		perror(gettext("open /dev failure"));
250 		exit(1);
251 	}
252 
253 	i = 0;
254 	while (dep = readdir(dirp)) {
255 		/* ignore if neither rst* nor nrst* */
256 		if (strncmp(dep->d_name, "rst", SIZE_OF_RST) &&
257 		    strncmp(dep->d_name, "nrst", SIZE_OF_NRST))
258 			continue;
259 
260 		/* if array full, then expand it */
261 		if (i == ntape) {
262 			/* will exit(1) if insufficient memory */
263 			ntape = expandmem(i, (void **)&tape,
264 					sizeof (struct tape));
265 		}
266 
267 		/* save name (/dev + / + d_name + \0) */
268 		nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
269 		if (nm == NULL)
270 			no_memory();
271 		(void) strcpy(nm, "/dev/");
272 		(void) strcat(nm, dep->d_name);
273 		tape[i].name = nm;
274 
275 		/* ignore if not symbolic link (note i not incremented) */
276 		if (lstat(tape[i].name, &stat) < 0) {
277 			perror("stat(2) failed ");
278 			exit(1);
279 		}
280 		if ((stat.st_mode & S_IFMT) != S_IFLNK)
281 			continue;
282 
283 		/* get name from symbolic link */
284 		if ((sz = readlink(tape[i].name, linkvalue,
285 				sizeof (linkvalue))) < 0)
286 			continue;
287 		nm = (char *)malloc(sz + 1);
288 		if (nm == NULL)
289 			no_memory();
290 		(void) strncpy(nm, linkvalue, sz);
291 		nm[sz] = '\0';
292 		tape[i].device = nm;
293 
294 		/* get device number */
295 		cp = strrchr(tape[i].device, '/');
296 		cp++;				/* advance to device # */
297 		(void) sscanf(cp, "%d", &tape[i].number);
298 
299 		i++;
300 	}
301 
302 	(void) closedir(dirp);
303 
304 	/*
305 	 * scan /dev/rmt and add entry to table
306 	 */
307 
308 	if ((dirp = opendir("/dev/rmt")) == NULL) {
309 		perror(gettext("open /dev failure"));
310 		exit(1);
311 	}
312 
313 	while (dep = readdir(dirp)) {
314 		/* skip . .. etc... */
315 		if (strncmp(dep->d_name, ".", 1) == NULL)
316 			continue;
317 
318 		/* if array full, then expand it */
319 		if (i == ntape) {
320 			/* will exit(1) if insufficient memory */
321 			ntape = expandmem(i, (void **)&tape,
322 					sizeof (struct tape));
323 		}
324 
325 		/* save name (/dev/rmt + / + d_name + \0) */
326 		nm = (char *)malloc(SIZE_OF_RMT + 1 + strlen(dep->d_name) + 1);
327 		if (nm == NULL)
328 			no_memory();
329 		(void) strcpy(nm, "/dev/rmt/");
330 		(void) strcat(nm, dep->d_name);
331 		tape[i].name = nm;
332 
333 		/* save device name (rmt/ + d_name + \0) */
334 		nm = (char *)malloc(SIZE_OF_TMP + strlen(dep->d_name) + 1);
335 		if (nm == NULL)
336 			no_memory();
337 		(void) strcpy(nm, "rmt/");
338 		(void) strcat(nm, dep->d_name);
339 		tape[i].device = nm;
340 
341 		(void) sscanf(dep->d_name, "%d", &tape[i].number);
342 
343 		i++;
344 	}
345 	tape_count = i;
346 
347 	(void) closedir(dirp);
348 
349 	/* remove duplicate entries */
350 	for (i = 0; i < tape_count - 1; i++) {
351 		for (j = i + 1; j < tape_count; j++) {
352 			if (strcmp(tape[i].device, tape[j].device))
353 				continue;
354 			tape[j].number = -1;
355 		}
356 	}
357 
358 	if (system_labeled) {
359 		dname = DA_TAPE_NAME;
360 		dtype = DA_TAPE_TYPE;
361 		dclean = DA_DEFAULT_TAPE_CLEAN;
362 	} else {
363 		dname = "st";
364 		dtype = "st";
365 		dclean = TAPE_CLEAN;
366 	}
367 	for (i = 0; i < 8; i++) {
368 		for (j = 0; j < tape_count; j++) {
369 			if (tape[j].number != i)
370 				continue;
371 			if (do_files) {
372 				(void) da_add_list(&devlist, tape[j].name, i,
373 				    DA_TAPE);
374 			} else if (do_devalloc) {
375 				/* print device_allocate for tape devices */
376 				if (system_labeled) {
377 					(void) printf("%s%d%s\\\n",
378 					    dname, i, KV_DELIMITER);
379 					(void) printf("\t%s%s\\\n",
380 					    DA_TAPE_TYPE, KV_DELIMITER);
381 					(void) printf("\t%s%s\\\n",
382 					    DA_RESERVED, KV_DELIMITER);
383 					(void) printf("\t%s%s\\\n",
384 					    DA_RESERVED, KV_DELIMITER);
385 					(void) printf("\t%s%s\\\n",
386 					    DEFAULT_DEV_ALLOC_AUTH,
387 					    KV_DELIMITER);
388 					(void) printf("\t%s\n\n", dclean);
389 				} else {
390 					(void) printf(
391 					    "st%d;st;reserved;reserved;%s;",
392 					    i, DEFAULT_DEV_ALLOC_AUTH);
393 					(void) printf("%s%s\n", SECLIB,
394 					    "/st_clean");
395 				}
396 				break;
397 			} else if (do_devmaps) {
398 				/* print device_maps for tape devices */
399 				if (first) {
400 					(void) printf(" ");
401 				} else {
402 					if (system_labeled) {
403 						(void) printf("%s%d%s\\\n",
404 						    dname, i, KV_TOKEN_DELIMIT);
405 						(void) printf("\t%s%s\\\n",
406 						    dtype, KV_TOKEN_DELIMIT);
407 						(void) printf("\t");
408 					} else {
409 						(void) printf("st%d:\\\n", i);
410 						(void) printf("\trmt:\\\n");
411 						(void) printf("\t");
412 					}
413 						first++;
414 				}
415 				(void) printf("%s", tape[j].name);
416 			}
417 		}
418 		if (do_devmaps && first) {
419 			(void) printf("\n\n");
420 			first = 0;
421 		}
422 	}
423 	if (do_files && tape_count) {
424 		dargs.rootdir = NULL;
425 		dargs.devnames = NULL;
426 		dargs.optflag = DA_ADD;
427 		for (entry = devlist.tape; entry != NULL; entry = entry->next) {
428 			dargs.devinfo = &(entry->devinfo);
429 			(void) da_update_device(&dargs);
430 		}
431 	}
432 }
433 
434 static void
435 doaudio()
436 {
437 	DIR *dirp;
438 	struct dirent *dep;	/* directory entry pointer */
439 	int	i, j;
440 	char	*nm;		/* name/device of special device */
441 	char	linkvalue[2048];	/* symlink value */
442 	struct stat stat;	/* determine if it's a symlink */
443 	int	sz;		/* size of symlink value */
444 	char	*cp;		/* pointer into string */
445 	int	naudio;		/* max array size */
446 	int	audio_count = 0;
447 	int	len, slen;
448 	int	first = 0;
449 	char	dname[128];
450 	char	*dclean;
451 	da_args	dargs;
452 	deventry_t *entry;
453 
454 	naudio = DFLT_NAUDIO;
455 
456 	if ((dirp = opendir("/dev")) == NULL) {
457 		perror(gettext("open /dev failure"));
458 		exit(1);
459 	}
460 
461 	i = 0;
462 	while (dep = readdir(dirp)) {
463 		if (strcmp(dep->d_name, "audio") &&
464 		    strcmp(dep->d_name, "audioctl"))
465 			continue;
466 
467 		/* if array full, then expand it */
468 		if (i == naudio) {
469 			/* will exit(1) if insufficient memory */
470 			naudio = expandmem(i, (void **)&audio,
471 					sizeof (struct audio));
472 		}
473 
474 		/* save name (/dev + 1 + d_name + \0) */
475 		nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
476 		if (nm == NULL)
477 			no_memory();
478 		(void) strcpy(nm, "/dev/");
479 		(void) strcat(nm, dep->d_name);
480 		audio[i].name = nm;
481 
482 		/* ignore if not symbolic link (note i not incremented) */
483 		if (lstat(audio[i].name, &stat) < 0) {
484 			perror(gettext("stat(2) failed "));
485 			exit(1);
486 		}
487 		if ((stat.st_mode & S_IFMT) != S_IFLNK)
488 			continue;
489 
490 		/* get name from symbolic link */
491 		if ((sz = readlink(audio[i].name, linkvalue,
492 				sizeof (linkvalue))) < 0)
493 			continue;
494 		nm = (char *)malloc(sz + 1);
495 		if (nm == NULL)
496 			no_memory();
497 		(void) strncpy(nm, linkvalue, sz);
498 		nm[sz] = '\0';
499 		audio[i].device = nm;
500 
501 		cp = strrchr(audio[i].device, '/');
502 		cp++;				/* advance to device # */
503 		(void) sscanf(cp, "%d", &audio[i].number);
504 
505 		i++;
506 	}
507 
508 	(void) closedir(dirp);
509 
510 	if ((dirp = opendir("/dev/sound")) == NULL) {
511 		goto skip;
512 	}
513 
514 	while (dep = readdir(dirp)) {
515 		/* skip . .. etc... */
516 		if (strncmp(dep->d_name, ".", 1) == NULL)
517 			continue;
518 
519 		/* if array full, then expand it */
520 		if (i == naudio) {
521 			/* will exit(1) if insufficient memory */
522 			naudio = expandmem(i, (void **)&audio,
523 					sizeof (struct audio));
524 		}
525 
526 		/* save name (/dev/sound + / + d_name + \0) */
527 		nm = (char *)malloc(SIZE_OF_SOUND + 1 +
528 		    strlen(dep->d_name) + 1);
529 		if (nm == NULL)
530 			no_memory();
531 		(void) strcpy(nm, "/dev/sound/");
532 		(void) strcat(nm, dep->d_name);
533 		audio[i].name = nm;
534 
535 		nm = (char *)malloc(SIZE_OF_SOUND + 1 +
536 		    strlen(dep->d_name) + 1);
537 		if (nm == NULL)
538 			no_memory();
539 		(void) strcpy(nm, "/dev/sound/");
540 		(void) strcat(nm, dep->d_name);
541 		audio[i].device = nm;
542 
543 		(void) sscanf(dep->d_name, "%d", &audio[i].number);
544 
545 		i++;
546 	}
547 
548 	(void) closedir(dirp);
549 
550 skip:
551 	audio_count = i;
552 
553 	/* remove duplicate entries */
554 	for (i = 0; i < audio_count - 1; i++) {
555 		for (j = i + 1; j < audio_count; j++) {
556 			if (strcmp(audio[i].device, audio[j].device))
557 				continue;
558 			audio[j].number = -1;
559 		}
560 	}
561 
562 	/* print out device_allocate entries for audio devices */
563 	(void) strcpy(dname, DA_AUDIO_NAME);
564 	slen = strlen(DA_AUDIO_NAME);
565 	len = sizeof (dname) - slen;
566 	dclean = system_labeled ? DA_DEFAULT_AUDIO_CLEAN : AUDIO_CLEAN;
567 	for (i = 0; i < 8; i++) {
568 		for (j = 0; j < audio_count; j++) {
569 			if (audio[j].number != i)
570 				continue;
571 			if (system_labeled)
572 				(void) snprintf(dname+slen, len, "%d", i);
573 			if (do_files) {
574 				(void) da_add_list(&devlist, audio[j].name,
575 				    i, DA_AUDIO);
576 			} else if (do_devalloc) {
577 				/* print device_allocate for audio devices */
578 				if (system_labeled) {
579 					(void) printf("%s%s\\\n",
580 					    dname, KV_DELIMITER);
581 					(void) printf("\t%s%s\\\n",
582 					    DA_AUDIO_TYPE, KV_DELIMITER);
583 					(void) printf("\t%s%s\\\n",
584 					    DA_RESERVED, KV_DELIMITER);
585 					(void) printf("\t%s%s\\\n",
586 					    DA_RESERVED, KV_DELIMITER);
587 					(void) printf("\t%s%s\\\n",
588 					    DEFAULT_DEV_ALLOC_AUTH,
589 					    KV_DELIMITER);
590 					(void) printf("\t%s\n\n", dclean);
591 				} else {
592 					(void) printf("audio;audio;");
593 					(void) printf("reserved;reserved;%s;",
594 					    DEFAULT_DEV_ALLOC_AUTH);
595 					(void) printf("%s%s\n", SECLIB,
596 					    "/audio_clean");
597 				}
598 				break;
599 			} else if (do_devmaps) {
600 				/* print device_maps for audio devices */
601 				if (first) {
602 					(void) printf(" ");
603 				} else {
604 					if (system_labeled) {
605 						(void) printf("%s%s\\\n",
606 						    dname, KV_TOKEN_DELIMIT);
607 						(void) printf("\t%s%s\\\n",
608 						    DA_AUDIO_TYPE,
609 						    KV_TOKEN_DELIMIT);
610 						(void) printf("\t");
611 					} else {
612 						(void) printf("audio:\\\n");
613 						(void) printf("\taudio:\\\n");
614 						(void) printf("\t");
615 					}
616 					first++;
617 				}
618 				(void) printf("%s", audio[j].name);
619 			}
620 		}
621 		if (do_devmaps && first) {
622 			(void) printf("\n\n");
623 			first = 0;
624 		}
625 	}
626 	if (do_files && audio_count) {
627 		dargs.rootdir = NULL;
628 		dargs.devnames = NULL;
629 		dargs.optflag = DA_ADD;
630 		for (entry = devlist.audio; entry != NULL;
631 		    entry = entry->next) {
632 			dargs.devinfo = &(entry->devinfo);
633 			(void) da_update_device(&dargs);
634 		}
635 	}
636 }
637 
638 static void
639 dofloppy()
640 {
641 	DIR *dirp;
642 	struct dirent *dep;	/* directory entry pointer */
643 	int i, j;
644 	char *nm;		/* name/device of special device */
645 	char linkvalue[2048];	/* symlink value */
646 	struct stat stat;	/* determine if it's a symlink */
647 	int sz;			/* size of symlink value */
648 	char *cp;		/* pointer into string */
649 	int nfp;		/* max array size */
650 	int floppy_count = 0;
651 	int first = 0;
652 	char *dname, *dclean;
653 	da_args dargs;
654 	deventry_t *entry;
655 
656 	nfp = DFLT_NFP;
657 
658 	/*
659 	 * look for fd* and rfd*
660 	 */
661 
662 	if ((dirp = opendir("/dev")) == NULL) {
663 		perror(gettext("open /dev failure"));
664 		exit(1);
665 	}
666 
667 	i = 0;
668 	while (dep = readdir(dirp)) {
669 		/* ignore if neither rst* nor nrst* */
670 		if (strncmp(dep->d_name, "fd0", SIZE_OF_FD0) &&
671 		    strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0) &&
672 		    strncmp(dep->d_name, "fd1", SIZE_OF_FD0) &&
673 		    strncmp(dep->d_name, "rfd0", SIZE_OF_RFD0))
674 			continue;
675 
676 		/* if array full, then expand it */
677 		if (i == nfp) {
678 			/* will exit(1) if insufficient memory */
679 			nfp = expandmem(i, (void **)&fp, sizeof (struct fp));
680 		}
681 
682 		/* save name (/dev + 1 + d_name + \0) */
683 		nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
684 		if (nm == NULL)
685 			no_memory();
686 		(void) strcpy(nm, "/dev/");
687 		(void) strcat(nm, dep->d_name);
688 		fp[i].name = nm;
689 
690 		/* ignore if not symbolic link (note i not incremented) */
691 		if (lstat(fp[i].name, &stat) < 0) {
692 			perror(gettext("stat(2) failed "));
693 			exit(1);
694 		}
695 		if ((stat.st_mode&S_IFMT) != S_IFLNK)
696 			continue;
697 
698 		/* get name from symbolic link */
699 		if ((sz = readlink(fp[i].name, linkvalue,
700 		    sizeof (linkvalue))) < 0)
701 			continue;
702 		nm = (char *)malloc(sz+1);
703 		if (nm == NULL)
704 			no_memory();
705 		(void) strncpy(nm, linkvalue, sz);
706 		nm[sz] = '\0';
707 		fp[i].device = nm;
708 
709 		/* get device number */
710 		cp = strchr(fp[i].name, 'd');
711 		cp++;				/* advance to device # */
712 		cp = strchr(cp, 'd');
713 		cp++;				/* advance to device # */
714 		(void) sscanf(cp, "%d", &fp[i].number);
715 
716 		i++;
717 	}
718 
719 	(void) closedir(dirp);
720 
721 	floppy_count = i;
722 
723 	/* print out device_allocate entries for floppy devices */
724 	if (system_labeled) {
725 		dname = DA_FLOPPY_NAME;
726 		dclean = DA_DEFAULT_DISK_CLEAN;
727 	} else {
728 		dname = "fd";
729 		dclean = FLOPPY_CLEAN;
730 	}
731 	for (i = 0; i < 8; i++) {
732 		for (j = 0; j < floppy_count; j++) {
733 			if (fp[j].number != i)
734 				continue;
735 			if (do_files) {
736 				(void) da_add_list(&devlist, fp[j].name, i,
737 				    DA_FLOPPY);
738 			} else if (do_devalloc) {
739 				/* print device_allocate for floppy devices */
740 				if (system_labeled) {
741 					(void) printf("%s%d%s\\\n",
742 					    dname, i, KV_DELIMITER);
743 					(void) printf("\t%s%s\\\n",
744 					    DA_FLOPPY_TYPE, KV_DELIMITER);
745 					(void) printf("\t%s%s\\\n",
746 					    DA_RESERVED, KV_DELIMITER);
747 					(void) printf("\t%s%s\\\n",
748 					    DA_RESERVED, KV_DELIMITER);
749 					(void) printf("\t%s%s\\\n",
750 					    DEFAULT_DEV_ALLOC_AUTH,
751 					    KV_DELIMITER);
752 					(void) printf("\t%s\n\n", dclean);
753 				} else {
754 					(void) printf(
755 					    "fd%d;fd;reserved;reserved;%s;",
756 					    i, DEFAULT_DEV_ALLOC_AUTH);
757 					(void) printf("%s%s\n", SECLIB,
758 					    "/fd_clean");
759 				}
760 				break;
761 			} else if (do_devmaps) {
762 				/* print device_maps for floppy devices */
763 				if (first) {
764 					(void) printf(" ");
765 				} else {
766 					if (system_labeled) {
767 						(void) printf("%s%d%s\\\n",
768 						    dname, i, KV_TOKEN_DELIMIT);
769 						(void) printf("\t%s%s\\\n",
770 						    DA_FLOPPY_TYPE,
771 						    KV_TOKEN_DELIMIT);
772 						(void) printf("\t");
773 					} else {
774 						(void) printf("fd%d:\\\n", i);
775 						(void) printf("\tfd:\\\n");
776 						(void) printf("\t");
777 					}
778 					if (i == 0) {
779 						(void) printf("/dev/diskette ");
780 						(void) printf(
781 						    "/dev/rdiskette ");
782 					}
783 					first++;
784 				}
785 				(void) printf("%s", fp[j].name);
786 			}
787 		}
788 		if (do_devmaps && first) {
789 			(void) printf("\n\n");
790 			first = 0;
791 		}
792 	}
793 	if (do_files && floppy_count) {
794 		dargs.rootdir = NULL;
795 		dargs.devnames = NULL;
796 		dargs.optflag = DA_ADD;
797 		for (entry = devlist.floppy; entry != NULL;
798 		    entry = entry->next) {
799 			dargs.devinfo = &(entry->devinfo);
800 			(void) da_update_device(&dargs);
801 		}
802 	}
803 }
804 
805 static int
806 docd()
807 {
808 	DIR *dirp;
809 	struct dirent *dep;	/* directory entry pointer */
810 	int	i, j;
811 	char	*nm;		/* name/device of special device */
812 	char	linkvalue[2048];	/* symlink value */
813 	struct stat stat;	/* determine if it's a symlink */
814 	int	sz;		/* size of symlink value */
815 	char	*cp;		/* pointer into string */
816 	int	id;		/* disk id */
817 	int	ctrl;		/* disk controller */
818 	int	ncd;		/* max array size */
819 	int	cd_count = 0;
820 	int	first = 0;
821 	char	*dname, *dclean;
822 	da_args	dargs;
823 	deventry_t *entry;
824 
825 	ncd = DFLT_NCD;
826 
827 	/*
828 	 * look for sr* and rsr*
829 	 */
830 
831 	if ((dirp = opendir("/dev")) == NULL) {
832 		perror(gettext("open /dev failure"));
833 		exit(1);
834 	}
835 
836 	i = 0;
837 	while (dep = readdir(dirp)) {
838 		/* ignore if neither sr* nor rsr* */
839 		if (strncmp(dep->d_name, "sr", SIZE_OF_SR) &&
840 		    strncmp(dep->d_name, "rsr", SIZE_OF_RSR))
841 			continue;
842 
843 		/* if array full, then expand it */
844 		if (i == ncd) {
845 			/* will exit(1) if insufficient memory */
846 			ncd = expandmem(i, (void **)&cd, sizeof (struct cd));
847 		}
848 
849 		/* save name (/dev + / + d_name + \0) */
850 		nm = (char *)malloc(SIZE_OF_TMP + 1 + strlen(dep->d_name) + 1);
851 		if (nm == NULL)
852 			no_memory();
853 		(void) strcpy(nm, "/dev/");
854 		(void) strcat(nm, dep->d_name);
855 		cd[i].name = nm;
856 
857 		/* save id # */
858 		if (dep->d_name[0] == 'r')
859 			(void) sscanf(dep->d_name, "rsr%d", &cd[i].id);
860 		else
861 			(void) sscanf(dep->d_name, "sr%d", &cd[i].id);
862 
863 		/* ignore if not symbolic link (note i not incremented) */
864 		if (lstat(cd[i].name, &stat) < 0) {
865 			perror(gettext("stat(2) failed "));
866 			exit(1);
867 		}
868 		if ((stat.st_mode & S_IFMT) != S_IFLNK)
869 			continue;
870 
871 		/* get name from symbolic link */
872 		if ((sz = readlink(cd[i].name, linkvalue, sizeof (linkvalue))) <
873 		    0)
874 			continue;
875 
876 		nm = (char *)malloc(sz + 1);
877 		if (nm == NULL)
878 			no_memory();
879 		(void) strncpy(nm, linkvalue, sz);
880 		nm[sz] = '\0';
881 		cd[i].device = nm;
882 
883 		cp = strrchr(cd[i].device, '/');
884 		cp++;				/* advance to device # */
885 		(void) sscanf(cp, "c%dt%d", &cd[i].controller, &cd[i].number);
886 
887 		i++;
888 	}
889 	cd_count = i;
890 
891 	(void) closedir(dirp);
892 
893 	/*
894 	 * scan /dev/dsk for cd devices
895 	 */
896 
897 	if ((dirp = opendir("/dev/dsk")) == NULL) {
898 		perror("gettext(open /dev/dsk failure)");
899 		exit(1);
900 	}
901 
902 	while (dep = readdir(dirp)) {
903 		/* skip . .. etc... */
904 		if (strncmp(dep->d_name, ".", 1) == NULL)
905 			continue;
906 
907 		/* get device # (disk #) */
908 		if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
909 			continue;
910 
911 		/* see if this is one of the cd special devices */
912 		for (j = 0; j < cd_count; j++) {
913 			if (cd[j].number == id && cd[j].controller == ctrl)
914 				goto found;
915 		}
916 		continue;
917 
918 		/* add new entry to table (/dev/dsk + / + d_name + \0) */
919 found:
920 		/* if array full, then expand it */
921 		if (i == ncd) {
922 			/* will exit(1) if insufficient memory */
923 			ncd = expandmem(i, (void **)&cd, sizeof (struct cd));
924 		}
925 
926 		nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1);
927 		if (nm == NULL)
928 			no_memory();
929 		(void) strcpy(nm, "/dev/dsk/");
930 		(void) strcat(nm, dep->d_name);
931 		cd[i].name = nm;
932 
933 		cd[i].id = cd[j].id;
934 
935 		cd[i].device = "";
936 
937 		cd[i].number = id;
938 
939 		i++;
940 	}
941 
942 	(void) closedir(dirp);
943 
944 	/*
945 	 * scan /dev/rdsk for cd devices
946 	 */
947 
948 	if ((dirp = opendir("/dev/rdsk")) == NULL) {
949 		perror(gettext("open /dev/dsk failure"));
950 		exit(1);
951 	}
952 
953 	while (dep = readdir(dirp)) {
954 		/* skip . .. etc... */
955 		if (strncmp(dep->d_name, ".", 1) == NULL)
956 			continue;
957 
958 		/* get device # (disk #) */
959 		if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) != 2)
960 			continue;
961 
962 		/* see if this is one of the cd special devices */
963 		for (j = 0; j < cd_count; j++) {
964 			if (cd[j].number == id && cd[j].controller == ctrl)
965 				goto found1;
966 		}
967 		continue;
968 
969 		/* add new entry to table (/dev/rdsk + / + d_name + \0) */
970 found1:
971 		/* if array full, then expand it */
972 		if (i == ncd) {
973 			/* will exit(1) if insufficient memory */
974 			ncd = expandmem(i, (void **)&cd, sizeof (struct cd));
975 		}
976 
977 		nm = (char *)malloc(SIZE_OF_RDSK + 1 + strlen(dep->d_name) + 1);
978 		if (nm == NULL)
979 			no_memory();
980 		(void) strcpy(nm, "/dev/rdsk/");
981 		(void) strcat(nm, dep->d_name);
982 		cd[i].name = nm;
983 
984 		cd[i].id = cd[j].id;
985 
986 		cd[i].device = "";
987 
988 		cd[i].number = id;
989 
990 		cd[i].controller = ctrl;
991 
992 		i++;
993 	}
994 
995 	(void) closedir(dirp);
996 
997 	cd_count = i;
998 
999 	if (system_labeled) {
1000 		dname = DA_CD_NAME;
1001 		dclean = DA_DEFAULT_DISK_CLEAN;
1002 	} else {
1003 		dname = "sr";
1004 		dclean = CD_CLEAN;
1005 	}
1006 	for (i = 0; i < 8; i++) {
1007 		for (j = 0; j < cd_count; j++) {
1008 			if (cd[j].id != i)
1009 				continue;
1010 			if (do_files) {
1011 				(void) da_add_list(&devlist, cd[j].name, i,
1012 				    DA_CD);
1013 			} else if (do_devalloc) {
1014 				/* print device_allocate for cd devices */
1015 				if (system_labeled) {
1016 					(void) printf("%s%d%s\\\n",
1017 					    dname, i, KV_DELIMITER);
1018 					(void) printf("\t%s%s\\\n",
1019 					    DA_CD_TYPE, KV_DELIMITER);
1020 					(void) printf("\t%s%s\\\n",
1021 					    DA_RESERVED, KV_DELIMITER);
1022 					(void) printf("\t%s%s\\\n",
1023 					    DA_RESERVED, KV_DELIMITER);
1024 					(void) printf("\t%s%s\\\n",
1025 					    DEFAULT_DEV_ALLOC_AUTH,
1026 					    KV_DELIMITER);
1027 					(void) printf("\t%s\n\n", dclean);
1028 				} else {
1029 					(void) printf(
1030 					    "sr%d;sr;reserved;reserved;%s;",
1031 					    i, DEFAULT_DEV_ALLOC_AUTH);
1032 					(void) printf("%s%s\n", SECLIB,
1033 					    "/sr_clean");
1034 				}
1035 				break;
1036 			} else if (do_devmaps) {
1037 				/* print device_maps for cd devices */
1038 				if (first) {
1039 					(void) printf(" ");
1040 				} else {
1041 					if (system_labeled) {
1042 						(void) printf("%s%d%s\\\n",
1043 						    dname, i, KV_TOKEN_DELIMIT);
1044 						(void) printf("\t%s%s\\\n",
1045 						    DA_CD_TYPE,
1046 						    KV_TOKEN_DELIMIT);
1047 						(void) printf("\t");
1048 					} else {
1049 						(void) printf("sr%d:\\\n", i);
1050 						(void) printf("\tsr:\\\n");
1051 						(void) printf("\t");
1052 					}
1053 					first++;
1054 				}
1055 				(void) printf("%s", cd[j].name);
1056 			}
1057 		}
1058 		if (do_devmaps && first) {
1059 			(void) printf("\n\n");
1060 			first = 0;
1061 		}
1062 	}
1063 	if (do_files && cd_count) {
1064 		dargs.rootdir = NULL;
1065 		dargs.devnames = NULL;
1066 		dargs.optflag = DA_ADD;
1067 		for (entry = devlist.cd; entry != NULL; entry = entry->next) {
1068 			dargs.devinfo = &(entry->devinfo);
1069 			(void) da_update_device(&dargs);
1070 		}
1071 	}
1072 
1073 	return (cd_count);
1074 }
1075 
1076 static void
1077 dormdisk(int cd_count)
1078 {
1079 	DIR *dirp;
1080 	struct dirent *dep;	/* directory entry pointer */
1081 	int	i, j;
1082 	char	*nm;		/* name/device of special device */
1083 	int	id;		/* disk id */
1084 	int	ctrl;		/* disk controller */
1085 	int	nrmdisk;	/* max array size */
1086 	int	fd = -1;
1087 	int	rmdisk_count;
1088 	int	first = 0;
1089 	int	is_cd;
1090 	int	checked;
1091 	int	removable;
1092 	char	path[MAXPATHLEN];
1093 	da_args	dargs;
1094 	deventry_t *entry;
1095 
1096 	nrmdisk = DFLT_RMDISK;
1097 	i = rmdisk_count = 0;
1098 
1099 	/*
1100 	 * scan /dev/dsk for rmdisk devices
1101 	 */
1102 	if ((dirp = opendir("/dev/dsk")) == NULL) {
1103 		perror("gettext(open /dev/dsk failure)");
1104 		exit(1);
1105 	}
1106 
1107 	while (dep = readdir(dirp)) {
1108 		is_cd = 0;
1109 		checked = 0;
1110 		removable = 0;
1111 		/* skip . .. etc... */
1112 		if (strncmp(dep->d_name, ".", 1) == NULL)
1113 			continue;
1114 
1115 		/* get device # (disk #) */
1116 		if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
1117 			continue;
1118 
1119 		/* see if we've already examined this device */
1120 		for (j = 0; j < i; j++) {
1121 			if (id == rmdisk[j].id &&
1122 			    ctrl == rmdisk[j].controller &&
1123 			    (strcmp(dep->d_name, rmdisk[j].name) == 0)) {
1124 				checked = 1;
1125 				break;
1126 			}
1127 			if (id == rmdisk[j].id && ctrl != rmdisk[j].controller)
1128 				/*
1129 				 * c2t0d0s0 is a different rmdisk than c3t0d0s0.
1130 				 */
1131 				id = rmdisk[j].id + 1;
1132 		}
1133 		if (checked)
1134 			continue;
1135 
1136 		/* ignore if this is a cd */
1137 		for (j = 0; j < cd_count; j++) {
1138 			if (id == cd[j].number && ctrl == cd[j].controller) {
1139 				is_cd = 1;
1140 				break;
1141 			}
1142 		}
1143 		if (is_cd)
1144 			continue;
1145 
1146 		/* see if device is removable */
1147 		(void) snprintf(path, sizeof (path), "%s%s", "/dev/rdsk/",
1148 		    dep->d_name);
1149 		if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0)
1150 			continue;
1151 		(void) ioctl(fd, DKIOCREMOVABLE, &removable);
1152 		(void) close(fd);
1153 		if (removable == 0)
1154 			continue;
1155 
1156 		/*
1157 		 * add new entry to table (/dev/dsk + / + d_name + \0)
1158 		 * if array full, then expand it
1159 		 */
1160 		if (i == nrmdisk) {
1161 			/* will exit(1) if insufficient memory */
1162 			nrmdisk = expandmem(i, (void **)&rmdisk,
1163 			    sizeof (struct rmdisk));
1164 		}
1165 		nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1);
1166 		if (nm == NULL)
1167 			no_memory();
1168 		(void) strcpy(nm, "/dev/dsk/");
1169 		(void) strcat(nm, dep->d_name);
1170 		rmdisk[i].name = nm;
1171 		rmdisk[i].id = id;
1172 		rmdisk[i].controller = ctrl;
1173 		rmdisk[i].device = "";
1174 		rmdisk[i].number = id;
1175 		rmdisk_r[i].name = strdup(path);
1176 		i++;
1177 	}
1178 
1179 	rmdisk_count = i;
1180 	(void) closedir(dirp);
1181 
1182 	for (i = 0, j = rmdisk_count; i < rmdisk_count; i++, j++) {
1183 		if (j == nrmdisk) {
1184 			/* will exit(1) if insufficient memory */
1185 			nrmdisk = expandmem(j, (void **)&rmdisk,
1186 			    sizeof (struct rmdisk));
1187 		}
1188 		rmdisk[j].name = rmdisk_r[i].name;
1189 		rmdisk[j].id = rmdisk[i].id;
1190 		rmdisk[j].controller = rmdisk[i].controller;
1191 		rmdisk[j].device = rmdisk[i].device;
1192 		rmdisk[j].number = rmdisk[i].number;
1193 	}
1194 	rmdisk_count = j;
1195 
1196 	for (i = 0; i < 8; i++) {
1197 		for (j = 0; j < rmdisk_count; j++) {
1198 			if (rmdisk[j].id != i)
1199 				continue;
1200 			if (do_files) {
1201 				(void) da_add_list(&devlist, rmdisk[j].name, i,
1202 				    DA_RMDISK);
1203 			} else if (do_devalloc) {
1204 				/* print device_allocate for rmdisk devices */
1205 				(void) printf("%s%d%s\\\n",
1206 				    DA_RMDISK_NAME, i, KV_DELIMITER);
1207 				(void) printf("\t%s%s\\\n",
1208 				    DA_RMDISK_TYPE, KV_DELIMITER);
1209 				(void) printf("\t%s%s\\\n",
1210 				    DA_RESERVED, KV_DELIMITER);
1211 				(void) printf("\t%s%s\\\n",
1212 				    DA_RESERVED, KV_DELIMITER);
1213 				(void) printf("\t%s%s\\\n",
1214 				    DEFAULT_DEV_ALLOC_AUTH, KV_DELIMITER);
1215 				(void) printf("\t%s\n", DA_DEFAULT_DISK_CLEAN);
1216 				break;
1217 			} else if (do_devmaps) {
1218 				/* print device_maps for rmdisk devices */
1219 				if (first) {
1220 					(void) printf(" ");
1221 				} else {
1222 					(void) printf("%s%d%s\\\n",
1223 					    DA_RMDISK_NAME, i,
1224 					    KV_TOKEN_DELIMIT);
1225 					(void) printf("\t%s%s\\\n",
1226 					    DA_RMDISK_TYPE, KV_TOKEN_DELIMIT);
1227 					(void) printf("\t");
1228 					first++;
1229 				}
1230 				(void) printf("%s", rmdisk[j].name);
1231 			}
1232 		}
1233 		if (do_devmaps && first) {
1234 			(void) printf("\n\n");
1235 			first = 0;
1236 		}
1237 	}
1238 	if (do_files && rmdisk_count) {
1239 		dargs.rootdir = NULL;
1240 		dargs.devnames = NULL;
1241 		dargs.optflag = DA_ADD;
1242 		for (entry = devlist.rmdisk; entry != NULL;
1243 		    entry = entry->next) {
1244 			dargs.devinfo = &(entry->devinfo);
1245 			(void) da_update_device(&dargs);
1246 		}
1247 	}
1248 }
1249 
1250 /* set default array sizes */
1251 static void
1252 initmem()
1253 {
1254 	tape  = (struct tape *)calloc(DFLT_NTAPE, sizeof (struct tape));
1255 	audio = (struct audio *)calloc(DFLT_NAUDIO, sizeof (struct audio));
1256 	cd    = (struct cd *)calloc(DFLT_NCD, sizeof (struct cd));
1257 	fp    = (struct fp *)calloc(DFLT_NFP, sizeof (struct fp));
1258 	if (system_labeled) {
1259 		rmdisk = (struct rmdisk *)calloc(DFLT_RMDISK,
1260 		    sizeof (struct rmdisk));
1261 		if (rmdisk == NULL)
1262 			no_memory();
1263 		rmdisk_r = (struct rmdisk *)calloc(DFLT_RMDISK,
1264 		    sizeof (struct rmdisk));
1265 		if (rmdisk_r == NULL)
1266 			no_memory();
1267 	}
1268 
1269 	if (tape == NULL || audio == NULL || cd == NULL || fp == NULL)
1270 		no_memory();
1271 
1272 	devlist.audio = devlist.cd = devlist.floppy = devlist.rmdisk =
1273 	    devlist.tape = NULL;
1274 }
1275 
1276 /* note n will be # elments in array (and could be 0) */
1277 static int
1278 expandmem(int n, void **array, int size)
1279 {
1280 	void *old = *array;
1281 	void *new;
1282 
1283 	/* get new array space (n + DELTA) */
1284 	new = (void *)calloc(n + DELTA,  size);
1285 
1286 	if (new == NULL) {
1287 		perror("memory allocation failed");
1288 		exit(1);
1289 	}
1290 
1291 	/* copy old array into new space */
1292 	bcopy(old, new, n * size);
1293 
1294 	/* now release old arrary */
1295 	free(old);
1296 
1297 	*array = new;
1298 
1299 	return (n + DELTA);
1300 }
1301 
1302 static void
1303 no_memory(void)
1304 {
1305 	(void) fprintf(stderr, "%s: %s\n", "mkdevalloc",
1306 	    gettext("out of memory"));
1307 	exit(1);
1308 	/* NOT REACHED */
1309 }
1310