xref: /onnv-gate/usr/src/cmd/devmgmt/mkdtab/mkdtab.c (revision 7563:84ec90ffc3f7)
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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
26 /*	  All Rights Reserved  	*/
27 
28 #include	<stdio.h>
29 #include	<stdlib.h>
30 #include	<string.h>
31 #include	<fcntl.h>
32 #include	<sys/types.h>
33 #include	<unistd.h>
34 #include	<devmgmt.h>
35 #include	<devtab.h>
36 #include	<dirent.h>
37 #include	<libgen.h>
38 #include	<sys/stat.h>
39 #include	<sys/vtoc.h>
40 #include	<sys/vfstab.h>
41 
42 /*
43  * Update device.tab and dgroup.tab to reflect current configuration.
44  * Designed so it can be run either once at installation time or after
45  * every reboot.  The alias naming scheme used is non-intuitive but
46  * is consistent with existing conventions and documentation and with
47  * the device numbering scheme used by the disks command.
48  * Code borrowed liberally from prtconf, disks and prtvtoc commands.
49  */
50 
51 /*
52  * make this long enough to start out with.
53  * there are place we write into putdevcmd
54  * where we are not testing for overrun.
55  */
56 #define	ORIGLEN	1024
57 
58 struct dpart {
59 	char		alias[20];
60 	char		*cdevice;
61 	char		*bdevice;
62 	diskaddr_t	capacity;
63 };
64 
65 static int		vfsnum;
66 static char		*putdevcmd;
67 static char		cmd[80];
68 static int		lastlen = ORIGLEN;
69 #ifdef att3b2
70 static struct mainedt	*edtp;
71 #endif
72 static struct vfstab	*vfstab;
73 
74 static void checkandresize(int);
75 
76 static char *
memstr(const char * str)77 memstr(const char *str)
78 {
79 	char	*mem;
80 
81 	if ((mem = (char *)malloc((uint_t)strlen(str) + 1)) == NULL) {
82 		(void) fprintf(stderr,
83 		    "%s: can't update device tables:Out of memory\n", cmd);
84 		exit(1);
85 	}
86 	return (strcpy(mem, str));
87 }
88 
89 
90 
91 /*
92  * Add device table entry for the floppy drive.
93  */
94 static void
fdisk(const int diskno,const char * disknm)95 fdisk(const int diskno, const char *disknm)
96 {
97 	if (snprintf(putdevcmd, lastlen, "/usr/bin/putdev -a diskette%d "
98 	    "cdevice=/dev/r%s bdevice=/dev/%s desc=\"Floppy Drive\" "
99 	    "mountpt=/mnt volume=diskette "
100 	    "type=diskette removable=true capacity=2880 "
101 	    "fmtcmd=\"/usr/bin/fdformat -f -v /dev/r%s\" "
102 	    "erasecmd=\"/usr/sbin/fdformat -f -v /dev/r%s\" "
103 	    "removecmd=\"/usr/bin/eject\" copy=true "
104 	    "mkfscmd=\"/usr/sbin/mkfs -F ufs /dev/r%s 2880 18 "
105 	    "2 4096 512 80 2 5 3072 t\"",
106 	    diskno, disknm, disknm, disknm, disknm, disknm) >= lastlen) {
107 		(void) fprintf(stderr,
108 		    "%s: Command too long: %s\n", cmd, putdevcmd);
109 		exit(1);
110 	}
111 	(void) system(putdevcmd);
112 }
113 
114 static void
do_fdisks(void)115 do_fdisks(void)
116 {
117 	DIR *dp;
118 	struct dirent *dirp;
119 	int drive = 1;
120 
121 	if ((dp = opendir("/dev")) == NULL) {
122 		(void) fprintf(stderr, "%s: can't open /dev\n", cmd);
123 		return;
124 	}
125 
126 	while ((dirp = readdir(dp)) != NULL) {
127 		if (gmatch(dirp->d_name, "diskette*")) {
128 			fdisk(drive++, dirp->d_name);
129 		}
130 	}
131 
132 	(void) closedir(dp);
133 }
134 
135 /*
136  * hdisk() gets information about the specified hard drive from the vtoc
137  * and vfstab and adds the disk and partition entries to device.tab. If
138  * we can't access the raw disk we simply assume it isn't properly configured
139  * and we add no entries to device.tab.
140  */
141 static void
hdisk(const int drive,const char * drivepfx)142 hdisk(const int drive, const char *drivepfx)
143 {
144 	char		*cdskpath;
145 	char		*bdskpath;
146 	char		*mountpoint;
147 	int		i, j, dpartcnt, fd;
148 	struct extvtoc	vtoc;
149 	static struct dpart    *dparttab;
150 
151 	if ((cdskpath = (char *)malloc(strlen(drivepfx) + 13)) == NULL) {
152 		(void) fprintf(stderr, "%s: Memory request failed\n", cmd);
153 		exit(1);
154 	}
155 
156 	(void) snprintf(cdskpath, strlen(drivepfx) + 13, "/dev/rdsk/%ss2",
157 	    drivepfx);
158 	if ((fd = open(cdskpath, O_RDONLY)) == -1) {
159 		free(cdskpath);
160 		return;
161 	}
162 
163 
164 	/*
165 	 * Read volume table of contents.
166 	 */
167 	if (read_extvtoc(fd, &vtoc) < 0) {
168 		(void) close(fd);
169 		free(cdskpath);
170 		return;
171 	}
172 
173 	(void) close(fd);
174 
175 	/*
176 	 * Begin building the putdev command string that will be
177 	 * used to make the entry for this disk.
178 	 */
179 
180 	if ((bdskpath = (char *)malloc(strlen(drivepfx) + 13)) == NULL) {
181 		(void) fprintf(stderr, "%s: Memory request failed\n", cmd);
182 		exit(1);
183 	}
184 
185 	(void) snprintf(bdskpath, strlen(drivepfx) + 13, "/dev/dsk/%ss2",
186 	    drivepfx);
187 	if (snprintf(putdevcmd, lastlen, "/usr/bin/putdev -a disk%d "
188 	    "cdevice=%s bdevice=%s "
189 	    "desc=\"Disk Drive\" type=disk "
190 	    "part=true removable=false capacity=%llu dpartlist=",
191 	    drive, cdskpath, bdskpath, vtoc.v_part[2].p_size) >= lastlen) {
192 		(void) fprintf(stderr,
193 		    "%s: Command too long: %s\n", cmd, putdevcmd);
194 		exit(1);
195 	}
196 
197 	free(cdskpath);
198 	free(bdskpath);
199 
200 	/*
201 	 * Build a table of disk partitions we are interested in and finish
202 	 * the putdev command string for the disk by adding the dpartlist.
203 	 */
204 
205 	if ((dparttab =
206 	    (struct dpart *)malloc((int)vtoc.v_nparts *
207 	    sizeof (struct dpart))) == NULL) {
208 		(void) fprintf(stderr,
209 		    "%s: can't disk partitions table: Out of memory\n", cmd);
210 		exit(1);
211 	}
212 
213 	dpartcnt = 0;
214 	for (i = 0; i < (int)vtoc.v_nparts; ++i) {
215 		if (vtoc.v_part[i].p_size == 0 || vtoc.v_part[i].p_flag != 0)
216 			continue;
217 		(void) sprintf(dparttab[dpartcnt].alias, "dpart%d%02d", drive,
218 		    i);
219 
220 		if ((dparttab[dpartcnt].cdevice =
221 		    (char *)malloc(strlen(drivepfx) + 14)) == NULL) {
222 			(void) fprintf(stderr, "%s: Out of memory\n", cmd);
223 			exit(1);
224 		}
225 
226 		(void) snprintf(dparttab[dpartcnt].cdevice,
227 		    strlen(drivepfx) + 14, "/dev/rdsk/%ss%x", drivepfx, i);
228 		if ((dparttab[dpartcnt].bdevice =
229 		    (char *)malloc(strlen(drivepfx) + 14)) == NULL) {
230 			(void) fprintf(stderr, "%s: Out of memory\n", cmd);
231 			exit(1);
232 		}
233 		(void) snprintf(dparttab[dpartcnt].bdevice,
234 		    strlen(drivepfx) + 14, "/dev/dsk/%ss%x", drivepfx, i);
235 		dparttab[dpartcnt].capacity = vtoc.v_part[i].p_size;
236 
237 		if (dpartcnt != 0)
238 			(void) strcat(putdevcmd, ",");
239 		(void) strcat(putdevcmd, dparttab[dpartcnt].alias);
240 		dpartcnt++;
241 	}
242 
243 	(void) system(putdevcmd);
244 
245 	/*
246 	 * We assemble the rest of the information about the partitions by
247 	 * looking in the vfstab.
248 	 */
249 	for (i = 0; i < dpartcnt; i++) {
250 		for (j = 0; j < vfsnum; j++) {
251 			if (vfstab[j].vfs_special != NULL &&
252 			    strcmp(dparttab[i].bdevice,
253 			    vfstab[j].vfs_special) == 0)
254 				break;
255 		}
256 		if (j < vfsnum) {
257 			/*
258 			 * Partition found in vfstab.
259 			 */
260 			if (vfstab[j].vfs_mountp == NULL ||
261 			    strcmp(vfstab[j].vfs_mountp, "-") == 0)
262 				mountpoint = "/mnt";
263 			else
264 				mountpoint = vfstab[j].vfs_mountp;
265 			if (snprintf(putdevcmd, lastlen, "/usr/bin/putdev "
266 			    "-a %s cdevice=%s bdevice=%s "
267 			    "desc=\"Disk Partition\" type=dpart "
268 			    "removable=false capacity=%llu dparttype=fs "
269 			    "fstype=%s mountpt=%s", dparttab[i].alias,
270 			    dparttab[i].cdevice, dparttab[i].bdevice,
271 			    dparttab[i].capacity, vfstab[j].vfs_fstype,
272 			    mountpoint) >= lastlen) {
273 					(void) fprintf(stderr,
274 					    "%s: Command too long: %s\n",
275 					    cmd, putdevcmd);
276 					exit(1);
277 				}
278 				(void) system(putdevcmd);
279 		}
280 		free(dparttab[i].cdevice);
281 		free(dparttab[i].bdevice);
282 	}
283 	free(dparttab);
284 }
285 
286 static void
do_hdisks(void)287 do_hdisks(void)
288 {
289 	DIR *dp;
290 	struct dirent *dirp;
291 	int drive = 1;	char disknm[MAXNAMLEN+1];
292 
293 	if ((dp = opendir("/dev/rdsk")) == NULL) {
294 		(void) fprintf(stderr, "%s: can't open /dev/rdsk\n", cmd);
295 		return;
296 	}
297 
298 	while ((dirp = readdir(dp)) != NULL) {
299 		if (gmatch(dirp->d_name, "c[0-9]*s2")) {
300 			(void) strcpy(disknm, dirp->d_name);
301 			/*
302 			 * now know off the 's2'
303 			 */
304 			disknm[strlen(disknm)-2] = '\0';
305 			/*
306 			 * And do it!
307 			 */
308 			hdisk(drive++, disknm);
309 		}
310 	}
311 
312 	(void) closedir(dp);
313 }
314 
315 
316 /*
317  * Add device table entry for the cartridge tape drive.
318  */
319 static void
tape(const int driveno,const char * drivenm)320 tape(const int driveno, const char *drivenm)
321 {
322 	if (snprintf(putdevcmd, lastlen, "/usr/bin/putdev -a ctape%d "
323 	    "cdevice=/dev/rmt/%s "
324 	    "desc=\"Tape Drive\" volume=\"tape\" "
325 	    "type=ctape removable=true capacity=45539 bufsize=15872 "
326 	    "erasecmd=\"/usr/bin/mt -f /dev/rmt/%s erase\" "
327 	    "removecmd=\"/usr/bin/mt -f /dev/rmt/%s offline\"",
328 	    driveno, drivenm, drivenm, drivenm) >= lastlen) {
329 		(void) fprintf(stderr,
330 		    "%s: Command too long: %s\n", cmd, putdevcmd);
331 		exit(1);
332 	}
333 	(void) system(putdevcmd);
334 }
335 
336 static void
do_tapes(void)337 do_tapes(void)
338 {
339 	DIR *dp;
340 	struct dirent *dirp;
341 
342 	if ((dp = opendir("/dev/rmt")) == NULL) {
343 		(void) fprintf(stderr, "%s: can't open /dev/rmt\n", cmd);
344 		return;
345 	}
346 
347 	while ((dirp = readdir(dp)) != NULL) {
348 		if (gmatch(dirp->d_name, "[0-9]") ||
349 		    gmatch(dirp->d_name, "[1-9][0-9]")) {
350 			tape(atoi(dirp->d_name), dirp->d_name);
351 		}
352 	}
353 
354 	(void) closedir(dp);
355 }
356 
357 static void
initialize(void)358 initialize(void)
359 {
360 	FILE		*fp;
361 	int		i;
362 	struct vfstab	vfsent;
363 	char		*criteria[5];
364 	char		**olddevlist;
365 
366 	/*
367 	 * Build a copy of vfstab in memory for later use.
368 	 */
369 	if ((fp = fopen("/etc/vfstab", "r")) == NULL) {
370 		(void) fprintf(stderr,
371 		    "%s: can't update device tables:Can't open /etc/vfstab\n",
372 		    cmd);
373 		exit(1);
374 	}
375 
376 	/*
377 	 * Go through the vfstab file once to get the number of entries so
378 	 * we can allocate the right amount of contiguous memory.
379 	 */
380 	vfsnum = 0;
381 	while (getvfsent(fp, &vfsent) == 0)
382 		vfsnum++;
383 	rewind(fp);
384 
385 	if ((vfstab = (struct vfstab *)malloc(vfsnum * sizeof (struct vfstab)))
386 	    == NULL) {
387 		(void) fprintf(stderr,
388 		    "%s: can't update device tables:Out of memory\n", cmd);
389 		exit(1);
390 	}
391 
392 	/*
393 	 * Go through the vfstab file one more time to populate our copy in
394 	 * memory.  We only populate the fields we'll need.
395 	 */
396 	i = 0;
397 	while (getvfsent(fp, &vfsent) == 0 && i < vfsnum) {
398 		if (vfsent.vfs_special == NULL)
399 			vfstab[i].vfs_special = NULL;
400 		else
401 			vfstab[i].vfs_special = memstr(vfsent.vfs_special);
402 		if (vfsent.vfs_mountp == NULL)
403 			vfstab[i].vfs_mountp = NULL;
404 		else
405 			vfstab[i].vfs_mountp = memstr(vfsent.vfs_mountp);
406 		if (vfsent.vfs_fstype == NULL)
407 			vfstab[i].vfs_fstype = NULL;
408 		else
409 			vfstab[i].vfs_fstype = memstr(vfsent.vfs_fstype);
410 		i++;
411 	}
412 	(void) fclose(fp);
413 
414 	/*
415 	 * Now remove all current entries of type disk, dpart, ctape
416 	 * and diskette from the device and device group tables.
417 	 * Any changes made manually since the last time this command
418 	 * was run will be lost.  Note that after this we are committed
419 	 * to try our best to rebuild the tables (i.e. the command
420 	 * should try not to fail completely after this point).
421 	 */
422 	criteria[0] = "type=disk";
423 	criteria[1] = "type=dpart";
424 	criteria[2] = "type=ctape";
425 	criteria[3] = "type=diskette";
426 	criteria[4] = (char *)NULL;
427 	olddevlist = getdev((char **)NULL, criteria, 0);
428 	_enddevtab();	/* getdev() should do this but doesn't */
429 
430 	putdevcmd = malloc(ORIGLEN);
431 
432 	if (putdevcmd == NULL) {
433 		perror("malloc");
434 		exit(-1);
435 	}
436 
437 	(void) memset(putdevcmd, 0, ORIGLEN);
438 
439 	for (i = 0; olddevlist[i] != (char *)NULL; i++) {
440 		if (snprintf(putdevcmd, lastlen,
441 		    "/usr/bin/putdev -d %s", olddevlist[i]) >= lastlen) {
442 			(void) fprintf(stderr,
443 			    "%s: Command too long: %s\n", cmd, putdevcmd);
444 			exit(1);
445 		}
446 		(void) system(putdevcmd);
447 	}
448 
449 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp -d disk 2>/dev/null");
450 	(void) system(putdevcmd);
451 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp -d dpart 2>/dev/null");
452 	(void) system(putdevcmd);
453 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp -d ctape 2>/dev/null");
454 	(void) system(putdevcmd);
455 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp -d diskette 2>/dev/null");
456 	(void) system(putdevcmd);
457 }
458 
459 
460 /*
461  * Update the dgroup.tab file with information from the updated device.tab.
462  */
463 static void
mkdgroups(void)464 mkdgroups(void)
465 {
466 	int	i;
467 	char	*criteria[2];
468 	char	**devlist;
469 
470 	criteria[1] = (char *)NULL;
471 
472 	criteria[0] = "type=disk";
473 
474 	devlist = getdev((char **)NULL, criteria, DTAB_ANDCRITERIA);
475 
476 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp disk");
477 	for (i = 0; devlist[i] != (char *)NULL; i++) {
478 		checkandresize((strlen(putdevcmd) + strlen(devlist[i]) + 2));
479 		(void) strcat(putdevcmd, " ");
480 		(void) strcat(putdevcmd, devlist[i]);
481 	}
482 	if (i != 0)
483 		(void) system(putdevcmd);
484 
485 	criteria[0] = "type=dpart";
486 
487 	devlist = getdev((char **)NULL, criteria, DTAB_ANDCRITERIA);
488 
489 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp dpart");
490 	for (i = 0; devlist[i] != (char *)NULL; i++) {
491 		checkandresize((strlen(putdevcmd) + strlen(devlist[i]) + 2));
492 		(void) strcat(putdevcmd, " ");
493 		(void) strcat(putdevcmd, devlist[i]);
494 	}
495 	if (i != 0)
496 		(void) system(putdevcmd);
497 
498 	criteria[0] = "type=ctape";
499 
500 	devlist = getdev((char **)NULL, criteria, DTAB_ANDCRITERIA);
501 
502 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp ctape");
503 	for (i = 0; devlist[i] != (char *)NULL; i++) {
504 		checkandresize((strlen(putdevcmd) + strlen(devlist[i]) + 2));
505 		(void) strcat(putdevcmd, " ");
506 		(void) strcat(putdevcmd, devlist[i]);
507 	}
508 	if (i != 0)
509 		(void) system(putdevcmd);
510 
511 	criteria[0] = "type=diskette";
512 
513 	devlist = getdev((char **)NULL, criteria, DTAB_ANDCRITERIA);
514 
515 	(void) sprintf(putdevcmd, "/usr/bin/putdgrp diskette");
516 	for (i = 0; devlist[i] != (char *)NULL; i++) {
517 		checkandresize((strlen(putdevcmd) + strlen(devlist[i]) + 2));
518 		(void) strcat(putdevcmd, " ");
519 		(void) strcat(putdevcmd, devlist[i]);
520 	}
521 	if (i != 0)
522 		(void) system(putdevcmd);
523 }
524 
525 static void
checkandresize(int size)526 checkandresize(int size)
527 {
528 	if (size >= lastlen) {
529 		putdevcmd = realloc(putdevcmd, lastlen * 2);
530 		lastlen = lastlen * 2;
531 	}
532 }
533 
534 /*ARGSUSED*/
535 int
main(int argc,char ** argv)536 main(int argc, char **argv)
537 {
538 	(void) strncpy(cmd, argv[0], 80);
539 
540 	initialize();
541 
542 	/*
543 	 * AT&T code looked at the 3B2 EDT here.  Since we have a known-good
544 	 * /dev directory ( presuming 'disks' has already been run), we simply
545 	 * look in the /dev subdirectories.
546 	 */
547 	do_hdisks();
548 
549 	do_fdisks();
550 
551 	do_tapes();
552 
553 	/*
554 	 * Update the dgroup.tab file.
555 	 */
556 	mkdgroups();
557 
558 	return (0);
559 
560 }
561