Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/bsdlabel/bsdlabel.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-4-Clause
3
*
4
* Copyright (c) 1994, 1995 Gordon W. Ross
5
* Copyright (c) 1994 Theo de Raadt
6
* All rights reserved.
7
* Copyright (c) 1987, 1993
8
* The Regents of the University of California. All rights reserved.
9
*
10
* This code is derived from software contributed to Berkeley by
11
* Symmetric Computer Systems.
12
*
13
* Redistribution and use in source and binary forms, with or without
14
* modification, are permitted provided that the following conditions
15
* are met:
16
* 1. Redistributions of source code must retain the above copyright
17
* notice, this list of conditions and the following disclaimer.
18
* 2. Redistributions in binary form must reproduce the above copyright
19
* notice, this list of conditions and the following disclaimer in the
20
* documentation and/or other materials provided with the distribution.
21
* 3. All advertising materials mentioning features or use of this software
22
* must display the following acknowledgement:
23
* This product includes software developed by the University of
24
* California, Berkeley and its contributors.
25
* This product includes software developed by Theo de Raadt.
26
* 4. Neither the name of the University nor the names of its contributors
27
* may be used to endorse or promote products derived from this software
28
* without specific prior written permission.
29
*
30
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
* SUCH DAMAGE.
41
*
42
* from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $
43
*/
44
45
#include <sys/param.h>
46
#include <stdint.h>
47
#include <sys/file.h>
48
#include <sys/stat.h>
49
#include <sys/wait.h>
50
#include <sys/disk.h>
51
#define DKTYPENAMES
52
#define FSTYPENAMES
53
#define MAXPARTITIONS 8 /* XXX should be 20, but see PR276517 */
54
#include <sys/disklabel.h>
55
56
#include <unistd.h>
57
#include <string.h>
58
#include <stdio.h>
59
#include <libgeom.h>
60
#include <stdlib.h>
61
#include <signal.h>
62
#include <stdarg.h>
63
#include <ctype.h>
64
#include <err.h>
65
#include <errno.h>
66
67
#include "pathnames.h"
68
69
static void makelabel(const char *, struct disklabel *);
70
static int geom_class_available(const char *);
71
static int writelabel(void);
72
static int readlabel(int flag);
73
static void display(FILE *, const struct disklabel *);
74
static int edit(void);
75
static int editit(void);
76
static void fixlabel(struct disklabel *);
77
static char *skip(char *);
78
static char *word(char *);
79
static int getasciilabel(FILE *, struct disklabel *);
80
static int getasciipartspec(char *, struct disklabel *, int, int);
81
static int checklabel(struct disklabel *);
82
static void usage(void);
83
static struct disklabel *getvirginlabel(void);
84
85
#define DEFEDITOR _PATH_VI
86
#define DEFPARTITIONS 8
87
88
static char *specname;
89
static char *pname;
90
static char tmpfil[] = PATH_TMPFILE;
91
92
static struct disklabel lab;
93
static u_char bootarea[BBSIZE];
94
static off_t mediasize;
95
static ssize_t secsize;
96
static char blank[] = "";
97
static char unknown[] = "unknown";
98
99
#define MAX_PART ('z')
100
#define MAX_NUM_PARTS (1 + MAX_PART - 'a')
101
static char part_size_type[MAX_NUM_PARTS];
102
static char part_offset_type[MAX_NUM_PARTS];
103
static int part_set[MAX_NUM_PARTS];
104
105
static int installboot; /* non-zero if we should install a boot program */
106
static int allfields; /* present all fields in edit */
107
static char const *xxboot; /* primary boot */
108
109
static uint32_t lba_offset;
110
#ifndef LABELSECTOR
111
#define LABELSECTOR -1
112
#endif
113
#ifndef LABELOFFSET
114
#define LABELOFFSET -1
115
#endif
116
static int labelsoffset = LABELSECTOR;
117
static int labeloffset = LABELOFFSET;
118
static int bbsize = BBSIZE;
119
120
static enum {
121
UNSPEC, EDIT, READ, RESTORE, WRITE, WRITEBOOT
122
} op = UNSPEC;
123
124
125
static int disable_write; /* set to disable writing to disk label */
126
static int is_file; /* work on a file (abs. pathname), "-f" opt. */
127
128
int
129
main(int argc, char *argv[])
130
{
131
FILE *t;
132
int ch, error, fd;
133
const char *name;
134
135
error = 0;
136
name = NULL;
137
138
fprintf(stderr,
139
"WARNING: bsdlabel is deprecated and is not available in FreeBSD 15 or later.\n"
140
"Please use gpart instead.\n\n");
141
142
while ((ch = getopt(argc, argv, "ABb:efm:nRrw")) != -1)
143
switch (ch) {
144
case 'A':
145
allfields = 1;
146
break;
147
case 'B':
148
++installboot;
149
break;
150
case 'b':
151
xxboot = optarg;
152
break;
153
case 'f':
154
is_file=1;
155
break;
156
case 'm':
157
if (!strcmp(optarg, "i386") ||
158
!strcmp(optarg, "amd64")) {
159
labelsoffset = 1;
160
labeloffset = 0;
161
bbsize = 8192;
162
} else {
163
errx(1, "Unsupported architecture");
164
}
165
break;
166
case 'n':
167
disable_write = 1;
168
break;
169
case 'R':
170
if (op != UNSPEC)
171
usage();
172
op = RESTORE;
173
break;
174
case 'e':
175
if (op != UNSPEC)
176
usage();
177
op = EDIT;
178
break;
179
case 'r':
180
/*
181
* We accept and ignore -r for compatibility with
182
* historical disklabel usage.
183
*/
184
break;
185
case 'w':
186
if (op != UNSPEC)
187
usage();
188
op = WRITE;
189
break;
190
case '?':
191
default:
192
usage();
193
}
194
argc -= optind;
195
argv += optind;
196
197
if (argc < 1)
198
usage();
199
if (labelsoffset < 0 || labeloffset < 0)
200
errx(1, "a -m <architecture> option must be specified");
201
202
/* Figure out the names of the thing we're working on */
203
if (is_file) {
204
specname = argv[0];
205
} else {
206
specname = g_device_path(argv[0]);
207
if (specname == NULL) {
208
warn("unable to get correct path for %s", argv[0]);
209
return(1);
210
}
211
fd = open(specname, O_RDONLY);
212
if (fd < 0) {
213
warn("error opening %s", specname);
214
return(1);
215
}
216
pname = g_providername(fd);
217
if (pname == NULL) {
218
warn("error getting providername for %s", specname);
219
close(fd);
220
return(1);
221
}
222
close(fd);
223
}
224
225
if (installboot && op == UNSPEC)
226
op = WRITEBOOT;
227
else if (op == UNSPEC)
228
op = READ;
229
230
switch(op) {
231
232
case UNSPEC:
233
break;
234
235
case EDIT:
236
if (argc != 1)
237
usage();
238
readlabel(1);
239
fixlabel(&lab);
240
error = edit();
241
break;
242
243
case READ:
244
if (argc != 1)
245
usage();
246
readlabel(1);
247
display(stdout, NULL);
248
error = checklabel(NULL);
249
break;
250
251
case RESTORE:
252
if (argc != 2)
253
usage();
254
if (!(t = fopen(argv[1], "r")))
255
err(4, "fopen %s", argv[1]);
256
readlabel(0);
257
if (!getasciilabel(t, &lab))
258
exit(1);
259
error = writelabel();
260
break;
261
262
case WRITE:
263
if (argc == 2)
264
name = argv[1];
265
else if (argc == 1)
266
name = "auto";
267
else
268
usage();
269
readlabel(0);
270
makelabel(name, &lab);
271
fixlabel(&lab);
272
if (checklabel(NULL) == 0)
273
error = writelabel();
274
break;
275
276
case WRITEBOOT:
277
278
readlabel(1);
279
fixlabel(&lab);
280
if (argc == 2)
281
makelabel(argv[1], &lab);
282
if (checklabel(NULL) == 0)
283
error = writelabel();
284
break;
285
}
286
exit(error);
287
}
288
289
static void
290
fixlabel(struct disklabel *lp)
291
{
292
struct partition *dp;
293
int i;
294
295
for (i = 0; i < lp->d_npartitions; i++) {
296
if (i == RAW_PART)
297
continue;
298
if (lp->d_partitions[i].p_size)
299
return;
300
}
301
302
dp = &lp->d_partitions[0];
303
dp->p_offset = BBSIZE / secsize;
304
dp->p_size = lp->d_secperunit - dp->p_offset;
305
}
306
307
/*
308
* Construct a prototype disklabel from /etc/disktab.
309
*/
310
static void
311
makelabel(const char *type, struct disklabel *lp)
312
{
313
struct disklabel *dp;
314
315
if (strcmp(type, "auto") == 0)
316
dp = getvirginlabel();
317
else
318
dp = getdiskbyname(type);
319
if (dp == NULL)
320
errx(1, "%s: unknown disk type", type);
321
*lp = *dp;
322
bzero(lp->d_packname, sizeof(lp->d_packname));
323
}
324
325
static void
326
readboot(void)
327
{
328
int fd;
329
struct stat st;
330
331
if (xxboot == NULL)
332
xxboot = "/boot/boot";
333
fd = open(xxboot, O_RDONLY);
334
if (fd < 0)
335
err(1, "cannot open %s", xxboot);
336
fstat(fd, &st);
337
if (st.st_size <= BBSIZE) {
338
if (read(fd, bootarea, st.st_size) != st.st_size)
339
err(1, "read error %s", xxboot);
340
close(fd);
341
return;
342
}
343
errx(1, "boot code %s is wrong size", xxboot);
344
}
345
346
static int
347
geom_class_available(const char *name)
348
{
349
struct gclass *class;
350
struct gmesh mesh;
351
int error;
352
353
error = geom_gettree(&mesh);
354
if (error != 0)
355
errc(1, error, "Cannot get GEOM tree");
356
357
LIST_FOREACH(class, &mesh.lg_class, lg_class) {
358
if (strcmp(class->lg_name, name) == 0) {
359
geom_deletetree(&mesh);
360
return (1);
361
}
362
}
363
364
geom_deletetree(&mesh);
365
366
return (0);
367
}
368
369
static int
370
writelabel(void)
371
{
372
int i, fd, serrno;
373
struct disklabel *lp = &lab;
374
375
if (disable_write) {
376
warnx("write to disk label suppressed - label was as follows:");
377
display(stdout, NULL);
378
return (0);
379
}
380
381
lp->d_magic = DISKMAGIC;
382
lp->d_magic2 = DISKMAGIC;
383
lp->d_checksum = 0;
384
lp->d_checksum = dkcksum(lp);
385
if (installboot)
386
readboot();
387
for (i = 0; i < lab.d_npartitions; i++)
388
if (lab.d_partitions[i].p_size)
389
lab.d_partitions[i].p_offset += lba_offset;
390
bsd_disklabel_le_enc(bootarea + labeloffset + labelsoffset * lab.d_secsize,
391
lp);
392
393
fd = open(specname, O_RDWR);
394
if (fd < 0) {
395
if (is_file) {
396
warn("cannot open file %s for writing label", specname);
397
return(1);
398
} else
399
serrno = errno;
400
401
if (geom_class_available("PART") != 0) {
402
/*
403
* Since we weren't able open provider for
404
* writing, then recommend user to use gpart(8).
405
*/
406
warnc(serrno,
407
"cannot open provider %s for writing label",
408
specname);
409
warnx("Try to use gpart(8).");
410
return (1);
411
}
412
413
warnc(serrno, "%s", specname);
414
return (1);
415
} else {
416
if (write(fd, bootarea, bbsize) != bbsize) {
417
warn("write %s", specname);
418
close (fd);
419
return (1);
420
}
421
close (fd);
422
}
423
return (0);
424
}
425
426
static void
427
get_file_parms(int f)
428
{
429
int i;
430
struct stat sb;
431
432
if (fstat(f, &sb) != 0)
433
err(4, "fstat failed");
434
i = sb.st_mode & S_IFMT;
435
if (i != S_IFREG && i != S_IFLNK)
436
errx(4, "%s is not a valid file or link", specname);
437
secsize = DEV_BSIZE;
438
mediasize = sb.st_size;
439
}
440
441
/*
442
* Fetch disklabel for disk.
443
*/
444
static int
445
readlabel(int flag)
446
{
447
ssize_t nbytes;
448
uint32_t lba;
449
int f, i;
450
int error;
451
452
f = open(specname, O_RDONLY);
453
if (f < 0)
454
err(1, "%s", specname);
455
if (is_file)
456
get_file_parms(f);
457
else {
458
mediasize = g_mediasize(f);
459
secsize = g_sectorsize(f);
460
if (secsize < 0 || mediasize < 0)
461
err(4, "cannot get disk geometry");
462
}
463
if (mediasize > (off_t)0xffffffff * secsize)
464
errx(1,
465
"disks with more than 2^32-1 sectors are not supported");
466
(void)lseek(f, (off_t)0, SEEK_SET);
467
nbytes = read(f, bootarea, BBSIZE);
468
if (nbytes == -1)
469
err(4, "%s read", specname);
470
if (nbytes != BBSIZE)
471
errx(4, "couldn't read %d bytes from %s", BBSIZE, specname);
472
close (f);
473
error = bsd_disklabel_le_dec(
474
bootarea + (labeloffset + labelsoffset * secsize),
475
&lab, MAXPARTITIONS);
476
if (flag && error)
477
errx(1, "%s: no valid label found", specname);
478
479
if (is_file)
480
return(0);
481
482
/*
483
* Compensate for absolute block addressing by finding the
484
* smallest partition offset and if the offset of the 'c'
485
* partition is equal to that, subtract it from all offsets.
486
*/
487
lba = ~0;
488
for (i = 0; i < lab.d_npartitions; i++) {
489
if (lab.d_partitions[i].p_size)
490
lba = MIN(lba, lab.d_partitions[i].p_offset);
491
}
492
if (lba != 0 && lab.d_partitions[RAW_PART].p_offset == lba) {
493
for (i = 0; i < lab.d_npartitions; i++) {
494
if (lab.d_partitions[i].p_size)
495
lab.d_partitions[i].p_offset -= lba;
496
}
497
/*
498
* Save the offset so that we can write the label
499
* back with absolute block addresses.
500
*/
501
lba_offset = lba;
502
}
503
return (error);
504
}
505
506
507
static void
508
display(FILE *f, const struct disklabel *lp)
509
{
510
int i, j;
511
const struct partition *pp;
512
513
if (lp == NULL)
514
lp = &lab;
515
516
fprintf(f, "# %s:\n", specname);
517
if (allfields) {
518
if (lp->d_type < DKMAXTYPES)
519
fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
520
else
521
fprintf(f, "type: %u\n", lp->d_type);
522
fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename),
523
lp->d_typename);
524
fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname),
525
lp->d_packname);
526
fprintf(f, "flags:");
527
if (lp->d_flags & D_REMOVABLE)
528
fprintf(f, " removeable");
529
if (lp->d_flags & D_ECC)
530
fprintf(f, " ecc");
531
if (lp->d_flags & D_BADSECT)
532
fprintf(f, " badsect");
533
fprintf(f, "\n");
534
fprintf(f, "bytes/sector: %lu\n", (u_long)lp->d_secsize);
535
fprintf(f, "sectors/track: %lu\n", (u_long)lp->d_nsectors);
536
fprintf(f, "tracks/cylinder: %lu\n", (u_long)lp->d_ntracks);
537
fprintf(f, "sectors/cylinder: %lu\n", (u_long)lp->d_secpercyl);
538
fprintf(f, "cylinders: %lu\n", (u_long)lp->d_ncylinders);
539
fprintf(f, "sectors/unit: %lu\n", (u_long)lp->d_secperunit);
540
fprintf(f, "rpm: %u\n", lp->d_rpm);
541
fprintf(f, "interleave: %u\n", lp->d_interleave);
542
fprintf(f, "trackskew: %u\n", lp->d_trackskew);
543
fprintf(f, "cylinderskew: %u\n", lp->d_cylskew);
544
fprintf(f, "headswitch: %lu\t\t# milliseconds\n",
545
(u_long)lp->d_headswitch);
546
fprintf(f, "track-to-track seek: %ld\t# milliseconds\n",
547
(u_long)lp->d_trkseek);
548
fprintf(f, "drivedata: ");
549
for (i = NDDATA - 1; i >= 0; i--)
550
if (lp->d_drivedata[i])
551
break;
552
if (i < 0)
553
i = 0;
554
for (j = 0; j <= i; j++)
555
fprintf(f, "%lu ", (u_long)lp->d_drivedata[j]);
556
fprintf(f, "\n\n");
557
}
558
fprintf(f, "%u partitions:\n", lp->d_npartitions);
559
fprintf(f,
560
"# size offset fstype [fsize bsize bps/cpg]\n");
561
pp = lp->d_partitions;
562
for (i = 0; i < lp->d_npartitions; i++, pp++) {
563
if (pp->p_size) {
564
fprintf(f, " %c: %10lu %10lu ", 'a' + i,
565
(u_long)pp->p_size, (u_long)pp->p_offset);
566
if (pp->p_fstype < FSMAXTYPES)
567
fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
568
else
569
fprintf(f, "%8d", pp->p_fstype);
570
switch (pp->p_fstype) {
571
572
case FS_UNUSED: /* XXX */
573
fprintf(f, " %5lu %5lu %2s",
574
(u_long)pp->p_fsize,
575
(u_long)(pp->p_fsize * pp->p_frag), "");
576
break;
577
578
case FS_BSDFFS:
579
fprintf(f, " %5lu %5lu %5u",
580
(u_long)pp->p_fsize,
581
(u_long)(pp->p_fsize * pp->p_frag),
582
pp->p_cpg);
583
break;
584
585
case FS_BSDLFS:
586
fprintf(f, " %5lu %5lu %5d",
587
(u_long)pp->p_fsize,
588
(u_long)(pp->p_fsize * pp->p_frag),
589
pp->p_cpg);
590
break;
591
592
default:
593
fprintf(f, "%20.20s", "");
594
break;
595
}
596
if (i == RAW_PART) {
597
fprintf(f, " # \"raw\" part, don't edit");
598
}
599
fprintf(f, "\n");
600
}
601
}
602
fflush(f);
603
}
604
605
static int
606
edit(void)
607
{
608
int c, fd;
609
struct disklabel label;
610
FILE *fp;
611
612
if ((fd = mkstemp(tmpfil)) == -1 ||
613
(fp = fdopen(fd, "w")) == NULL) {
614
warnx("can't create %s", tmpfil);
615
return (1);
616
}
617
display(fp, NULL);
618
fclose(fp);
619
for (;;) {
620
if (!editit())
621
break;
622
fp = fopen(tmpfil, "r");
623
if (fp == NULL) {
624
warnx("can't reopen %s for reading", tmpfil);
625
break;
626
}
627
bzero((char *)&label, sizeof(label));
628
c = getasciilabel(fp, &label);
629
fclose(fp);
630
if (c) {
631
lab = label;
632
if (writelabel() == 0) {
633
(void) unlink(tmpfil);
634
return (0);
635
}
636
}
637
printf("re-edit the label? [y]: ");
638
fflush(stdout);
639
c = getchar();
640
if (c != EOF && c != (int)'\n')
641
while (getchar() != (int)'\n')
642
;
643
if (c == (int)'n')
644
break;
645
}
646
(void) unlink(tmpfil);
647
return (1);
648
}
649
650
static int
651
editit(void)
652
{
653
int pid, xpid;
654
int locstat, omask;
655
const char *ed;
656
uid_t uid;
657
gid_t gid;
658
659
omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
660
while ((pid = fork()) < 0) {
661
if (errno == EPROCLIM) {
662
warnx("you have too many processes");
663
return(0);
664
}
665
if (errno != EAGAIN) {
666
warn("fork");
667
return(0);
668
}
669
sleep(1);
670
}
671
if (pid == 0) {
672
sigsetmask(omask);
673
gid = getgid();
674
if (setresgid(gid, gid, gid) == -1)
675
err(1, "setresgid");
676
uid = getuid();
677
if (setresuid(uid, uid, uid) == -1)
678
err(1, "setresuid");
679
if ((ed = getenv("EDITOR")) == (char *)0)
680
ed = DEFEDITOR;
681
execlp(ed, ed, tmpfil, (char *)0);
682
err(1, "%s", ed);
683
}
684
while ((xpid = wait(&locstat)) >= 0)
685
if (xpid == pid)
686
break;
687
sigsetmask(omask);
688
return(!locstat);
689
}
690
691
static char *
692
skip(char *cp)
693
{
694
695
while (*cp != '\0' && isspace(*cp))
696
cp++;
697
if (*cp == '\0' || *cp == '#')
698
return (NULL);
699
return (cp);
700
}
701
702
static char *
703
word(char *cp)
704
{
705
char c;
706
707
while (*cp != '\0' && !isspace(*cp) && *cp != '#')
708
cp++;
709
if ((c = *cp) != '\0') {
710
*cp++ = '\0';
711
if (c != '#')
712
return (skip(cp));
713
}
714
return (NULL);
715
}
716
717
/*
718
* Read an ascii label in from fd f,
719
* in the same format as that put out by display(),
720
* and fill in lp.
721
*/
722
static int
723
getasciilabel(FILE *f, struct disklabel *lp)
724
{
725
char *cp, *endp;
726
const char **cpp;
727
u_int part;
728
char *tp, line[BUFSIZ];
729
u_long v;
730
int lineno = 0, errors = 0;
731
int i;
732
733
makelabel("auto", lp);
734
bzero(&part_set, sizeof(part_set));
735
bzero(&part_size_type, sizeof(part_size_type));
736
bzero(&part_offset_type, sizeof(part_offset_type));
737
lp->d_bbsize = BBSIZE; /* XXX */
738
lp->d_sbsize = 0; /* XXX */
739
while (fgets(line, sizeof(line) - 1, f)) {
740
lineno++;
741
if ((cp = strchr(line,'\n')) != NULL)
742
*cp = '\0';
743
cp = skip(line);
744
if (cp == NULL)
745
continue;
746
tp = strchr(cp, ':');
747
if (tp == NULL) {
748
fprintf(stderr, "line %d: syntax error\n", lineno);
749
errors++;
750
continue;
751
}
752
*tp++ = '\0', tp = skip(tp);
753
if (!strcmp(cp, "type")) {
754
if (tp == NULL)
755
tp = unknown;
756
cpp = dktypenames;
757
for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
758
if (*cpp && !strcmp(*cpp, tp)) {
759
lp->d_type = cpp - dktypenames;
760
break;
761
}
762
if (cpp < &dktypenames[DKMAXTYPES])
763
continue;
764
errno = 0;
765
v = strtoul(tp, &endp, 10);
766
if (errno != 0 || *endp != '\0')
767
v = DKMAXTYPES;
768
if (v >= DKMAXTYPES)
769
fprintf(stderr, "line %d:%s %lu\n", lineno,
770
"Warning, unknown disk type", v);
771
else
772
lp->d_type = v;
773
continue;
774
}
775
if (!strcmp(cp, "flags")) {
776
for (v = 0; (cp = tp) && *cp != '\0';) {
777
tp = word(cp);
778
if (!strcmp(cp, "removeable"))
779
v |= D_REMOVABLE;
780
else if (!strcmp(cp, "ecc"))
781
v |= D_ECC;
782
else if (!strcmp(cp, "badsect"))
783
v |= D_BADSECT;
784
else {
785
fprintf(stderr,
786
"line %d: %s: bad flag\n",
787
lineno, cp);
788
errors++;
789
}
790
}
791
lp->d_flags = v;
792
continue;
793
}
794
if (!strcmp(cp, "drivedata")) {
795
for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
796
lp->d_drivedata[i++] = strtoul(cp, NULL, 10);
797
tp = word(cp);
798
}
799
continue;
800
}
801
if (sscanf(cp, "%lu partitions", &v) == 1) {
802
if (v > MAXPARTITIONS) {
803
fprintf(stderr,
804
"line %d: bad # of partitions\n", lineno);
805
lp->d_npartitions = MAXPARTITIONS;
806
errors++;
807
} else if (v < DEFPARTITIONS) {
808
fprintf(stderr,
809
"line %d: bad # of partitions\n", lineno);
810
lp->d_npartitions = DEFPARTITIONS;
811
errors++;
812
} else
813
lp->d_npartitions = v;
814
continue;
815
}
816
if (tp == NULL)
817
tp = blank;
818
if (!strcmp(cp, "disk")) {
819
strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
820
continue;
821
}
822
if (!strcmp(cp, "label")) {
823
strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
824
continue;
825
}
826
if (!strcmp(cp, "bytes/sector")) {
827
v = strtoul(tp, NULL, 10);
828
if (v == 0 || (v % DEV_BSIZE) != 0) {
829
fprintf(stderr,
830
"line %d: %s: bad sector size\n",
831
lineno, tp);
832
errors++;
833
} else
834
lp->d_secsize = v;
835
continue;
836
}
837
if (!strcmp(cp, "sectors/track")) {
838
v = strtoul(tp, NULL, 10);
839
#if (ULONG_MAX != 0xffffffffUL)
840
if (v == 0 || v > 0xffffffff)
841
#else
842
if (v == 0)
843
#endif
844
{
845
fprintf(stderr, "line %d: %s: bad %s\n",
846
lineno, tp, cp);
847
errors++;
848
} else
849
lp->d_nsectors = v;
850
continue;
851
}
852
if (!strcmp(cp, "sectors/cylinder")) {
853
v = strtoul(tp, NULL, 10);
854
if (v == 0) {
855
fprintf(stderr, "line %d: %s: bad %s\n",
856
lineno, tp, cp);
857
errors++;
858
} else
859
lp->d_secpercyl = v;
860
continue;
861
}
862
if (!strcmp(cp, "tracks/cylinder")) {
863
v = strtoul(tp, NULL, 10);
864
if (v == 0) {
865
fprintf(stderr, "line %d: %s: bad %s\n",
866
lineno, tp, cp);
867
errors++;
868
} else
869
lp->d_ntracks = v;
870
continue;
871
}
872
if (!strcmp(cp, "cylinders")) {
873
v = strtoul(tp, NULL, 10);
874
if (v == 0) {
875
fprintf(stderr, "line %d: %s: bad %s\n",
876
lineno, tp, cp);
877
errors++;
878
} else
879
lp->d_ncylinders = v;
880
continue;
881
}
882
if (!strcmp(cp, "sectors/unit")) {
883
v = strtoul(tp, NULL, 10);
884
if (v == 0) {
885
fprintf(stderr, "line %d: %s: bad %s\n",
886
lineno, tp, cp);
887
errors++;
888
} else
889
lp->d_secperunit = v;
890
continue;
891
}
892
if (!strcmp(cp, "rpm")) {
893
v = strtoul(tp, NULL, 10);
894
if (v == 0 || v > USHRT_MAX) {
895
fprintf(stderr, "line %d: %s: bad %s\n",
896
lineno, tp, cp);
897
errors++;
898
} else
899
lp->d_rpm = v;
900
continue;
901
}
902
if (!strcmp(cp, "interleave")) {
903
v = strtoul(tp, NULL, 10);
904
if (v == 0 || v > USHRT_MAX) {
905
fprintf(stderr, "line %d: %s: bad %s\n",
906
lineno, tp, cp);
907
errors++;
908
} else
909
lp->d_interleave = v;
910
continue;
911
}
912
if (!strcmp(cp, "trackskew")) {
913
v = strtoul(tp, NULL, 10);
914
if (v > USHRT_MAX) {
915
fprintf(stderr, "line %d: %s: bad %s\n",
916
lineno, tp, cp);
917
errors++;
918
} else
919
lp->d_trackskew = v;
920
continue;
921
}
922
if (!strcmp(cp, "cylinderskew")) {
923
v = strtoul(tp, NULL, 10);
924
if (v > USHRT_MAX) {
925
fprintf(stderr, "line %d: %s: bad %s\n",
926
lineno, tp, cp);
927
errors++;
928
} else
929
lp->d_cylskew = v;
930
continue;
931
}
932
if (!strcmp(cp, "headswitch")) {
933
v = strtoul(tp, NULL, 10);
934
lp->d_headswitch = v;
935
continue;
936
}
937
if (!strcmp(cp, "track-to-track seek")) {
938
v = strtoul(tp, NULL, 10);
939
lp->d_trkseek = v;
940
continue;
941
}
942
/* the ':' was removed above */
943
if (*cp < 'a' || *cp > MAX_PART || cp[1] != '\0') {
944
fprintf(stderr,
945
"line %d: %s: Unknown disklabel field\n", lineno,
946
cp);
947
errors++;
948
continue;
949
}
950
951
/* Process a partition specification line. */
952
part = *cp - 'a';
953
if (part >= lp->d_npartitions) {
954
fprintf(stderr,
955
"line %d: partition name out of range a-%c: %s\n",
956
lineno, 'a' + lp->d_npartitions - 1, cp);
957
errors++;
958
continue;
959
}
960
part_set[part] = 1;
961
962
if (getasciipartspec(tp, lp, part, lineno) != 0) {
963
errors++;
964
break;
965
}
966
}
967
errors += checklabel(lp);
968
return (errors == 0);
969
}
970
971
#define NXTNUM(n) do { \
972
if (tp == NULL) { \
973
fprintf(stderr, "line %d: too few numeric fields\n", lineno); \
974
return (1); \
975
} else { \
976
cp = tp, tp = word(cp); \
977
(n) = strtoul(cp, NULL, 10); \
978
} \
979
} while (0)
980
981
/* retain 1 character following number */
982
#define NXTWORD(w,n) do { \
983
if (tp == NULL) { \
984
fprintf(stderr, "line %d: too few numeric fields\n", lineno); \
985
return (1); \
986
} else { \
987
char *tmp; \
988
cp = tp, tp = word(cp); \
989
(n) = strtoul(cp, &tmp, 10); \
990
if (tmp) (w) = *tmp; \
991
} \
992
} while (0)
993
994
/*
995
* Read a partition line into partition `part' in the specified disklabel.
996
* Return 0 on success, 1 on failure.
997
*/
998
static int
999
getasciipartspec(char *tp, struct disklabel *lp, int part, int lineno)
1000
{
1001
struct partition *pp;
1002
char *cp, *endp;
1003
const char **cpp;
1004
u_long v;
1005
1006
pp = &lp->d_partitions[part];
1007
cp = NULL;
1008
1009
v = 0;
1010
NXTWORD(part_size_type[part],v);
1011
if (v == 0 && part_size_type[part] != '*') {
1012
fprintf(stderr,
1013
"line %d: %s: bad partition size\n", lineno, cp);
1014
return (1);
1015
}
1016
pp->p_size = v;
1017
1018
v = 0;
1019
NXTWORD(part_offset_type[part],v);
1020
if (v == 0 && part_offset_type[part] != '*' &&
1021
part_offset_type[part] != '\0') {
1022
fprintf(stderr,
1023
"line %d: %s: bad partition offset\n", lineno, cp);
1024
return (1);
1025
}
1026
pp->p_offset = v;
1027
if (tp == NULL) {
1028
fprintf(stderr, "line %d: missing file system type\n", lineno);
1029
return (1);
1030
}
1031
cp = tp, tp = word(cp);
1032
for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++)
1033
if (*cpp && !strcmp(*cpp, cp))
1034
break;
1035
if (*cpp != NULL) {
1036
pp->p_fstype = cpp - fstypenames;
1037
} else {
1038
if (isdigit(*cp)) {
1039
errno = 0;
1040
v = strtoul(cp, &endp, 10);
1041
if (errno != 0 || *endp != '\0')
1042
v = FSMAXTYPES;
1043
} else
1044
v = FSMAXTYPES;
1045
if (v >= FSMAXTYPES) {
1046
fprintf(stderr,
1047
"line %d: Warning, unknown file system type %s\n",
1048
lineno, cp);
1049
v = FS_UNUSED;
1050
}
1051
pp->p_fstype = v;
1052
}
1053
1054
switch (pp->p_fstype) {
1055
case FS_UNUSED:
1056
case FS_BSDFFS:
1057
case FS_BSDLFS:
1058
/* accept defaults for fsize/frag/cpg */
1059
if (tp) {
1060
NXTNUM(pp->p_fsize);
1061
if (pp->p_fsize == 0)
1062
break;
1063
NXTNUM(v);
1064
pp->p_frag = v / pp->p_fsize;
1065
if (tp != NULL)
1066
NXTNUM(pp->p_cpg);
1067
}
1068
/* else default to 0's */
1069
break;
1070
default:
1071
break;
1072
}
1073
return (0);
1074
}
1075
1076
/*
1077
* Check disklabel for errors and fill in
1078
* derived fields according to supplied values.
1079
*/
1080
static int
1081
checklabel(struct disklabel *lp)
1082
{
1083
struct partition *pp;
1084
int i, errors = 0;
1085
char part;
1086
u_long base_offset, needed, total_percent, current_offset;
1087
long free_space;
1088
int seen_default_offset;
1089
int hog_part;
1090
int j;
1091
struct partition *pp2;
1092
1093
if (lp == NULL)
1094
lp = &lab;
1095
1096
if (allfields) {
1097
1098
if (lp->d_secsize == 0) {
1099
fprintf(stderr, "sector size 0\n");
1100
return (1);
1101
}
1102
if (lp->d_nsectors == 0) {
1103
fprintf(stderr, "sectors/track 0\n");
1104
return (1);
1105
}
1106
if (lp->d_ntracks == 0) {
1107
fprintf(stderr, "tracks/cylinder 0\n");
1108
return (1);
1109
}
1110
if (lp->d_ncylinders == 0) {
1111
fprintf(stderr, "cylinders/unit 0\n");
1112
errors++;
1113
}
1114
if (lp->d_rpm == 0)
1115
warnx("revolutions/minute 0");
1116
if (lp->d_secpercyl == 0)
1117
lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
1118
if (lp->d_secperunit == 0)
1119
lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
1120
if (lp->d_bbsize == 0) {
1121
fprintf(stderr, "boot block size 0\n");
1122
errors++;
1123
} else if (lp->d_bbsize % lp->d_secsize)
1124
warnx("boot block size %% sector-size != 0");
1125
if (lp->d_npartitions > MAXPARTITIONS) {
1126
warnx("number of partitions (%lu) > MAXPARTITIONS (%d)",
1127
(u_long)lp->d_npartitions, MAXPARTITIONS);
1128
errors++;
1129
}
1130
if (lp->d_npartitions < DEFPARTITIONS) {
1131
warnx("number of partitions (%lu) < DEFPARTITIONS (%d)",
1132
(u_long)lp->d_npartitions, DEFPARTITIONS);
1133
errors++;
1134
}
1135
} else {
1136
struct disklabel *vl;
1137
1138
vl = getvirginlabel();
1139
if (lp->d_secsize == 0)
1140
lp->d_secsize = vl->d_secsize;
1141
if (lp->d_nsectors == 0)
1142
lp->d_nsectors = vl->d_nsectors;
1143
if (lp->d_ntracks == 0)
1144
lp->d_ntracks = vl->d_ntracks;
1145
if (lp->d_ncylinders == 0)
1146
lp->d_ncylinders = vl->d_ncylinders;
1147
if (lp->d_rpm == 0)
1148
lp->d_rpm = vl->d_rpm;
1149
if (lp->d_interleave == 0)
1150
lp->d_interleave = vl->d_interleave;
1151
if (lp->d_secpercyl == 0)
1152
lp->d_secpercyl = vl->d_secpercyl;
1153
if (lp->d_secperunit == 0 ||
1154
lp->d_secperunit > vl->d_secperunit)
1155
lp->d_secperunit = vl->d_secperunit;
1156
if (lp->d_bbsize == 0)
1157
lp->d_bbsize = vl->d_bbsize;
1158
if (lp->d_npartitions < DEFPARTITIONS ||
1159
lp->d_npartitions > MAXPARTITIONS)
1160
lp->d_npartitions = vl->d_npartitions;
1161
}
1162
1163
1164
/* first allocate space to the partitions, then offsets */
1165
total_percent = 0; /* in percent */
1166
hog_part = -1;
1167
/* find all fixed partitions */
1168
for (i = 0; i < lp->d_npartitions; i++) {
1169
pp = &lp->d_partitions[i];
1170
if (part_set[i]) {
1171
if (part_size_type[i] == '*') {
1172
if (i == RAW_PART) {
1173
pp->p_size = lp->d_secperunit;
1174
} else {
1175
if (hog_part != -1)
1176
warnx("Too many '*' partitions (%c and %c)",
1177
hog_part + 'a',i + 'a');
1178
else
1179
hog_part = i;
1180
}
1181
} else {
1182
off_t size;
1183
1184
size = pp->p_size;
1185
switch (part_size_type[i]) {
1186
case '%':
1187
total_percent += size;
1188
break;
1189
case 't':
1190
case 'T':
1191
size *= 1024ULL;
1192
/* FALLTHROUGH */
1193
case 'g':
1194
case 'G':
1195
size *= 1024ULL;
1196
/* FALLTHROUGH */
1197
case 'm':
1198
case 'M':
1199
size *= 1024ULL;
1200
/* FALLTHROUGH */
1201
case 'k':
1202
case 'K':
1203
size *= 1024ULL;
1204
break;
1205
case '\0':
1206
break;
1207
default:
1208
warnx("unknown multiplier suffix '%c' for partition %c (should be K, M, G or T)",
1209
part_size_type[i], i + 'a');
1210
break;
1211
}
1212
/* don't count %'s yet */
1213
if (part_size_type[i] != '%') {
1214
/*
1215
* for all not in sectors, convert to
1216
* sectors
1217
*/
1218
if (part_size_type[i] != '\0') {
1219
if (size % lp->d_secsize != 0)
1220
warnx("partition %c not an integer number of sectors",
1221
i + 'a');
1222
size /= lp->d_secsize;
1223
pp->p_size = size;
1224
}
1225
}
1226
}
1227
}
1228
}
1229
1230
/* Find out the total free space, excluding the boot block area. */
1231
base_offset = BBSIZE / secsize;
1232
free_space = 0;
1233
for (i = 0; i < lp->d_npartitions; i++) {
1234
pp = &lp->d_partitions[i];
1235
if (!part_set[i] || i == RAW_PART ||
1236
part_size_type[i] == '%' || part_size_type[i] == '*')
1237
continue;
1238
if (pp->p_offset > base_offset)
1239
free_space += pp->p_offset - base_offset;
1240
if (pp->p_offset + pp->p_size > base_offset)
1241
base_offset = pp->p_offset + pp->p_size;
1242
}
1243
if (base_offset < lp->d_secperunit)
1244
free_space += lp->d_secperunit - base_offset;
1245
1246
/* handle % partitions - note %'s don't need to add up to 100! */
1247
if (total_percent != 0) {
1248
if (total_percent > 100) {
1249
fprintf(stderr,"total percentage %lu is greater than 100\n",
1250
total_percent);
1251
errors++;
1252
}
1253
1254
if (free_space > 0) {
1255
for (i = 0; i < lp->d_npartitions; i++) {
1256
pp = &lp->d_partitions[i];
1257
if (part_set[i] && part_size_type[i] == '%') {
1258
/* careful of overflows! and integer roundoff */
1259
pp->p_size = ((double)pp->p_size/100) * free_space;
1260
1261
/* FIX we can lose a sector or so due to roundoff per
1262
partition. A more complex algorithm could avoid that */
1263
}
1264
}
1265
} else {
1266
fprintf(stderr,
1267
"%ld sectors available to give to '*' and '%%' partitions\n",
1268
free_space);
1269
errors++;
1270
/* fix? set all % partitions to size 0? */
1271
}
1272
}
1273
/* give anything remaining to the hog partition */
1274
if (hog_part != -1) {
1275
/*
1276
* Find the range of offsets usable by '*' partitions around
1277
* the hog partition and how much space they need.
1278
*/
1279
needed = 0;
1280
base_offset = BBSIZE / secsize;
1281
for (i = hog_part - 1; i >= 0; i--) {
1282
pp = &lp->d_partitions[i];
1283
if (!part_set[i] || i == RAW_PART)
1284
continue;
1285
if (part_offset_type[i] == '*') {
1286
needed += pp->p_size;
1287
continue;
1288
}
1289
base_offset = pp->p_offset + pp->p_size;
1290
break;
1291
}
1292
current_offset = lp->d_secperunit;
1293
for (i = lp->d_npartitions - 1; i > hog_part; i--) {
1294
pp = &lp->d_partitions[i];
1295
if (!part_set[i] || i == RAW_PART)
1296
continue;
1297
if (part_offset_type[i] == '*') {
1298
needed += pp->p_size;
1299
continue;
1300
}
1301
current_offset = pp->p_offset;
1302
}
1303
1304
if (current_offset - base_offset <= needed) {
1305
fprintf(stderr, "Cannot find space for partition %c\n",
1306
hog_part + 'a');
1307
fprintf(stderr,
1308
"Need more than %lu sectors between %lu and %lu\n",
1309
needed, base_offset, current_offset);
1310
errors++;
1311
lp->d_partitions[hog_part].p_size = 0;
1312
} else {
1313
lp->d_partitions[hog_part].p_size = current_offset -
1314
base_offset - needed;
1315
}
1316
}
1317
1318
/* Now set the offsets for each partition */
1319
current_offset = BBSIZE / secsize; /* in sectors */
1320
seen_default_offset = 0;
1321
for (i = 0; i < lp->d_npartitions; i++) {
1322
part = 'a' + i;
1323
pp = &lp->d_partitions[i];
1324
if (part_set[i]) {
1325
if (part_offset_type[i] == '*') {
1326
if (i == RAW_PART) {
1327
pp->p_offset = 0;
1328
} else {
1329
pp->p_offset = current_offset;
1330
seen_default_offset = 1;
1331
}
1332
} else {
1333
/* allow them to be out of order for old-style tables */
1334
if (pp->p_offset < current_offset &&
1335
seen_default_offset && i != RAW_PART &&
1336
pp->p_fstype != FS_VINUM) {
1337
fprintf(stderr,
1338
"Offset %ld for partition %c overlaps previous partition which ends at %lu\n",
1339
(long)pp->p_offset,i+'a',current_offset);
1340
fprintf(stderr,
1341
"Labels with any *'s for offset must be in ascending order by sector\n");
1342
errors++;
1343
} else if (pp->p_offset != current_offset &&
1344
i != RAW_PART && seen_default_offset) {
1345
/*
1346
* this may give unneeded warnings if
1347
* partitions are out-of-order
1348
*/
1349
warnx(
1350
"Offset %ld for partition %c doesn't match expected value %ld",
1351
(long)pp->p_offset, i + 'a', current_offset);
1352
}
1353
}
1354
if (i != RAW_PART)
1355
current_offset = pp->p_offset + pp->p_size;
1356
}
1357
}
1358
1359
for (i = 0; i < lp->d_npartitions; i++) {
1360
part = 'a' + i;
1361
pp = &lp->d_partitions[i];
1362
if (pp->p_size == 0 && pp->p_offset != 0)
1363
warnx("partition %c: size 0, but offset %lu",
1364
part, (u_long)pp->p_offset);
1365
#ifdef notdef
1366
if (pp->p_size % lp->d_secpercyl)
1367
warnx("partition %c: size %% cylinder-size != 0",
1368
part);
1369
if (pp->p_offset % lp->d_secpercyl)
1370
warnx("partition %c: offset %% cylinder-size != 0",
1371
part);
1372
#endif
1373
if (pp->p_offset > lp->d_secperunit) {
1374
fprintf(stderr,
1375
"partition %c: offset past end of unit\n", part);
1376
errors++;
1377
}
1378
if (pp->p_offset + pp->p_size > lp->d_secperunit) {
1379
fprintf(stderr,
1380
"partition %c: partition extends past end of unit\n",
1381
part);
1382
errors++;
1383
}
1384
if (i == RAW_PART) {
1385
if (pp->p_fstype != FS_UNUSED)
1386
warnx("partition %c is not marked as unused!",part);
1387
if (pp->p_offset != 0)
1388
warnx("partition %c doesn't start at 0!",part);
1389
if (pp->p_size != lp->d_secperunit)
1390
warnx("partition %c doesn't cover the whole unit!",part);
1391
1392
if ((pp->p_fstype != FS_UNUSED) || (pp->p_offset != 0) ||
1393
(pp->p_size != lp->d_secperunit)) {
1394
warnx("An incorrect partition %c may cause problems for "
1395
"standard system utilities",part);
1396
}
1397
}
1398
1399
/* check for overlaps */
1400
/* this will check for all possible overlaps once and only once */
1401
for (j = 0; j < i; j++) {
1402
pp2 = &lp->d_partitions[j];
1403
if (j != RAW_PART && i != RAW_PART &&
1404
pp->p_fstype != FS_VINUM &&
1405
pp2->p_fstype != FS_VINUM &&
1406
part_set[i] && part_set[j]) {
1407
if (pp2->p_offset < pp->p_offset + pp->p_size &&
1408
(pp2->p_offset + pp2->p_size > pp->p_offset ||
1409
pp2->p_offset >= pp->p_offset)) {
1410
fprintf(stderr,"partitions %c and %c overlap!\n",
1411
j + 'a', i + 'a');
1412
errors++;
1413
}
1414
}
1415
}
1416
}
1417
for (; i < lp->d_npartitions; i++) {
1418
part = 'a' + i;
1419
pp = &lp->d_partitions[i];
1420
if (pp->p_size || pp->p_offset)
1421
warnx("unused partition %c: size %d offset %lu",
1422
'a' + i, pp->p_size, (u_long)pp->p_offset);
1423
}
1424
return (errors);
1425
}
1426
1427
/*
1428
* When operating on a "virgin" disk, try getting an initial label
1429
* from the associated device driver. This might work for all device
1430
* drivers that are able to fetch some initial device parameters
1431
* without even having access to a (BSD) disklabel, like SCSI disks,
1432
* most IDE drives, or vn devices.
1433
*
1434
* The device name must be given in its "canonical" form.
1435
*/
1436
static struct disklabel *
1437
getvirginlabel(void)
1438
{
1439
static struct disklabel loclab;
1440
struct partition *dp;
1441
int f;
1442
u_int u;
1443
1444
if ((f = open(specname, O_RDONLY)) == -1) {
1445
warn("cannot open %s", specname);
1446
return (NULL);
1447
}
1448
1449
if (is_file)
1450
get_file_parms(f);
1451
else {
1452
mediasize = g_mediasize(f);
1453
secsize = g_sectorsize(f);
1454
if (secsize < 0 || mediasize < 0) {
1455
close (f);
1456
return (NULL);
1457
}
1458
}
1459
memset(&loclab, 0, sizeof loclab);
1460
loclab.d_magic = DISKMAGIC;
1461
loclab.d_magic2 = DISKMAGIC;
1462
loclab.d_secsize = secsize;
1463
loclab.d_secperunit = mediasize / secsize;
1464
1465
/*
1466
* Nobody in these enlightened days uses the CHS geometry for
1467
* anything, but nonetheless try to get it right. If we fail
1468
* to get any good ideas from the device, construct something
1469
* which is IBM-PC friendly.
1470
*/
1471
if (ioctl(f, DIOCGFWSECTORS, &u) == 0)
1472
loclab.d_nsectors = u;
1473
else
1474
loclab.d_nsectors = 63;
1475
if (ioctl(f, DIOCGFWHEADS, &u) == 0)
1476
loclab.d_ntracks = u;
1477
else if (loclab.d_secperunit <= 63*1*1024)
1478
loclab.d_ntracks = 1;
1479
else if (loclab.d_secperunit <= 63*16*1024)
1480
loclab.d_ntracks = 16;
1481
else
1482
loclab.d_ntracks = 255;
1483
loclab.d_secpercyl = loclab.d_ntracks * loclab.d_nsectors;
1484
loclab.d_ncylinders = loclab.d_secperunit / loclab.d_secpercyl;
1485
loclab.d_npartitions = DEFPARTITIONS;
1486
1487
/* Various (unneeded) compat stuff */
1488
loclab.d_rpm = 3600;
1489
loclab.d_bbsize = BBSIZE;
1490
loclab.d_interleave = 1;
1491
strncpy(loclab.d_typename, "amnesiac",
1492
sizeof(loclab.d_typename));
1493
1494
dp = &loclab.d_partitions[RAW_PART];
1495
dp->p_size = loclab.d_secperunit;
1496
loclab.d_checksum = dkcksum(&loclab);
1497
close (f);
1498
return (&loclab);
1499
}
1500
1501
static void
1502
usage(void)
1503
{
1504
1505
fprintf(stderr,
1506
"%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
1507
"usage: bsdlabel disk",
1508
"\t\t(to read label)",
1509
" bsdlabel -w [-n] [-m machine] disk [type]",
1510
"\t\t(to write label with existing boot program)",
1511
" bsdlabel -e [-n] [-m machine] disk",
1512
"\t\t(to edit label)",
1513
" bsdlabel -R [-n] [-m machine] disk protofile",
1514
"\t\t(to restore label with existing boot program)",
1515
" bsdlabel -B [-b boot] [-m machine] disk",
1516
"\t\t(to install boot program with existing on-disk label)",
1517
" bsdlabel -w -B [-n] [-b boot] [-m machine] disk [type]",
1518
"\t\t(to write label and install boot program)",
1519
" bsdlabel -R -B [-n] [-b boot] [-m machine] disk protofile",
1520
"\t\t(to restore label and install boot program)"
1521
);
1522
exit(1);
1523
}
1524
1525