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:
6 Copyright (c) 1987, 1988 Regents of the University of California.
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions
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.
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
38 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
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()
55 #include <sys/param.h>
61 #include "fdiskbsdlabel.h"
64 static char *xbsd_dktypenames
[] = {
78 #define BSD_DKMAXTYPES (ARRAY_SIZE(xbsd_dktypenames) - 1)
80 static struct fdisk_parttype xbsd_fstypes
[] = {
81 {BSD_FS_UNUSED
, "unused"},
82 {BSD_FS_SWAP
, "swap"},
83 {BSD_FS_V6
, "Version 6"},
84 {BSD_FS_V7
, "Version 7"},
85 {BSD_FS_SYSV
, "System V"},
86 {BSD_FS_V71K
, "4.1BSD"},
87 {BSD_FS_V8
, "Eighth Edition"},
88 {BSD_FS_BSDFFS
, "4.2BSD"},
90 {BSD_FS_EXT2
, "ext2"},
92 {BSD_FS_MSDOS
, "MS-DOS"},
94 {BSD_FS_BSDLFS
, "4.4LFS"},
95 {BSD_FS_OTHER
, "unknown"},
96 {BSD_FS_HPFS
, "HPFS"},
97 {BSD_FS_ISO9660
,"ISO-9660"},
98 {BSD_FS_BOOT
, "boot"},
99 {BSD_FS_ADOS
, "ADOS"},
101 {BSD_FS_ADVFS
, "AdvFS"},
104 #define BSD_FSMAXTYPES (ARRAY_SIZE(xbsd_fstypes)-1)
107 * in-memory fdisk BSD stuff
109 struct fdisk_bsd_label
{
110 struct fdisk_label head
; /* generic part */
114 static int xbsd_delete_part (struct fdisk_context
*cxt
, size_t partnum
);
115 static void xbsd_edit_disklabel (struct fdisk_context
*cxt
);
116 static int xbsd_write_bootstrap (struct fdisk_context
*cxt
);
117 static void xbsd_change_fstype (struct fdisk_context
*cxt
);
118 static int xbsd_get_part_index (struct fdisk_context
*cxt
, int max
, int *n
);
119 static int xbsd_check_new_partition (struct fdisk_context
*cxt
, int *i
);
120 static unsigned short xbsd_dkcksum (struct bsd_disklabel
*lp
);
121 static int xbsd_initlabel (struct fdisk_context
*cxt
,
122 struct dos_partition
*p
, struct bsd_disklabel
*d
);
123 static int xbsd_readlabel (struct fdisk_context
*cxt
,
124 struct dos_partition
*p
, struct bsd_disklabel
*d
);
125 static int xbsd_writelabel (struct fdisk_context
*cxt
, struct dos_partition
*p
, struct bsd_disklabel
*d
);
126 static void sync_disks (void);
128 #if defined (__alpha__)
129 void alpha_bootblock_checksum (char *boot
);
132 #if !defined (__alpha__)
133 static int xbsd_translate_fstype (int linux_type
);
134 static void xbsd_link_part (struct fdisk_context
*cxt
);
135 static struct dos_partition
*xbsd_part
;
136 static int xbsd_part_index
;
139 #if defined (__alpha__)
140 /* We access this through a u_int64_t * when checksumming */
141 static char disklabelbuffer
[BSD_BBSIZE
] __attribute__((aligned(8)));
143 static char disklabelbuffer
[BSD_BBSIZE
];
146 static struct bsd_disklabel xbsd_dlabel
;
148 #define bsd_cround(c, n) \
149 (fdisk_context_use_cylinders(c) ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
151 #define HIDDEN_MASK 0x10
153 static int is_bsd_partition_type(int type
)
155 return (type
== MBR_FREEBSD_PARTITION
||
156 type
== (MBR_FREEBSD_PARTITION
^ HIDDEN_MASK
) ||
157 type
== MBR_NETBSD_PARTITION
||
158 type
== (MBR_NETBSD_PARTITION
^ HIDDEN_MASK
) ||
159 type
== MBR_OPENBSD_PARTITION
||
160 type
== (MBR_OPENBSD_PARTITION
^ HIDDEN_MASK
));
164 * look for DOS partition usable for nested BSD partition table
166 static int bsd_assign_dos_partition(struct fdisk_context
*cxt
)
173 assert(fdisk_is_disklabel(cxt
, OSF
));
175 for (i
= 0; i
< 4; i
++) {
177 struct dos_partition
*p
=
178 fdisk_dos_get_partition(cxt
->parent
, i
);
180 if (!p
|| !is_bsd_partition_type(p
->sys_ind
))
185 ss
= dos_partition_get_start(p
);
188 fprintf (stderr
, _("Partition %zd: has invalid starting sector 0.\n"), i
+ 1);
192 if (cxt
->parent
->dev_path
) {
194 cxt
->dev_path
= fdisk_partname(
195 cxt
->parent
->dev_path
, i
+ 1);
198 DBG(LABEL
, dbgprint("partition %zu assigned to BSD", i
+ 1));
202 printf (_("There is no *BSD partition on %s.\n"), cxt
->parent
->dev_path
);
206 static int bsd_probe_label(struct fdisk_context
*cxt
)
212 assert(fdisk_is_disklabel(cxt
, OSF
));
215 /* nested BSD partiotn table */
216 rc
= bsd_assign_dos_partition(cxt
);
218 rc
= xbsd_readlabel(cxt
, NULL
, &xbsd_dlabel
);
220 return 1; /* found BSD */
221 return 0; /* not found */
224 static int xbsd_write_disklabel (struct fdisk_context
*cxt
)
226 printf (_("Writing disklabel to %s.\n"), cxt
->dev_path
);
227 #if defined (__alpha__)
228 xbsd_writelabel (cxt
, NULL
, &xbsd_dlabel
);
230 xbsd_writelabel (cxt
, xbsd_part
, &xbsd_dlabel
);
232 reread_partition_table(cxt
, 0); /* no exit yet */
237 static int xbsd_add_part (struct fdisk_context
*cxt
,
238 size_t partnum
__attribute__((__unused__
)),
239 struct fdisk_parttype
*t
__attribute__((__unused__
)))
241 struct fdisk_ask
*ask
;
242 unsigned int begin
, end
;
247 assert(fdisk_is_disklabel(cxt
, OSF
));
249 rc
= xbsd_check_new_partition(cxt
, &i
);
253 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
254 begin
= dos_partition_get_start(xbsd_part
);
255 end
= begin
+ dos_partition_get_size(xbsd_part
) - 1;
258 end
= xbsd_dlabel
.d_secperunit
- 1;
260 ask
= fdisk_new_ask();
265 if (fdisk_context_use_cylinders(cxt
))
266 fdisk_ask_set_query(ask
, _("First cylinder"));
268 fdisk_ask_set_query(ask
, _("First sector"));
270 fdisk_ask_set_type(ask
, FDISK_ASKTYPE_NUMBER
);
271 fdisk_ask_number_set_low(ask
, bsd_cround(cxt
, begin
));
272 fdisk_ask_number_set_default(ask
, bsd_cround(cxt
, begin
));
273 fdisk_ask_number_set_high(ask
, bsd_cround(cxt
, end
));
275 rc
= fdisk_do_ask(cxt
, ask
);
280 begin
= fdisk_ask_number_get_result(ask
);
282 if (fdisk_context_use_cylinders(cxt
))
283 begin
= (begin
- 1) * xbsd_dlabel
.d_secpercyl
;
285 fdisk_reset_ask(ask
);
290 fdisk_ask_set_type(ask
, FDISK_ASKTYPE_OFFSET
);
292 if (fdisk_context_use_cylinders(cxt
)) {
293 fdisk_ask_set_query(ask
, _("Last cylinder, +cylinders or +size{K,M,G,T,P}"));
294 fdisk_ask_number_set_unit(ask
,
296 fdisk_context_get_units_per_sector(cxt
));
298 fdisk_ask_set_query(ask
, _("Last sector, +sectors or +size{K,M,G,T,P}"));
299 fdisk_ask_number_set_unit(ask
,cxt
->sector_size
);
302 fdisk_ask_number_set_low(ask
, bsd_cround(cxt
, begin
));
303 fdisk_ask_number_set_default(ask
, bsd_cround(cxt
, end
));
304 fdisk_ask_number_set_high(ask
, bsd_cround(cxt
, end
));
305 fdisk_ask_number_set_base(ask
, bsd_cround(cxt
, begin
));
307 rc
= fdisk_do_ask(cxt
, ask
);
308 end
= fdisk_ask_number_get_result(ask
);
313 if (fdisk_context_use_cylinders(cxt
))
314 end
= end
* xbsd_dlabel
.d_secpercyl
- 1;
316 xbsd_dlabel
.d_partitions
[i
].p_size
= end
- begin
+ 1;
317 xbsd_dlabel
.d_partitions
[i
].p_offset
= begin
;
318 xbsd_dlabel
.d_partitions
[i
].p_fstype
= BSD_FS_UNUSED
;
320 cxt
->label
->nparts_cur
= xbsd_dlabel
.d_npartitions
;
321 fdisk_label_set_changed(cxt
->label
, 1);
326 /* Returns 0 on success, < 0 on error. */
327 static int xbsd_create_disklabel(struct fdisk_context
*cxt
)
333 assert(fdisk_is_disklabel(cxt
, OSF
));
335 fdisk_info(cxt
, _("The device %s does not contain BSD disklabel."), cxt
->dev_path
);
336 rc
= fdisk_ask_yesno(cxt
,
337 _("Do you want to create a BSD disklabel?"),
343 rc
= bsd_assign_dos_partition(cxt
);
345 /* not found DOS partition usable for BSD label */
351 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
352 defined (__s390__) || defined (__s390x__)
353 rc
= xbsd_initlabel(cxt
, NULL
, &xbsd_dlabel
);
355 rc
= xbsd_initlabel(cxt
, xbsd_part
, &xbsd_dlabel
);
358 xbsd_print_disklabel (cxt
, 1);
359 cxt
->label
->nparts_cur
= xbsd_dlabel
.d_npartitions
;
360 cxt
->label
->nparts_max
= BSD_MAXPARTITIONS
;
368 bsd_command_prompt (struct fdisk_context
*cxt
)
376 * BIG-FAT-TODO: don't use bsd_command_prompt(), just initialialize BSD
377 * stuff by label probe() libfdisk function, and use standard fdisk.c
381 rc
= get_user_reply(cxt
, _("BSD disklabel command (m for help): "),
386 switch (tolower(buf
[0])) {
388 rc
= xbsd_get_part_index(cxt
, xbsd_dlabel
.d_npartitions
, &n
);
391 xbsd_delete_part(cxt
, n
);
394 xbsd_edit_disklabel (cxt
);
397 xbsd_write_bootstrap (cxt
);
400 list_partition_types (cxt
);
403 xbsd_add_part (cxt
, 0, 0);
406 xbsd_print_disklabel (cxt
, 0);
410 exit ( EXIT_SUCCESS
);
414 xbsd_print_disklabel (cxt
, 1);
417 xbsd_change_fstype (cxt
);
423 xbsd_write_disklabel (cxt
);
425 #if !defined (__alpha__)
427 xbsd_link_part (cxt
);
431 print_fdisk_menu(cxt
);
437 static int xbsd_delete_part(
438 struct fdisk_context
*cxt
,
443 assert(fdisk_is_disklabel(cxt
, OSF
));
445 xbsd_dlabel
.d_partitions
[partnum
].p_size
= 0;
446 xbsd_dlabel
.d_partitions
[partnum
].p_offset
= 0;
447 xbsd_dlabel
.d_partitions
[partnum
].p_fstype
= BSD_FS_UNUSED
;
448 if (xbsd_dlabel
.d_npartitions
== partnum
+ 1)
449 while (!xbsd_dlabel
.d_partitions
[xbsd_dlabel
.d_npartitions
-1].p_size
)
450 xbsd_dlabel
.d_npartitions
--;
452 cxt
->label
->nparts_cur
= xbsd_dlabel
.d_npartitions
;
453 fdisk_label_set_changed(cxt
->label
, 1);
458 xbsd_print_disklabel (struct fdisk_context
*cxt
, int show_all
)
460 struct bsd_disklabel
*lp
= &xbsd_dlabel
;
461 struct bsd_partition
*pp
;
466 fprintf(f
, "# %s:\n", cxt
->dev_path
);
467 if ((unsigned) lp
->d_type
< BSD_DKMAXTYPES
)
468 fprintf(f
, _("type: %s\n"), xbsd_dktypenames
[lp
->d_type
]);
470 fprintf(f
, _("type: %d\n"), lp
->d_type
);
471 fprintf(f
, _("disk: %.*s\n"), (int) sizeof(lp
->d_typename
), lp
->d_typename
);
472 fprintf(f
, _("label: %.*s\n"), (int) sizeof(lp
->d_packname
), lp
->d_packname
);
473 fprintf(f
, _("flags:"));
474 if (lp
->d_flags
& BSD_D_REMOVABLE
)
475 fprintf(f
, _(" removable"));
476 if (lp
->d_flags
& BSD_D_ECC
)
477 fprintf(f
, _(" ecc"));
478 if (lp
->d_flags
& BSD_D_BADSECT
)
479 fprintf(f
, _(" badsect"));
481 /* On various machines the fields of *lp are short/int/long */
482 /* In order to avoid problems, we cast them all to long. */
483 fprintf(f
, _("bytes/sector: %ld\n"), (long) lp
->d_secsize
);
484 fprintf(f
, _("sectors/track: %ld\n"), (long) lp
->d_nsectors
);
485 fprintf(f
, _("tracks/cylinder: %ld\n"), (long) lp
->d_ntracks
);
486 fprintf(f
, _("sectors/cylinder: %ld\n"), (long) lp
->d_secpercyl
);
487 fprintf(f
, _("cylinders: %ld\n"), (long) lp
->d_ncylinders
);
488 fprintf(f
, _("rpm: %d\n"), lp
->d_rpm
);
489 fprintf(f
, _("interleave: %d\n"), lp
->d_interleave
);
490 fprintf(f
, _("trackskew: %d\n"), lp
->d_trackskew
);
491 fprintf(f
, _("cylinderskew: %d\n"), lp
->d_cylskew
);
492 fprintf(f
, _("headswitch: %ld\t\t# milliseconds\n"),
493 (long) lp
->d_headswitch
);
494 fprintf(f
, _("track-to-track seek: %ld\t# milliseconds\n"),
495 (long) lp
->d_trkseek
);
496 fprintf(f
, _("drivedata: "));
497 for (i
= ARRAY_SIZE(lp
->d_drivedata
)- 1; i
>= 0; i
--)
498 if (lp
->d_drivedata
[i
])
502 for (j
= 0; j
<= i
; j
++)
503 fprintf(f
, "%ld ", (long) lp
->d_drivedata
[j
]);
505 fprintf (f
, _("\n%d partitions:\n"), lp
->d_npartitions
);
506 fprintf (f
, _("# start end size fstype [fsize bsize cpg]\n"));
507 pp
= lp
->d_partitions
;
508 for (i
= 0; i
< lp
->d_npartitions
; i
++, pp
++) {
510 if (fdisk_context_use_cylinders(cxt
) && lp
->d_secpercyl
) {
511 fprintf(f
, " %c: %8ld%c %8ld%c %8ld%c ",
513 (long) pp
->p_offset
/ lp
->d_secpercyl
+ 1,
514 (pp
->p_offset
% lp
->d_secpercyl
) ? '*' : ' ',
515 (long) (pp
->p_offset
+ pp
->p_size
+ lp
->d_secpercyl
- 1)
517 ((pp
->p_offset
+ pp
->p_size
) % lp
->d_secpercyl
) ? '*' : ' ',
518 (long) pp
->p_size
/ lp
->d_secpercyl
,
519 (pp
->p_size
% lp
->d_secpercyl
) ? '*' : ' ');
521 fprintf(f
, " %c: %8ld %8ld %8ld ",
524 (long) pp
->p_offset
+ pp
->p_size
- 1,
527 if ((unsigned) pp
->p_fstype
< BSD_FSMAXTYPES
)
528 fprintf(f
, "%8.8s", xbsd_fstypes
[pp
->p_fstype
].name
);
530 fprintf(f
, "%8x", pp
->p_fstype
);
531 switch (pp
->p_fstype
) {
533 fprintf(f
, " %5ld %5ld %5.5s ",
534 (long) pp
->p_fsize
, (long) pp
->p_fsize
* pp
->p_frag
, "");
538 fprintf(f
, " %5ld %5ld %5d ",
539 (long) pp
->p_fsize
, (long) pp
->p_fsize
* pp
->p_frag
,
544 fprintf(f
, "%22.22s", "");
552 static uint32_t ask_uint32(struct fdisk_context
*cxt
,
553 uint32_t dflt
, char *mesg
)
557 if (fdisk_ask_number(cxt
, min(dflt
, (uint32_t) 1), dflt
,
558 UINT32_MAX
, mesg
, &res
) == 0)
563 static uint16_t ask_uint16(struct fdisk_context
*cxt
,
564 uint16_t dflt
, char *mesg
)
568 if (fdisk_ask_number(cxt
, min(dflt
, (uint16_t) 1),
569 dflt
, UINT16_MAX
, mesg
, &res
) == 0)
574 static void xbsd_edit_disklabel(struct fdisk_context
*cxt
)
576 struct bsd_disklabel
*d
;
581 #if defined (__alpha__) || defined (__ia64__)
582 if (fdisk_ask_number(cxt
, DEFAULT_SECTOR_SIZE
, d
->d_secsize
,
583 UINT32_MAX
, _("bytes/sector"), &res
) == 0)
586 d
->d_nsectors
= ask_uint32(cxt
, d
->d_nsectors
, _("sectors/track"));
587 d
->d_ntracks
= ask_uint32(cxt
, d
->d_ntracks
, _("tracks/cylinder"));
588 d
->d_ncylinders
= ask_uint32(cxt
, d
->d_ncylinders
,_("cylinders"));
591 if (fdisk_ask_number(cxt
, 1, d
->d_nsectors
* d
->d_ntracks
,
592 d
->d_nsectors
* d
->d_ntracks
,
593 _("sectors/cylinder"), &res
) == 0)
594 d
->d_secpercyl
= res
;
596 d
->d_rpm
= ask_uint16(cxt
, d
->d_rpm
, _("rpm"));
597 d
->d_interleave
= ask_uint16(cxt
, d
->d_interleave
, _("interleave"));
598 d
->d_trackskew
= ask_uint16(cxt
, d
->d_trackskew
, _("trackskew"));
599 d
->d_cylskew
= ask_uint16(cxt
, d
->d_cylskew
, _("cylinderskew"));
601 d
->d_headswitch
= ask_uint32(cxt
, d
->d_headswitch
, _("headswitch"));
602 d
->d_trkseek
= ask_uint32(cxt
, d
->d_trkseek
, _("track-to-track seek"));
604 d
->d_secperunit
= d
->d_secpercyl
* d
->d_ncylinders
;
607 static int xbsd_get_bootstrap(struct fdisk_context
*cxt
,
608 char *path
, void *ptr
, int size
)
612 if ((fd
= open(path
, O_RDONLY
)) < 0) {
613 fdisk_warn(cxt
, _("open failed %s"), path
);
617 if (read_all(fd
, ptr
, size
) != size
) {
618 fdisk_warn(cxt
, _("read failed %s"), path
);
623 fdisk_info(cxt
, "bootstrap file %s successfully loaded", path
);
628 static int xbsd_write_bootstrap (struct fdisk_context
*cxt
)
630 char *name
= xbsd_dlabel
.d_type
== BSD_DTYPE_SCSI
? "sd" : "wd";
635 struct bsd_disklabel dl
;
637 snprintf(buf
, sizeof(buf
),
638 _("Bootstrap: %1$sboot -> boot%1$s (default %1$s)"),
640 rc
= fdisk_ask_string(cxt
, buf
, &res
);
646 snprintf(buf
, sizeof(buf
), "%s/%sboot", BSD_LINUX_BOOTDIR
, name
);
647 rc
= xbsd_get_bootstrap(cxt
, buf
,
649 (int) xbsd_dlabel
.d_secsize
);
653 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
654 d
= &disklabelbuffer
[BSD_LABELSECTOR
* DEFAULT_SECTOR_SIZE
];
655 memmove(&dl
, d
, sizeof(struct bsd_disklabel
));
657 /* The disklabel will be overwritten by 0's from bootxx anyway */
658 memset(d
, 0, sizeof(struct bsd_disklabel
));
660 snprintf(buf
, sizeof(buf
), "%s/boot%s", BSD_LINUX_BOOTDIR
, name
);
661 rc
= xbsd_get_bootstrap(cxt
, buf
,
662 &disklabelbuffer
[xbsd_dlabel
.d_secsize
],
663 (int) xbsd_dlabel
.d_bbsize
- xbsd_dlabel
.d_secsize
);
667 /* check end of the bootstrap */
668 for (p
= d
; p
< d
+ sizeof(struct bsd_disklabel
); p
++) {
671 fdisk_warnx(cxt
, _("Bootstrap overlaps with disk label!"));
675 /* move disklabel back */
676 memmove(d
, &dl
, sizeof(struct bsd_disklabel
));
678 #if defined (__powerpc__) || defined (__hppa__)
680 #elif defined (__alpha__)
682 alpha_bootblock_checksum(disklabelbuffer
);
684 sector
= dos_partition_get_start(xbsd_part
);
686 if (lseek(cxt
->dev_fd
, (off_t
) sector
* DEFAULT_SECTOR_SIZE
, SEEK_SET
) == -1) {
687 fdisk_warn(cxt
, _("seek failed %s"), cxt
->dev_path
);
691 if (write_all(cxt
->dev_fd
, disklabelbuffer
, BSD_BBSIZE
)) {
692 fdisk_warn(cxt
, _("write failed %s"), cxt
->dev_path
);
697 fdisk_info(cxt
, _("Bootstrap installed on %s."), cxt
->dev_path
);
706 /* TODO: remove this, use regular change_partition_type() in fdisk.c */
707 static void xbsd_change_fstype (struct fdisk_context
*cxt
)
710 struct fdisk_parttype
*t
;
714 assert(fdisk_is_disklabel(cxt
, OSF
));
716 if (xbsd_get_part_index(cxt
, xbsd_dlabel
.d_npartitions
, &i
))
718 t
= ask_partition_type(cxt
);
721 xbsd_dlabel
.d_partitions
[i
].p_fstype
= t
->type
;
722 fdisk_free_parttype(t
);
723 fdisk_label_set_changed(cxt
->label
, 1);
727 static int xbsd_get_part_index(struct fdisk_context
*cxt
, int max
, int *n
)
732 snprintf(prompt
, sizeof(prompt
), _("Partition (a-%c): "), 'a' + max
- 1);
735 int rc
= fdisk_ask_string(cxt
, prompt
, &res
);
741 } while (c
< 'a' || c
> 'a' + max
- 1);
748 xbsd_check_new_partition(struct fdisk_context
*cxt
, int *i
)
752 /* room for more? various BSD flavours have different maxima */
753 if (xbsd_dlabel
.d_npartitions
== BSD_MAXPARTITIONS
) {
756 for (t
= 0; t
< BSD_MAXPARTITIONS
; t
++)
757 if (xbsd_dlabel
.d_partitions
[t
].p_size
== 0)
760 if (t
== BSD_MAXPARTITIONS
) {
761 fprintf (stderr
, _("The maximum number of partitions "
762 "has been created\n"));
767 rc
= xbsd_get_part_index(cxt
, BSD_MAXPARTITIONS
, i
);
771 if (*i
>= xbsd_dlabel
.d_npartitions
)
772 xbsd_dlabel
.d_npartitions
= (*i
) + 1;
774 if (xbsd_dlabel
.d_partitions
[*i
].p_size
!= 0) {
775 fprintf (stderr
, _("This partition already exists.\n"));
782 static unsigned short
783 xbsd_dkcksum (struct bsd_disklabel
*lp
) {
784 unsigned short *start
, *end
;
785 unsigned short sum
= 0;
787 start
= (unsigned short *) lp
;
788 end
= (unsigned short *) &lp
->d_partitions
[lp
->d_npartitions
];
794 static int xbsd_initlabel (struct fdisk_context
*cxt
,
795 struct dos_partition
*p
,
796 struct bsd_disklabel
*d
)
798 struct bsd_partition
*pp
;
800 memset (d
, 0, sizeof (struct bsd_disklabel
));
802 d
-> d_magic
= BSD_DISKMAGIC
;
804 if (strncmp (cxt
->dev_path
, "/dev/sd", 7) == 0)
805 d
-> d_type
= BSD_DTYPE_SCSI
;
807 d
-> d_type
= BSD_DTYPE_ST506
;
809 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
810 d
-> d_subtype
= BSD_DSTYPE_INDOSPART
& pindex
;
813 #if !defined (__alpha__)
814 d
-> d_flags
= BSD_D_DOSPART
;
818 d
-> d_secsize
= DEFAULT_SECTOR_SIZE
; /* bytes/sector */
819 d
-> d_nsectors
= cxt
->geom
.sectors
; /* sectors/track */
820 d
-> d_ntracks
= cxt
->geom
.heads
; /* tracks/cylinder (heads) */
821 d
-> d_ncylinders
= cxt
->geom
.cylinders
;
822 d
-> d_secpercyl
= cxt
->geom
.sectors
* cxt
->geom
.heads
;/* sectors/cylinder */
823 if (d
-> d_secpercyl
== 0)
824 d
-> d_secpercyl
= 1; /* avoid segfaults */
825 d
-> d_secperunit
= d
-> d_secpercyl
* d
-> d_ncylinders
;
828 d
-> d_interleave
= 1;
829 d
-> d_trackskew
= 0;
831 d
-> d_headswitch
= 0;
834 d
-> d_magic2
= BSD_DISKMAGIC
;
835 d
-> d_bbsize
= BSD_BBSIZE
;
836 d
-> d_sbsize
= BSD_SBSIZE
;
838 #if !defined (__alpha__)
839 d
-> d_npartitions
= 4;
840 pp
= &d
-> d_partitions
[2]; /* Partition C should be
841 the NetBSD partition */
842 pp
-> p_offset
= dos_partition_get_start(p
);
843 pp
-> p_size
= dos_partition_get_size(p
);
844 pp
-> p_fstype
= BSD_FS_UNUSED
;
845 pp
= &d
-> d_partitions
[3]; /* Partition D should be
848 pp
-> p_size
= d
-> d_secperunit
;
849 pp
-> p_fstype
= BSD_FS_UNUSED
;
850 #elif defined (__alpha__)
851 d
-> d_npartitions
= 3;
852 pp
= &d
-> d_partitions
[2]; /* Partition C should be
855 pp
-> p_size
= d
-> d_secperunit
;
856 pp
-> p_fstype
= BSD_FS_UNUSED
;
863 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
864 * If it has the right magic, return 0.
867 xbsd_readlabel (struct fdisk_context
*cxt
, struct dos_partition
*p
, struct bsd_disklabel
*d
)
874 /* p is used only to get the starting sector */
875 #if !defined (__alpha__)
876 sector
= (p
? dos_partition_get_start(p
) : 0);
877 #elif defined (__alpha__)
881 if (lseek (cxt
->dev_fd
, (off_t
) sector
* DEFAULT_SECTOR_SIZE
, SEEK_SET
) == -1)
883 if (BSD_BBSIZE
!= read (cxt
->dev_fd
, disklabelbuffer
, BSD_BBSIZE
))
887 &disklabelbuffer
[BSD_LABELSECTOR
* DEFAULT_SECTOR_SIZE
+ BSD_LABELOFFSET
],
888 sizeof (struct bsd_disklabel
));
890 if (d
-> d_magic
!= BSD_DISKMAGIC
|| d
-> d_magic2
!= BSD_DISKMAGIC
)
893 for (t
= d
-> d_npartitions
; t
< BSD_MAXPARTITIONS
; t
++) {
894 d
-> d_partitions
[t
].p_size
= 0;
895 d
-> d_partitions
[t
].p_offset
= 0;
896 d
-> d_partitions
[t
].p_fstype
= BSD_FS_UNUSED
;
899 if (d
-> d_npartitions
> BSD_MAXPARTITIONS
)
900 fprintf (stderr
, _("Warning: too many partitions "
901 "(%d, maximum is %d).\n"),
902 d
-> d_npartitions
, BSD_MAXPARTITIONS
);
904 cxt
->label
->nparts_cur
= d
->d_npartitions
;
905 cxt
->label
->nparts_max
= BSD_MAXPARTITIONS
;
910 xbsd_writelabel (struct fdisk_context
*cxt
, struct dos_partition
*p
, struct bsd_disklabel
*d
)
914 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
915 sector
= dos_partition_get_start(p
) + BSD_LABELSECTOR
;
917 sector
= BSD_LABELSECTOR
;
921 d
-> d_checksum
= xbsd_dkcksum (d
);
923 /* This is necessary if we want to write the bootstrap later,
924 otherwise we'd write the old disklabel with the bootstrap.
926 memmove (&disklabelbuffer
[BSD_LABELSECTOR
* DEFAULT_SECTOR_SIZE
+ BSD_LABELOFFSET
], d
,
927 sizeof (struct bsd_disklabel
));
929 #if defined (__alpha__) && BSD_LABELSECTOR == 0
930 alpha_bootblock_checksum (disklabelbuffer
);
931 if (lseek (cxt
->dev_fd
, (off_t
) 0, SEEK_SET
) == -1) {
932 fdisk_warn(cxt
, _("seek failed: %d"), cxt
->dev_path
);
935 if (BSD_BBSIZE
!= write (cxt
->dev_fd
, disklabelbuffer
, BSD_BBSIZE
)) {
936 fdisk_warn(cxt
, _("write failed: %d"), cxt
->dev_path
);
940 if (lseek (cxt
->dev_fd
, (off_t
) sector
* DEFAULT_SECTOR_SIZE
+ BSD_LABELOFFSET
,
942 fdisk_warn(cxt
, _("seek failed: %d"), cxt
->dev_path
);
945 if (sizeof (struct bsd_disklabel
) != write (cxt
->dev_fd
, d
, sizeof (struct bsd_disklabel
))) {
946 fdisk_warn(cxt
, _("write failed: %d"), cxt
->dev_path
);
958 printf (_("\nSyncing disks.\n"));
963 #if !defined (__alpha__)
965 xbsd_translate_fstype (int linux_type
)
969 case 0x01: /* DOS 12-bit FAT */
970 case 0x04: /* DOS 16-bit <32M */
971 case 0x06: /* DOS 16-bit >=32M */
972 case 0xe1: /* DOS access */
973 case 0xe3: /* DOS R/O */
974 case 0xf2: /* DOS secondary */
976 case 0x07: /* OS/2 HPFS */
984 * link partition from parent (DOS) to nested BSD partition table
987 xbsd_link_part (struct fdisk_context
*cxt
)
991 struct dos_partition
*p
;
993 if (!cxt
->parent
|| !fdisk_is_disklabel(cxt
->parent
, DOS
))
994 return; /* not nested PT */
996 if (fdisk_ask_partnum(cxt
->parent
, &k
, FALSE
))
999 if (xbsd_check_new_partition(cxt
, &i
))
1002 p
= fdisk_dos_get_partition(cxt
->parent
, k
);
1004 xbsd_dlabel
.d_partitions
[i
].p_size
= dos_partition_get_size(p
);
1005 xbsd_dlabel
.d_partitions
[i
].p_offset
= dos_partition_get_start(p
);
1006 xbsd_dlabel
.d_partitions
[i
].p_fstype
= xbsd_translate_fstype(p
->sys_ind
);
1010 #if defined (__alpha__)
1012 #if !defined(__GLIBC__)
1013 typedef unsigned long long u_int64_t
;
1017 alpha_bootblock_checksum (char *boot
)
1022 dp
= (u_int64_t
*)boot
;
1024 for (i
= 0; i
< 63; i
++)
1028 #endif /* __alpha__ */
1030 static struct fdisk_parttype
*xbsd_get_parttype(
1031 struct fdisk_context
*cxt
,
1034 struct fdisk_parttype
*t
;
1038 assert(fdisk_is_disklabel(cxt
, OSF
));
1040 if (n
>= xbsd_dlabel
.d_npartitions
)
1043 t
= fdisk_get_parttype_from_code(cxt
, xbsd_dlabel
.d_partitions
[n
].p_fstype
);
1045 t
= fdisk_new_unknown_parttype(xbsd_dlabel
.d_partitions
[n
].p_fstype
, NULL
);
1049 static int xbsd_set_parttype(
1050 struct fdisk_context
*cxt
,
1052 struct fdisk_parttype
*t
)
1054 struct bsd_partition
*p
;
1058 assert(fdisk_is_disklabel(cxt
, OSF
));
1060 if (partnum
>= xbsd_dlabel
.d_npartitions
|| !t
|| t
->type
> UINT8_MAX
)
1063 p
= &xbsd_dlabel
.d_partitions
[partnum
];
1064 if (t
->type
== p
->p_fstype
)
1067 p
->p_fstype
= t
->type
;
1068 fdisk_label_set_changed(cxt
->label
, 1);
1072 static const struct fdisk_label_operations bsd_operations
=
1074 .probe
= bsd_probe_label
,
1075 .write
= xbsd_write_disklabel
,
1076 .create
= xbsd_create_disklabel
,
1077 .part_add
= xbsd_add_part
,
1078 .part_delete
= xbsd_delete_part
,
1079 .part_get_type
= xbsd_get_parttype
,
1080 .part_set_type
= xbsd_set_parttype
1085 * allocates BSD label driver
1087 struct fdisk_label
*fdisk_new_bsd_label(struct fdisk_context
*cxt
)
1089 struct fdisk_label
*lb
;
1090 struct fdisk_bsd_label
*bsd
;
1094 bsd
= calloc(1, sizeof(*bsd
));
1098 /* initialize generic part of the driver */
1099 lb
= (struct fdisk_label
*) bsd
;
1101 lb
->id
= FDISK_DISKLABEL_OSF
;
1102 lb
->op
= &bsd_operations
;
1103 lb
->parttypes
= xbsd_fstypes
;
1104 lb
->nparttypes
= ARRAY_SIZE(xbsd_fstypes
);
1106 lb
->flags
|= FDISK_LABEL_FL_ADDPART_NOPARTNO
;
1107 lb
->flags
|= FDISK_LABEL_FL_REQUIRE_GEOMETRY
;