]> git.ipfire.org Git - thirdparty/util-linux.git/blob - fdisk/fdiskbsdlabel.c
Imported from util-linux-2.12 tarball.
[thirdparty/util-linux.git] / fdisk / fdiskbsdlabel.c
1 /*
2 NetBSD disklabel editor for Linux fdisk
3 Written by Bernhard Fastenrath (fasten@informatik.uni-bonn.de)
4 with code from the NetBSD disklabel command:
5
6 Copyright (c) 1987, 1988 Regents of the University of California.
7 All rights reserved.
8
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
11 are met:
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
17 3. All advertising materials mentioning features or use of this software
18 must display the following acknowledgement:
19 This product includes software developed by the University of
20 California, Berkeley and its contributors.
21 4. Neither the name of the University nor the names of its contributors
22 may be used to endorse or promote products derived from this software
23 without specific prior written permission.
24
25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 SUCH DAMAGE.
36
37 Changes:
38 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
39
40 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
41 support for OSF/1 disklabels on Alpha.
42 Also fixed unaligned accesses in alpha_bootblock_checksum()
43 */
44
45 #include <unistd.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <fcntl.h>
50 #include <ctype.h>
51 #include <setjmp.h>
52 #include <errno.h>
53 #include "nls.h"
54
55 #include <sys/ioctl.h>
56 #include <sys/param.h>
57
58 #include "common.h"
59 #include "fdisk.h"
60 #define FREEBSD_PARTITION 0xa5
61 #define NETBSD_PARTITION 0xa9
62 #define DKTYPENAMES
63 #include "fdiskbsdlabel.h"
64
65 static void xbsd_delete_part (void);
66 static void xbsd_new_part (void);
67 static void xbsd_write_disklabel (void);
68 static int xbsd_create_disklabel (void);
69 static void xbsd_edit_disklabel (void);
70 static void xbsd_write_bootstrap (void);
71 static void xbsd_change_fstype (void);
72 static int xbsd_get_part_index (int max);
73 static int xbsd_check_new_partition (int *i);
74 static void xbsd_list_types (void);
75 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
76 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
77 int pindex);
78 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
79 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
80 static void sync_disks (void);
81
82 #if defined (__alpha__)
83 void alpha_bootblock_checksum (char *boot);
84 #endif
85
86 #if !defined (__alpha__)
87 static int xbsd_translate_fstype (int linux_type);
88 static void xbsd_link_part (void);
89 static struct partition *xbsd_part;
90 static int xbsd_part_index;
91 #endif
92
93 #if defined (__alpha__)
94 /* We access this through a u_int64_t * when checksumming */
95 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
96 #else
97 static char disklabelbuffer[BSD_BBSIZE];
98 #endif
99
100 static struct xbsd_disklabel xbsd_dlabel;
101
102 #define bsd_cround(n) \
103 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
104
105 /*
106 * Test whether the whole disk has BSD disk label magic.
107 *
108 * Note: often reformatting with DOS-type label leaves the BSD magic,
109 * so this does not mean that there is a BSD disk label.
110 */
111 int
112 check_osf_label(void) {
113 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
114 return 0;
115 return 1;
116 }
117
118 int
119 btrydev (char * dev) {
120 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
121 return -1;
122 printf(_("\nBSD label for device: %s\n"), dev);
123 xbsd_print_disklabel (0);
124 return 0;
125 }
126
127 static void
128 bmenu (void) {
129 puts (_("Command action"));
130 puts (_(" d delete a BSD partition"));
131 puts (_(" e edit drive data"));
132 puts (_(" i install bootstrap"));
133 puts (_(" l list known filesystem types"));
134 puts (_(" m print this menu"));
135 puts (_(" n add a new BSD partition"));
136 puts (_(" p print BSD partition table"));
137 puts (_(" q quit without saving changes"));
138 puts (_(" r return to main menu"));
139 puts (_(" s show complete disklabel"));
140 puts (_(" t change a partition's filesystem id"));
141 puts (_(" u change units (cylinders/sectors)"));
142 puts (_(" w write disklabel to disk"));
143 #if !defined (__alpha__)
144 puts (_(" x link BSD partition to non-BSD partition"));
145 #endif
146 }
147
148 #if !defined (__alpha__)
149 static int
150 hidden(int type) {
151 return type ^ 0x10;
152 }
153
154 static int
155 is_bsd_partition_type(int type) {
156 return (type == FREEBSD_PARTITION ||
157 type == hidden(FREEBSD_PARTITION) ||
158 type == NETBSD_PARTITION ||
159 type == hidden(NETBSD_PARTITION));
160 }
161 #endif
162
163 void
164 bselect (void) {
165 #if !defined (__alpha__)
166 int t, ss;
167 struct partition *p;
168
169 for (t=0; t<4; t++) {
170 p = get_part_table(t);
171 if (p && is_bsd_partition_type(p->sys_ind)) {
172 xbsd_part = p;
173 xbsd_part_index = t;
174 ss = get_start_sect(xbsd_part);
175 if (ss == 0) {
176 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
177 partname(disk_device, t+1, 0));
178 return;
179 }
180 printf (_("Reading disklabel of %s at sector %d.\n"),
181 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
182 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
183 if (xbsd_create_disklabel () == 0)
184 return;
185 break;
186 }
187 }
188
189 if (t == 4) {
190 printf (_("There is no *BSD partition on %s.\n"), disk_device);
191 return;
192 }
193
194 #elif defined (__alpha__)
195
196 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
197 if (xbsd_create_disklabel () == 0)
198 exit ( EXIT_SUCCESS );
199
200 #endif
201
202 while (1) {
203 putchar ('\n');
204 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
205 case 'd':
206 xbsd_delete_part ();
207 break;
208 case 'e':
209 xbsd_edit_disklabel ();
210 break;
211 case 'i':
212 xbsd_write_bootstrap ();
213 break;
214 case 'l':
215 xbsd_list_types ();
216 break;
217 case 'n':
218 xbsd_new_part ();
219 break;
220 case 'p':
221 xbsd_print_disklabel (0);
222 break;
223 case 'q':
224 close (fd);
225 exit ( EXIT_SUCCESS );
226 case 'r':
227 return;
228 case 's':
229 xbsd_print_disklabel (1);
230 break;
231 case 't':
232 xbsd_change_fstype ();
233 break;
234 case 'u':
235 change_units();
236 break;
237 case 'w':
238 xbsd_write_disklabel ();
239 break;
240 #if !defined (__alpha__)
241 case 'x':
242 xbsd_link_part ();
243 break;
244 #endif
245 default:
246 bmenu ();
247 break;
248 }
249 }
250 }
251
252 static void
253 xbsd_delete_part (void)
254 {
255 int i;
256
257 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
258 xbsd_dlabel.d_partitions[i].p_size = 0;
259 xbsd_dlabel.d_partitions[i].p_offset = 0;
260 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
261 if (xbsd_dlabel.d_npartitions == i + 1)
262 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
263 xbsd_dlabel.d_npartitions--;
264 }
265
266 static void
267 xbsd_new_part (void)
268 {
269 unsigned int begin, end;
270 char mesg[256];
271 int i;
272
273 if (!xbsd_check_new_partition (&i))
274 return;
275
276 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
277 begin = get_start_sect(xbsd_part);
278 end = begin + get_nr_sects(xbsd_part) - 1;
279 #else
280 begin = 0;
281 end = xbsd_dlabel.d_secperunit - 1;
282 #endif
283
284 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
285 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
286 0, mesg);
287
288 if (display_in_cyl_units)
289 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
290
291 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
292 str_units(SINGULAR));
293 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
294 bsd_cround (begin), mesg);
295
296 if (display_in_cyl_units)
297 end = end * xbsd_dlabel.d_secpercyl - 1;
298
299 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
300 xbsd_dlabel.d_partitions[i].p_offset = begin;
301 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
302 }
303
304 void
305 xbsd_print_disklabel (int show_all) {
306 struct xbsd_disklabel *lp = &xbsd_dlabel;
307 struct xbsd_partition *pp;
308 FILE *f = stdout;
309 int i, j;
310
311 if (show_all) {
312 #if defined (__alpha__)
313 fprintf(f, "# %s:\n", disk_device);
314 #else
315 fprintf(f, "# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
316 #endif
317 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
318 fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]);
319 else
320 fprintf(f, _("type: %d\n"), lp->d_type);
321 fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
322 fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
323 fprintf(f, _("flags:"));
324 if (lp->d_flags & BSD_D_REMOVABLE)
325 fprintf(f, _(" removable"));
326 if (lp->d_flags & BSD_D_ECC)
327 fprintf(f, _(" ecc"));
328 if (lp->d_flags & BSD_D_BADSECT)
329 fprintf(f, _(" badsect"));
330 fprintf(f, "\n");
331 /* On various machines the fields of *lp are short/int/long */
332 /* In order to avoid problems, we cast them all to long. */
333 fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize);
334 fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors);
335 fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
336 fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
337 fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders);
338 fprintf(f, _("rpm: %d\n"), lp->d_rpm);
339 fprintf(f, _("interleave: %d\n"), lp->d_interleave);
340 fprintf(f, _("trackskew: %d\n"), lp->d_trackskew);
341 fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew);
342 fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"),
343 (long) lp->d_headswitch);
344 fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"),
345 (long) lp->d_trkseek);
346 fprintf(f, _("drivedata: "));
347 for (i = NDDATA - 1; i >= 0; i--)
348 if (lp->d_drivedata[i])
349 break;
350 if (i < 0)
351 i = 0;
352 for (j = 0; j <= i; j++)
353 fprintf(f, "%ld ", (long) lp->d_drivedata[j]);
354 }
355 fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions);
356 fprintf (f, _("# start end size fstype [fsize bsize cpg]\n"));
357 pp = lp->d_partitions;
358 for (i = 0; i < lp->d_npartitions; i++, pp++) {
359 if (pp->p_size) {
360 if (display_in_cyl_units && lp->d_secpercyl) {
361 fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ",
362 'a' + i,
363 (long) pp->p_offset / lp->d_secpercyl + 1,
364 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
365 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
366 / lp->d_secpercyl,
367 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
368 (long) pp->p_size / lp->d_secpercyl,
369 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
370 } else {
371 fprintf(f, " %c: %8ld %8ld %8ld ",
372 'a' + i,
373 (long) pp->p_offset,
374 (long) pp->p_offset + pp->p_size - 1,
375 (long) pp->p_size);
376 }
377 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
378 fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name);
379 else
380 fprintf(f, "%8x", pp->p_fstype);
381 switch (pp->p_fstype) {
382 case BSD_FS_UNUSED:
383 fprintf(f, " %5ld %5ld %5.5s ",
384 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
385 break;
386
387 case BSD_FS_BSDFFS:
388 fprintf(f, " %5ld %5ld %5d ",
389 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
390 pp->p_cpg);
391 break;
392
393 default:
394 fprintf(f, "%22.22s", "");
395 break;
396 }
397 fprintf(f, "\n");
398 }
399 }
400 }
401
402 static void
403 xbsd_write_disklabel (void) {
404 #if defined (__alpha__)
405 printf (_("Writing disklabel to %s.\n"), disk_device);
406 xbsd_writelabel (NULL, &xbsd_dlabel);
407 #else
408 printf (_("Writing disklabel to %s.\n"),
409 partname(disk_device, xbsd_part_index+1, 0));
410 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
411 #endif
412 reread_partition_table(0); /* no exit yet */
413 }
414
415 static int
416 xbsd_create_disklabel (void) {
417 char c;
418
419 #if defined (__alpha__)
420 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
421 #else
422 fprintf (stderr, _("%s contains no disklabel.\n"),
423 partname(disk_device, xbsd_part_index+1, 0));
424 #endif
425
426 while (1) {
427 c = read_char (_("Do you want to create a disklabel? (y/n) "));
428 if (tolower(c) == 'y') {
429 if (xbsd_initlabel (
430 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
431 defined (__s390__) || defined (__s390x__)
432 NULL, &xbsd_dlabel, 0
433 #else
434 xbsd_part, &xbsd_dlabel, xbsd_part_index
435 #endif
436 ) == 1) {
437 xbsd_print_disklabel (1);
438 return 1;
439 } else
440 return 0;
441 } else if (c == 'n')
442 return 0;
443 }
444 }
445
446 static int
447 edit_int (int def, char *mesg)
448 {
449 do {
450 fputs (mesg, stdout);
451 printf (" (%d): ", def);
452 if (!read_line ())
453 return def;
454 }
455 while (!isdigit (*line_ptr));
456 return atoi (line_ptr);
457 }
458
459 static void
460 xbsd_edit_disklabel (void)
461 {
462 struct xbsd_disklabel *d;
463
464 d = &xbsd_dlabel;
465
466 #if defined (__alpha__) || defined (__ia64__)
467 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
468 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
469 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
470 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
471 #endif
472
473 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
474 while (1)
475 {
476 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
477 _("sectors/cylinder"));
478 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
479 break;
480
481 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
482 }
483 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
484 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
485 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
486 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
487 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
488 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
489
490 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
491 }
492
493 static int
494 xbsd_get_bootstrap (char *path, void *ptr, int size)
495 {
496 int fd;
497
498 if ((fd = open (path, O_RDONLY)) < 0)
499 {
500 perror (path);
501 return 0;
502 }
503 if (read (fd, ptr, size) < 0)
504 {
505 perror (path);
506 close (fd);
507 return 0;
508 }
509 printf (" ... %s\n", path);
510 close (fd);
511 return 1;
512 }
513
514 static void
515 xbsd_write_bootstrap (void)
516 {
517 char *bootdir = BSD_LINUX_BOOTDIR;
518 char path[MAXPATHLEN];
519 char *dkbasename;
520 struct xbsd_disklabel dl;
521 char *d, *p, *e;
522 int sector;
523
524 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
525 dkbasename = "sd";
526 else
527 dkbasename = "wd";
528
529 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
530 dkbasename, dkbasename, dkbasename);
531 if (read_line ()) {
532 line_ptr[strlen (line_ptr)-1] = '\0';
533 dkbasename = line_ptr;
534 }
535 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
536 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
537 return;
538
539 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
540 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
541 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
542
543 /* The disklabel will be overwritten by 0's from bootxx anyway */
544 bzero (d, sizeof (struct xbsd_disklabel));
545
546 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
547 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
548 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
549 return;
550
551 e = d + sizeof (struct xbsd_disklabel);
552 for (p=d; p < e; p++)
553 if (*p) {
554 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
555 exit ( EXIT_FAILURE );
556 }
557
558 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
559
560 #if defined (__powerpc__) || defined (__hppa__)
561 sector = 0;
562 #elif defined (__alpha__)
563 sector = 0;
564 alpha_bootblock_checksum (disklabelbuffer);
565 #else
566 sector = get_start_sect(xbsd_part);
567 #endif
568
569 if (ext2_llseek (fd, (long long) sector * SECTOR_SIZE, SEEK_SET) == -1)
570 fatal (unable_to_seek);
571 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
572 fatal (unable_to_write);
573
574 #if defined (__alpha__)
575 printf (_("Bootstrap installed on %s.\n"), disk_device);
576 #else
577 printf (_("Bootstrap installed on %s.\n"),
578 partname (disk_device, xbsd_part_index+1, 0));
579 #endif
580
581 sync_disks ();
582 }
583
584 static void
585 xbsd_change_fstype (void)
586 {
587 int i;
588
589 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
590 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
591 }
592
593 static int
594 xbsd_get_part_index (int max)
595 {
596 char prompt[256];
597 char l;
598
599 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
600 do
601 l = tolower (read_char (prompt));
602 while (l < 'a' || l > 'a' + max - 1);
603 return l - 'a';
604 }
605
606 static int
607 xbsd_check_new_partition (int *i) {
608
609 /* room for more? various BSD flavours have different maxima */
610 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
611 int t;
612
613 for (t = 0; t < BSD_MAXPARTITIONS; t++)
614 if (xbsd_dlabel.d_partitions[t].p_size == 0)
615 break;
616
617 if (t == BSD_MAXPARTITIONS) {
618 fprintf (stderr, _("The maximum number of partitions "
619 "has been created\n"));
620 return 0;
621 }
622 }
623
624 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
625
626 if (*i >= xbsd_dlabel.d_npartitions)
627 xbsd_dlabel.d_npartitions = (*i) + 1;
628
629 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
630 fprintf (stderr, _("This partition already exists.\n"));
631 return 0;
632 }
633
634 return 1;
635 }
636
637 static void
638 xbsd_list_types (void) {
639 list_types (xbsd_fstypes);
640 }
641
642 static u_short
643 xbsd_dkcksum (struct xbsd_disklabel *lp) {
644 u_short *start, *end;
645 u_short sum = 0;
646
647 start = (u_short *) lp;
648 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
649 while (start < end)
650 sum ^= *start++;
651 return sum;
652 }
653
654 static int
655 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
656 struct xbsd_partition *pp;
657 struct geom g;
658
659 get_geometry (fd, &g);
660 bzero (d, sizeof (struct xbsd_disklabel));
661
662 d -> d_magic = BSD_DISKMAGIC;
663
664 if (strncmp (disk_device, "/dev/sd", 7) == 0)
665 d -> d_type = BSD_DTYPE_SCSI;
666 else
667 d -> d_type = BSD_DTYPE_ST506;
668
669 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
670 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
671 #endif
672
673 #if !defined (__alpha__)
674 d -> d_flags = BSD_D_DOSPART;
675 #else
676 d -> d_flags = 0;
677 #endif
678 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
679 d -> d_nsectors = g.sectors; /* sectors/track */
680 d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */
681 d -> d_ncylinders = g.cylinders;
682 d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */
683 if (d -> d_secpercyl == 0)
684 d -> d_secpercyl = 1; /* avoid segfaults */
685 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
686
687 d -> d_rpm = 3600;
688 d -> d_interleave = 1;
689 d -> d_trackskew = 0;
690 d -> d_cylskew = 0;
691 d -> d_headswitch = 0;
692 d -> d_trkseek = 0;
693
694 d -> d_magic2 = BSD_DISKMAGIC;
695 d -> d_bbsize = BSD_BBSIZE;
696 d -> d_sbsize = BSD_SBSIZE;
697
698 #if !defined (__alpha__)
699 d -> d_npartitions = 4;
700 pp = &d -> d_partitions[2]; /* Partition C should be
701 the NetBSD partition */
702 pp -> p_offset = get_start_sect(p);
703 pp -> p_size = get_nr_sects(p);
704 pp -> p_fstype = BSD_FS_UNUSED;
705 pp = &d -> d_partitions[3]; /* Partition D should be
706 the whole disk */
707 pp -> p_offset = 0;
708 pp -> p_size = d -> d_secperunit;
709 pp -> p_fstype = BSD_FS_UNUSED;
710 #elif defined (__alpha__)
711 d -> d_npartitions = 3;
712 pp = &d -> d_partitions[2]; /* Partition C should be
713 the whole disk */
714 pp -> p_offset = 0;
715 pp -> p_size = d -> d_secperunit;
716 pp -> p_fstype = BSD_FS_UNUSED;
717 #endif
718
719 return 1;
720 }
721
722 /*
723 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
724 * If it has the right magic, return 1.
725 */
726 static int
727 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
728 {
729 int t, sector;
730
731 /* p is used only to get the starting sector */
732 #if !defined (__alpha__)
733 sector = (p ? get_start_sect(p) : 0);
734 #elif defined (__alpha__)
735 sector = 0;
736 #endif
737
738 if (ext2_llseek (fd, (long long) sector * SECTOR_SIZE, SEEK_SET) == -1)
739 fatal (unable_to_seek);
740 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
741 fatal (unable_to_read);
742
743 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
744 d, sizeof (struct xbsd_disklabel));
745
746 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
747 return 0;
748
749 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
750 d -> d_partitions[t].p_size = 0;
751 d -> d_partitions[t].p_offset = 0;
752 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
753 }
754
755 if (d -> d_npartitions > BSD_MAXPARTITIONS)
756 fprintf (stderr, _("Warning: too many partitions "
757 "(%d, maximum is %d).\n"),
758 d -> d_npartitions, BSD_MAXPARTITIONS);
759 return 1;
760 }
761
762 static int
763 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
764 {
765 unsigned int sector;
766
767 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
768 sector = get_start_sect(p) + BSD_LABELSECTOR;
769 #else
770 sector = BSD_LABELSECTOR;
771 #endif
772
773 d -> d_checksum = 0;
774 d -> d_checksum = xbsd_dkcksum (d);
775
776 /* This is necessary if we want to write the bootstrap later,
777 otherwise we'd write the old disklabel with the bootstrap.
778 */
779 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
780 sizeof (struct xbsd_disklabel));
781
782 #if defined (__alpha__) && BSD_LABELSECTOR == 0
783 alpha_bootblock_checksum (disklabelbuffer);
784 if (ext2_llseek (fd, (long long) 0, SEEK_SET) == -1)
785 fatal (unable_to_seek);
786 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
787 fatal (unable_to_write);
788 #else
789 if (ext2_llseek (fd, (long long) sector * SECTOR_SIZE + BSD_LABELOFFSET,
790 SEEK_SET) == -1)
791 fatal (unable_to_seek);
792 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
793 fatal (unable_to_write);
794 #endif
795
796 sync_disks ();
797
798 return 1;
799 }
800
801 static void
802 sync_disks (void)
803 {
804 printf (_("\nSyncing disks.\n"));
805 sync ();
806 sleep (4);
807 }
808
809 #if !defined (__alpha__)
810 static int
811 xbsd_translate_fstype (int linux_type)
812 {
813 switch (linux_type)
814 {
815 case 0x01: /* DOS 12-bit FAT */
816 case 0x04: /* DOS 16-bit <32M */
817 case 0x06: /* DOS 16-bit >=32M */
818 case 0xe1: /* DOS access */
819 case 0xe3: /* DOS R/O */
820 case 0xf2: /* DOS secondary */
821 return BSD_FS_MSDOS;
822 case 0x07: /* OS/2 HPFS */
823 return BSD_FS_HPFS;
824 default:
825 return BSD_FS_OTHER;
826 }
827 }
828
829 static void
830 xbsd_link_part (void)
831 {
832 int k, i;
833 struct partition *p;
834
835 k = get_partition (1, partitions);
836
837 if (!xbsd_check_new_partition (&i))
838 return;
839
840 p = get_part_table(k);
841
842 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
843 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
844 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
845 }
846 #endif
847
848 #if defined (__alpha__)
849
850 #if !defined(__GLIBC__)
851 typedef unsigned long long u_int64_t;
852 #endif
853
854 void
855 alpha_bootblock_checksum (char *boot)
856 {
857 u_int64_t *dp, sum;
858 int i;
859
860 dp = (u_int64_t *)boot;
861 sum = 0;
862 for (i = 0; i < 63; i++)
863 sum += dp[i];
864 dp[63] = sum;
865 }
866 #endif /* __alpha__ */