AT&T free
[unix-history] / usr / src / sbin / newfs / newfs.c
CommitLineData
c018628f 1/*
ec7b02f7
KM
2 * Copyright (c) 1983, 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
c018628f
DF
16 */
17
18#ifndef lint
ec7b02f7
KM
19static char sccsid[] = "@(#)newfs.c 6.19 (Berkeley) %G%";
20#endif /* not lint */
c018628f 21
a54c0b3f 22#ifndef lint
ec7b02f7
KM
23char copyright[] =
24"@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
25 All rights reserved.\n";
26#endif /* not lint */
a54c0b3f
SL
27
28/*
c6003316 29 * newfs: friendly front end to mkfs
a54c0b3f
SL
30 */
31#include <sys/param.h>
32#include <sys/stat.h>
e6c352bc
KM
33#include <ufs/fs.h>
34#include <ufs/dir.h>
8485bb11
KM
35#include <sys/ioctl.h>
36#include <sys/disklabel.h>
37#include <sys/file.h>
ec7b02f7 38#include <sys/mount.h>
a54c0b3f
SL
39
40#include <stdio.h>
8485bb11 41#include <ctype.h>
7abf8d65 42#include <paths.h>
a54c0b3f 43
f24e4d82
MK
44#define COMPAT /* allow non-labeled disks */
45
8485bb11
KM
46/*
47 * The following two constants set the default block and fragment sizes.
48 * Both constants must be a power of 2 and meet the following constraints:
49 * MINBSIZE <= DESBLKSIZE <= MAXBSIZE
50 * sectorsize <= DESFRAGSIZE <= DESBLKSIZE
51 * DESBLKSIZE / DESFRAGSIZE <= 8
52 */
53#define DFL_FRAGSIZE 1024
54#define DFL_BLKSIZE 8192
55
56/*
38f1cd11 57 * Cylinder groups may have up to many cylinders. The actual
8485bb11 58 * number used depends upon how much information can be stored
38f1cd11 59 * on a single cylinder. The default is to use 16 cylinders
8485bb11
KM
60 * per group.
61 */
62#define DESCPG 16 /* desired fs_cpg */
89241117 63
8485bb11
KM
64/*
65 * MINFREE gives the minimum acceptable percentage of file system
66 * blocks which may be free. If the freelist drops below this level
67 * only the superuser may continue to allocate blocks. This may
68 * be set to 0 if no reserve of free blocks is deemed necessary,
69 * however throughput drops by fifty percent if the file system
70 * is run at between 90% and 100% full; thus the default value of
71 * fs_minfree is 10%. With 10% free space, fragmentation is not a
72 * problem, so we choose to optimize for time.
73 */
74#define MINFREE 10
75#define DEFAULTOPT FS_OPTTIME
76
77/*
78 * ROTDELAY gives the minimum number of milliseconds to initiate
79 * another disk transfer on the same cylinder. It is used in
80 * determining the rotationally optimal layout for disk blocks
81 * within a file; the default of fs_rotdelay is 4ms.
82 */
83#define ROTDELAY 4
84
85/*
86 * MAXCONTIG sets the default for the maximum number of blocks
87 * that may be allocated sequentially. Since UNIX drivers are
88 * not capable of scheduling multi-block transfers, this defaults
89 * to 1 (ie no contiguous blocks are allocated).
90 */
91#define MAXCONTIG 1
92
3d632f12
KM
93/*
94 * MAXBLKPG determines the maximum number of data blocks which are
95 * placed in a single cylinder group. The default is one indirect
96 * block worth of data blocks.
97 */
98#define MAXBLKPG(bsize) ((bsize) / sizeof(daddr_t))
99
8485bb11
KM
100/*
101 * Each file system has a number of inodes statically allocated.
ec7b02f7 102 * We allocate one inode slot per NFPI fragments, expecting this
8485bb11
KM
103 * to be far more than we will ever need.
104 */
ec7b02f7 105#define NFPI 4
8485bb11 106
38f1cd11
KM
107/*
108 * For each cylinder we keep track of the availability of blocks at different
109 * rotational positions, so that we can lay out the data to be picked
110 * up with minimum rotational latency. NRPOS is the default number of
111 * rotational positions that we distinguish. With NRPOS of 8 the resolution
112 * of our summary information is 2ms for a typical 3600 rpm drive.
113 */
114#define NRPOS 8 /* number distinct rotational positions */
115
116
ec7b02f7 117int memfs; /* run as the memory based filesystem */
8485bb11 118int Nflag; /* run without writing file system */
a54c0b3f 119int fssize; /* file system size */
a54c0b3f
SL
120int ntracks; /* # tracks/cylinder */
121int nsectors; /* # sectors/track */
a20edd44 122int nphyssectors; /* # sectors/track including spares */
8485bb11 123int secpercyl; /* sectors per cylinder */
a20edd44
KM
124int trackspares = -1; /* spare sectors per track */
125int cylspares = -1; /* spare sectors per cylinder */
a54c0b3f 126int sectorsize; /* bytes/sector */
c5d3fd78
MK
127#ifdef tahoe
128int realsectorsize; /* bytes/sector in hardware */
129#endif
c6003316 130int rpm; /* revolutions/minute of drive */
a20edd44
KM
131int interleave; /* hardware sector interleave */
132int trackskew = -1; /* sector 0 skew, per track */
133int headswitch; /* head switch time, usec */
134int trackseek; /* track-to-track seek, usec */
187d180d
MK
135int fsize = 0; /* fragment size */
136int bsize = 0; /* block size */
8485bb11 137int cpg = DESCPG; /* cylinders/cylinder group */
f40b03d9 138int cpgflg; /* cylinders/cylinder group flag was given */
8485bb11
KM
139int minfree = MINFREE; /* free space threshold */
140int opt = DEFAULTOPT; /* optimization preference (space or time) */
ec7b02f7 141int density; /* number of bytes per inode */
8485bb11
KM
142int maxcontig = MAXCONTIG; /* max contiguous blocks to allocate */
143int rotdelay = ROTDELAY; /* rotational delay between blocks */
3d632f12 144int maxbpg; /* maximum blocks per file in a cyl group */
38f1cd11 145int nrpos = NRPOS; /* # of distinguished rotational positions */
c5d3fd78
MK
146int bbsize = BBSIZE; /* boot block size */
147int sbsize = SBSIZE; /* superblock size */
ec7b02f7
KM
148u_long memleft; /* virtual memory available */
149caddr_t membase; /* start address of memory based filesystem */
f24e4d82
MK
150#ifdef COMPAT
151int unlabelled;
152#endif
8485bb11 153
a54c0b3f 154char device[MAXPATHLEN];
ec7b02f7 155char *progname;
a54c0b3f 156
8485bb11 157extern int errno;
a54c0b3f
SL
158char *index();
159char *rindex();
a54c0b3f
SL
160
161main(argc, argv)
1b8b6e44 162 int argc;
a54c0b3f
SL
163 char *argv[];
164{
ec7b02f7 165 char *cp, *special, *rindex();
a54c0b3f 166 register struct partition *pp;
8485bb11
KM
167 register struct disklabel *lp;
168 struct disklabel *getdisklabel();
169 struct partition oldpartition;
ec7b02f7 170 struct mfs_args args;
a54c0b3f 171 struct stat st;
8485bb11 172 int fsi, fso;
a54c0b3f
SL
173 register int i;
174 int status;
ec7b02f7 175 char buf[BUFSIZ];
a54c0b3f 176
ec7b02f7
KM
177 if ((progname = rindex(*argv, '/') + 1) == (char *)1)
178 progname = *argv;
179 if (!strcmp(progname, "memfs")) {
180 Nflag++;
181 memfs++;
182 }
a54c0b3f
SL
183 argc--, argv++;
184 while (argc > 0 && argv[0][0] == '-') {
185 for (cp = &argv[0][1]; *cp; cp++)
186 switch (*cp) {
187
28b1d98d
KM
188 case 'N':
189 Nflag++;
11b2fe08
HS
190 break;
191
8485bb11 192 case 'S':
a54c0b3f 193 if (argc < 1)
8485bb11 194 fatal("-S: missing sector size");
a54c0b3f 195 argc--, argv++;
8485bb11
KM
196 sectorsize = atoi(*argv);
197 if (sectorsize <= 0)
198 fatal("%s: bad sector size", *argv);
a54c0b3f
SL
199 goto next;
200
8485bb11 201 case 'a':
75e589fc 202 if (argc < 1)
3d632f12 203 fatal("-a: missing max contiguous blocks\n");
75e589fc 204 argc--, argv++;
3d632f12
KM
205 maxcontig = atoi(*argv);
206 if (maxcontig <= 0)
207 fatal("%s: bad max contiguous blocks\n",
208 *argv);
75e589fc
KM
209 goto next;
210
a54c0b3f
SL
211 case 'b':
212 if (argc < 1)
213 fatal("-b: missing block size");
214 argc--, argv++;
215 bsize = atoi(*argv);
8485bb11 216 if (bsize < MINBSIZE)
a54c0b3f
SL
217 fatal("%s: bad block size", *argv);
218 goto next;
219
8485bb11 220 case 'c':
a54c0b3f 221 if (argc < 1)
8485bb11 222 fatal("-c: missing cylinders/group");
a54c0b3f 223 argc--, argv++;
8485bb11
KM
224 cpg = atoi(*argv);
225 if (cpg <= 0)
226 fatal("%s: bad cylinders/group", *argv);
f40b03d9 227 cpgflg++;
a54c0b3f
SL
228 goto next;
229
8485bb11 230 case 'd':
a54c0b3f 231 if (argc < 1)
3d632f12 232 fatal("-d: missing rotational delay\n");
a54c0b3f 233 argc--, argv++;
3d632f12
KM
234 rotdelay = atoi(*argv);
235 if (rotdelay < 0)
236 fatal("%s: bad rotational delay\n",
237 *argv);
238 goto next;
239
240 case 'e':
241 if (argc < 1)
242 fatal("-e: missing blocks pre file in a cyl group\n");
243 argc--, argv++;
244 maxbpg = atoi(*argv);
245 if (maxbpg <= 0)
246 fatal("%s: bad blocks per file in a cyl group\n",
247 *argv);
a54c0b3f
SL
248 goto next;
249
8485bb11 250 case 'f':
a54c0b3f 251 if (argc < 1)
8485bb11 252 fatal("-f: missing frag size");
a54c0b3f 253 argc--, argv++;
8485bb11
KM
254 fsize = atoi(*argv);
255 if (fsize <= 0)
256 fatal("%s: bad frag size", *argv);
257 goto next;
258
259 case 'i':
260 if (argc < 1)
261 fatal("-i: missing bytes per inode\n");
262 argc--, argv++;
263 density = atoi(*argv);
264 if (density <= 0)
265 fatal("%s: bad bytes per inode\n",
266 *argv);
a54c0b3f
SL
267 goto next;
268
a20edd44
KM
269 case 'k':
270 if (argc < 1)
271 fatal("-k: track skew");
272 argc--, argv++;
273 trackskew = atoi(*argv);
274 if (trackskew < 0)
275 fatal("%s: bad track skew", *argv);
276 goto next;
277
278 case 'l':
279 if (argc < 1)
280 fatal("-l: interleave");
281 argc--, argv++;
282 interleave = atoi(*argv);
283 if (interleave <= 0)
284 fatal("%s: bad interleave", *argv);
285 goto next;
286
c6003316
SL
287 case 'm':
288 if (argc < 1)
289 fatal("-m: missing free space %%\n");
290 argc--, argv++;
291 minfree = atoi(*argv);
292 if (minfree < 0 || minfree > 99)
293 fatal("%s: bad free space %%\n",
294 *argv);
295 goto next;
296
38f1cd11
KM
297 case 'n':
298 if (argc < 1)
299 fatal("-n: missing rotational layout count\n");
300 argc--, argv++;
301 nrpos = atoi(*argv);
302 if (nrpos <= 0)
303 fatal("%s: bad rotational layout count\n",
304 *argv);
305 goto next;
306
8485bb11
KM
307 case 'o':
308 if (argc < 1)
309 fatal("-o: missing optimization preference");
310 argc--, argv++;
311 if (strcmp(*argv, "space") == 0)
312 opt = FS_OPTSPACE;
313 else if (strcmp(*argv, "time") == 0)
314 opt = FS_OPTTIME;
315 else
316 fatal("%s: bad optimization preference %s",
317 *argv,
318 "(options are `space' or `time')");
319 goto next;
320
a20edd44
KM
321 case 'p':
322 if (argc < 1)
323 fatal("-p: spare sectors per track");
324 argc--, argv++;
325 trackspares = atoi(*argv);
326 if (trackspares < 0)
327 fatal("%s: bad spare sectors per track", *argv);
328 goto next;
329
c6003316
SL
330 case 'r':
331 if (argc < 1)
332 fatal("-r: missing revs/minute\n");
333 argc--, argv++;
334 rpm = atoi(*argv);
8485bb11 335 if (rpm <= 0)
c6003316
SL
336 fatal("%s: bad revs/minute\n", *argv);
337 goto next;
338
8485bb11 339 case 's':
685a1465 340 if (argc < 1)
8485bb11 341 fatal("-s: missing file system size");
685a1465 342 argc--, argv++;
8485bb11
KM
343 fssize = atoi(*argv);
344 if (fssize <= 0)
345 fatal("%s: bad file system size",
685a1465
KM
346 *argv);
347 goto next;
348
8485bb11
KM
349 case 't':
350 if (argc < 1)
351 fatal("-t: missing track total");
352 argc--, argv++;
353 ntracks = atoi(*argv);
354 if (ntracks <= 0)
355 fatal("%s: bad total tracks", *argv);
356 goto next;
357
3d632f12
KM
358 case 'u':
359 if (argc < 1)
360 fatal("-u: missing sectors/track");
361 argc--, argv++;
362 nsectors = atoi(*argv);
363 if (nsectors <= 0)
364 fatal("%s: bad sectors/track", *argv);
365 goto next;
366
367 case 'x':
368 if (argc < 1)
369 fatal("-x: spare sectors per cylinder");
370 argc--, argv++;
371 cylspares = atoi(*argv);
372 if (cylspares < 0)
373 fatal("%s: bad spare sectors per cylinder", *argv);
374 goto next;
375
a54c0b3f 376 default:
fbf84598 377 fatal("-%c: unknown flag", *cp);
a54c0b3f
SL
378 }
379next:
380 argc--, argv++;
381 }
8485bb11 382 if (argc < 1) {
ec7b02f7
KM
383 if (memfs)
384 fprintf(stderr,
385 "usage: memfs [ fsoptions ] special-device %s\n",
386 "mount-point");
387 else
f24e4d82 388#ifdef COMPAT
ec7b02f7
KM
389 fprintf(stderr, "usage: %s\n",
390 "newfs [ fsoptions ] special-device [device-type]");
f24e4d82 391#else
ec7b02f7
KM
392 fprintf(stderr,
393 "usage: newfs [ fsoptions ] special-device\n");
f24e4d82 394#endif
8485bb11 395 fprintf(stderr, "where fsoptions are:\n");
28b1d98d
KM
396 fprintf(stderr, "\t-N do not create file system, %s\n",
397 "just print out parameters");
e6b4584b
SL
398 fprintf(stderr, "\t-b block size\n");
399 fprintf(stderr, "\t-f frag size\n");
c6003316 400 fprintf(stderr, "\t-m minimum free space %%\n");
75e589fc
KM
401 fprintf(stderr, "\t-o optimization preference %s\n",
402 "(`space' or `time')");
3d632f12
KM
403 fprintf(stderr, "\t-a maximum contiguous blocks\n");
404 fprintf(stderr, "\t-d rotational delay between %s\n",
405 "contiguous blocks");
406 fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
407 "cylinder group");
685a1465 408 fprintf(stderr, "\t-i number of bytes per inode\n");
6bd85141 409 fprintf(stderr, "\t-c cylinders/group\n");
38f1cd11
KM
410 fprintf(stderr, "\t-n number of distinguished %s\n",
411 "rotational positions");
6bd85141
KM
412 fprintf(stderr, "\t-s file system size (sectors)\n");
413 fprintf(stderr, "\t-r revolutions/minute\n");
8485bb11 414 fprintf(stderr, "\t-S sector size\n");
3d632f12 415 fprintf(stderr, "\t-u sectors/track\n");
6bd85141 416 fprintf(stderr, "\t-t tracks/cylinder\n");
a20edd44 417 fprintf(stderr, "\t-p spare sectors per track\n");
3d632f12 418 fprintf(stderr, "\t-x spare sectors per cylinder\n");
6bd85141
KM
419 fprintf(stderr, "\t-l hardware sector interleave\n");
420 fprintf(stderr, "\t-k sector 0 skew, per track\n");
a54c0b3f
SL
421 exit(1);
422 }
423 special = argv[0];
1b8b6e44
KM
424 cp = rindex(special, '/');
425 if (cp != 0)
426 special = cp + 1;
2f56e34c 427 if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
1b8b6e44 428 special++;
7abf8d65 429 (void)sprintf(device, "%s/r%s", _PATH_DEV, special);
9bd38ba8 430 special = device;
8485bb11
KM
431 if (!Nflag) {
432 fso = open(special, O_WRONLY);
433 if (fso < 0) {
434 perror(special);
ec7b02f7 435 exit(2);
8485bb11
KM
436 }
437 } else
438 fso = -1;
439 fsi = open(special, O_RDONLY);
440 if (fsi < 0) {
441 perror(special);
ec7b02f7 442 exit(3);
8485bb11
KM
443 }
444 if (fstat(fsi, &st) < 0) {
ec7b02f7
KM
445 fprintf(stderr, "%s: ", progname); perror(special);
446 exit(4);
a54c0b3f 447 }
1b8b6e44
KM
448 if ((st.st_mode & S_IFMT) != S_IFCHR)
449 fatal("%s: not a character device", special);
a54c0b3f 450 cp = index(argv[0], '\0') - 1;
8485bb11 451 if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
a54c0b3f 452 fatal("%s: can't figure out file system partition", argv[0]);
f24e4d82
MK
453#ifdef COMPAT
454 lp = getdisklabel(special, fsi, argv[1]);
455#else
8485bb11 456 lp = getdisklabel(special, fsi);
f24e4d82 457#endif
8485bb11
KM
458 if (isdigit(*cp))
459 pp = &lp->d_partitions[0];
460 else
461 pp = &lp->d_partitions[*cp - 'a'];
462 if (pp->p_size == 0)
463 fatal("%s: `%c' partition is unavailable", argv[0], *cp);
464 if (fssize == 0)
a54c0b3f 465 fssize = pp->p_size;
ec7b02f7 466 if (fssize > pp->p_size && !memfs)
8485bb11
KM
467 fatal("%s: maximum file system size on the `%c' partition is %d",
468 argv[0], *cp, pp->p_size);
469 if (rpm == 0) {
470 rpm = lp->d_rpm;
471 if (rpm <= 0)
6181c540 472 rpm = 3600;
a54c0b3f
SL
473 }
474 if (ntracks == 0) {
8485bb11
KM
475 ntracks = lp->d_ntracks;
476 if (ntracks <= 0)
6181c540 477 fatal("%s: no default #tracks", argv[0]);
a54c0b3f 478 }
8485bb11
KM
479 if (nsectors == 0) {
480 nsectors = lp->d_nsectors;
481 if (nsectors <= 0)
6181c540 482 fatal("%s: no default #sectors/track", argv[0]);
8485bb11 483 }
a54c0b3f 484 if (sectorsize == 0) {
8485bb11
KM
485 sectorsize = lp->d_secsize;
486 if (sectorsize <= 0)
6181c540 487 fatal("%s: no default sector size", argv[0]);
a54c0b3f 488 }
a20edd44
KM
489 if (trackskew == -1) {
490 trackskew = lp->d_trackskew;
491 if (trackskew < 0)
6181c540 492 trackskew = 0;
a20edd44
KM
493 }
494 if (interleave == 0) {
495 interleave = lp->d_interleave;
496 if (interleave <= 0)
6181c540 497 interleave = 1;
a20edd44 498 }
a54c0b3f
SL
499 if (fsize == 0) {
500 fsize = pp->p_fsize;
8485bb11
KM
501 if (fsize <= 0)
502 fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
a54c0b3f 503 }
8485bb11
KM
504 if (bsize == 0) {
505 bsize = pp->p_frag * pp->p_fsize;
506 if (bsize <= 0)
507 bsize = MIN(DFL_BLKSIZE, 8 * fsize);
c6003316 508 }
ec7b02f7
KM
509 if (density == 0)
510 density = NFPI * fsize;
75e589fc 511 if (minfree < 10 && opt != FS_OPTSPACE) {
8485bb11
KM
512 fprintf(stderr, "Warning: changing optimization to space ");
513 fprintf(stderr, "because minfree is less than 10%%\n");
75e589fc
KM
514 opt = FS_OPTSPACE;
515 }
a20edd44
KM
516 if (trackspares == -1) {
517 trackspares = lp->d_sparespertrack;
518 if (trackspares < 0)
6181c540 519 trackspares = 0;
a20edd44
KM
520 }
521 nphyssectors = nsectors + trackspares;
522 if (cylspares == -1) {
523 cylspares = lp->d_sparespercyl;
524 if (cylspares < 0)
6181c540 525 cylspares = 0;
a20edd44
KM
526 }
527 secpercyl = nsectors * ntracks - cylspares;
8485bb11
KM
528 if (secpercyl != lp->d_secpercyl)
529 fprintf(stderr, "%s (%d) %s (%d)\n",
530 "Warning: calculated sectors per cylinder", secpercyl,
531 "disagrees with disk label", lp->d_secpercyl);
c9b3f9df
KM
532 if (maxbpg == 0)
533 maxbpg = MAXBLKPG(bsize);
a20edd44
KM
534 headswitch = lp->d_headswitch;
535 trackseek = lp->d_trkseek;
c5d3fd78
MK
536 bbsize = lp->d_bbsize;
537 sbsize = lp->d_sbsize;
8485bb11 538 oldpartition = *pp;
c5d3fd78
MK
539#ifdef tahoe
540 realsectorsize = sectorsize;
187d180d 541 if (sectorsize != DEV_BSIZE) { /* XXX */
c5d3fd78
MK
542 int secperblk = DEV_BSIZE / sectorsize;
543
544 sectorsize = DEV_BSIZE;
545 nsectors /= secperblk;
546 nphyssectors /= secperblk;
547 secpercyl /= secperblk;
548 fssize /= secperblk;
549 pp->p_size /= secperblk;
550 }
551#endif
8485bb11 552 mkfs(pp, special, fsi, fso);
c5d3fd78
MK
553#ifdef tahoe
554 if (realsectorsize != DEV_BSIZE)
555 pp->p_size *= DEV_BSIZE / realsectorsize;
556#endif
8485bb11
KM
557 if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
558 rewritelabel(special, fso, lp);
ec7b02f7
KM
559 if (!Nflag)
560 close(fso);
561 close(fsi);
562 if (memfs) {
563 sprintf(buf, "memfs:%d", getpid());
564 args.name = buf;
565 args.base = membase;
566 args.size = fssize * sectorsize;
567 if (mount(MOUNT_MFS, argv[1], 0, &args) < 0) {
568 perror("memfs: mount");
569 exit(5);
570 }
571 }
a54c0b3f
SL
572 exit(0);
573}
574
f24e4d82
MK
575#ifdef COMPAT
576struct disklabel *
577getdisklabel(s, fd, type)
578 char *s, *type;
579 int fd;
580{
581 static struct disklabel lab;
582 struct disklabel *getdiskbyname();
583
584 if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
585 if (type == NULL) {
586 perror("ioctl (GDINFO)");
587 fatal(
588 "%s: can't read disk label; disk type must be specified", s);
589 }
590 unlabelled++;
591 return (getdiskbyname(type));
592 }
593 return (&lab);
594}
595#else
8485bb11
KM
596struct disklabel *
597getdisklabel(s, fd)
598 char *s;
f24e4d82 599 int fd;
a54c0b3f 600{
8485bb11
KM
601 static struct disklabel lab;
602
603 if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
604 perror("ioctl (GDINFO)");
605 fatal("%s: can't read disk label", s);
606 }
607 return (&lab);
608}
f24e4d82 609#endif
8485bb11
KM
610
611rewritelabel(s, fd, lp)
612 char *s;
a54c0b3f 613 int fd;
8485bb11
KM
614 register struct disklabel *lp;
615{
616
f24e4d82
MK
617#ifdef COMPAT
618 if (unlabelled)
619 return;
620#endif
8485bb11
KM
621 lp->d_checksum = 0;
622 lp->d_checksum = dkcksum(lp);
623 if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
aaa1c5f0 624 perror("ioctl (WDINFO)");
8485bb11 625 fatal("%s: can't rewrite disk label", s);
a54c0b3f 626 }
bf8f0524
MK
627#if vax
628 if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
629 register i;
c5d3fd78 630 int cfd;
bf8f0524 631 daddr_t alt;
c5d3fd78
MK
632 char specname[64];
633 char blk[1024];
866736b4 634 char *cp;
c5d3fd78
MK
635
636 /*
637 * Make name for 'c' partition.
638 */
639 strcpy(specname, s);
640 cp = specname + strlen(specname) - 1;
641 if (!isdigit(*cp))
642 *cp = 'c';
643 cfd = open(specname, O_WRONLY);
644 if (cfd < 0) {
645 perror(specname);
ec7b02f7 646 exit(6);
c5d3fd78
MK
647 }
648 bzero(blk, sizeof(blk));
649 *(struct disklabel *)(blk + LABELOFFSET) = *lp;
bf8f0524
MK
650 alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
651 for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
f24e4d82
MK
652 if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
653 perror("lseek to badsector area");
ec7b02f7 654 exit(7);
f24e4d82 655 }
c5d3fd78 656 if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
bf8f0524
MK
657 int oerrno = errno;
658 fprintf(stderr, "alternate label %d ", i/2);
659 errno = oerrno;
660 perror("write");
661 }
8485bb11 662 }
ec7b02f7 663 close(cfd);
8485bb11 664 }
bf8f0524 665#endif
a54c0b3f
SL
666}
667
668/*VARARGS*/
669fatal(fmt, arg1, arg2)
670 char *fmt;
671{
672
ec7b02f7 673 fprintf(stderr, "%s: ", progname);
a54c0b3f
SL
674 fprintf(stderr, fmt, arg1, arg2);
675 putc('\n', stderr);
ec7b02f7 676 exit(8);
a54c0b3f 677}