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