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