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