]>
Commit | Line | Data |
---|---|---|
726f69e2 KZ |
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: | |
50ea6795 | 5 | |
726f69e2 KZ |
6 | Copyright (c) 1987, 1988 Regents of the University of California. |
7 | All rights reserved. | |
50ea6795 | 8 | |
726f69e2 KZ |
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: | |
50ea6795 KZ |
19 | This product includes software developed by the University of |
20 | California, Berkeley and its contributors. | |
726f69e2 KZ |
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. | |
50ea6795 | 24 | |
726f69e2 KZ |
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. | |
7eda085c KZ |
36 | |
37 | Changes: | |
38 | 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls | |
22853e4a KZ |
39 | |
40 | 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better | |
63cccae4 KZ |
41 | support for OSF/1 disklabels on Alpha. |
42 | Also fixed unaligned accesses in alpha_bootblock_checksum() | |
726f69e2 KZ |
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> | |
7eda085c | 53 | #include "nls.h" |
726f69e2 | 54 | |
726f69e2 KZ |
55 | #include <sys/param.h> |
56 | ||
7eda085c | 57 | #include "common.h" |
726f69e2 | 58 | #include "fdisk.h" |
e8f26419 KZ |
59 | #define FREEBSD_PARTITION 0xa5 |
60 | #define NETBSD_PARTITION 0xa9 | |
726f69e2 | 61 | #define DKTYPENAMES |
5c36a0eb | 62 | #include "fdiskbsdlabel.h" |
726f69e2 | 63 | |
61c4cb85 | 64 | static void xbsd_delete_part (struct fdisk_context *cxt, int partnum); |
fd6b7a7f | 65 | static void xbsd_edit_disklabel (void); |
7737f698 | 66 | static void xbsd_write_bootstrap (struct fdisk_context *cxt); |
749af4b6 | 67 | static void xbsd_change_fstype (struct fdisk_context *cxt); |
fd6b7a7f KZ |
68 | static int xbsd_get_part_index (int max); |
69 | static int xbsd_check_new_partition (int *i); | |
95961ee2 | 70 | static unsigned short xbsd_dkcksum (struct xbsd_disklabel *lp); |
7737f698 DB |
71 | static int xbsd_initlabel (struct fdisk_context *cxt, |
72 | struct partition *p, struct xbsd_disklabel *d, | |
63cccae4 | 73 | int pindex); |
7737f698 DB |
74 | static int xbsd_readlabel (struct fdisk_context *cxt, |
75 | struct partition *p, struct xbsd_disklabel *d); | |
76 | static int xbsd_writelabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d); | |
726f69e2 | 77 | static void sync_disks (void); |
22853e4a | 78 | |
726f69e2 KZ |
79 | #if defined (__alpha__) |
80 | void alpha_bootblock_checksum (char *boot); | |
81 | #endif | |
82 | ||
22853e4a KZ |
83 | #if !defined (__alpha__) |
84 | static int xbsd_translate_fstype (int linux_type); | |
e53ced85 | 85 | static void xbsd_link_part (struct fdisk_context *cxt); |
fd6b7a7f KZ |
86 | static struct partition *xbsd_part; |
87 | static int xbsd_part_index; | |
726f69e2 KZ |
88 | #endif |
89 | ||
22853e4a KZ |
90 | #if defined (__alpha__) |
91 | /* We access this through a u_int64_t * when checksumming */ | |
92 | static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8))); | |
93 | #else | |
94 | static char disklabelbuffer[BSD_BBSIZE]; | |
95 | #endif | |
96 | ||
97 | static struct xbsd_disklabel xbsd_dlabel; | |
98 | ||
99 | #define bsd_cround(n) \ | |
100 | (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n)) | |
101 | ||
63cccae4 KZ |
102 | /* |
103 | * Test whether the whole disk has BSD disk label magic. | |
104 | * | |
105 | * Note: often reformatting with DOS-type label leaves the BSD magic, | |
106 | * so this does not mean that there is a BSD disk label. | |
107 | */ | |
b8855c86 | 108 | static int |
da4ea9f5 | 109 | osf_probe_label(struct fdisk_context *cxt) { |
7737f698 | 110 | if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0) |
63cccae4 KZ |
111 | return 0; |
112 | return 1; | |
22853e4a KZ |
113 | } |
114 | ||
2b6fc908 | 115 | int |
7737f698 DB |
116 | btrydev (struct fdisk_context *cxt) { |
117 | if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0) | |
63cccae4 | 118 | return -1; |
7737f698 DB |
119 | printf(_("\nBSD label for device: %s\n"), cxt->dev_path); |
120 | xbsd_print_disklabel (cxt, 0); | |
63cccae4 | 121 | return 0; |
fd6b7a7f KZ |
122 | } |
123 | ||
22853e4a KZ |
124 | #if !defined (__alpha__) |
125 | static int | |
5c36a0eb KZ |
126 | hidden(int type) { |
127 | return type ^ 0x10; | |
128 | } | |
129 | ||
22853e4a | 130 | static int |
e8f26419 KZ |
131 | is_bsd_partition_type(int type) { |
132 | return (type == FREEBSD_PARTITION || | |
133 | type == hidden(FREEBSD_PARTITION) || | |
134 | type == NETBSD_PARTITION || | |
135 | type == hidden(NETBSD_PARTITION)); | |
5c36a0eb | 136 | } |
22853e4a | 137 | #endif |
5c36a0eb | 138 | |
fae7b1bc DB |
139 | static int xbsd_write_disklabel (struct fdisk_context *cxt) |
140 | { | |
141 | #if defined (__alpha__) | |
142 | printf (_("Writing disklabel to %s.\n"), cxt->dev_path); | |
143 | xbsd_writelabel (cxt, NULL, &xbsd_dlabel); | |
144 | #else | |
145 | printf (_("Writing disklabel to %s.\n"), | |
146 | partname(cxt->dev_path, xbsd_part_index+1, 0)); | |
147 | xbsd_writelabel (cxt, xbsd_part, &xbsd_dlabel); | |
148 | #endif | |
149 | reread_partition_table(cxt, 0); /* no exit yet */ | |
150 | ||
151 | return 0; | |
152 | } | |
153 | ||
4ae4a8af KZ |
154 | static void xbsd_add_part (struct fdisk_context *cxt, |
155 | int partnum __attribute__((__unused__)), | |
ed470672 | 156 | struct fdisk_parttype *t __attribute__((__unused__))) |
0f639e54 DB |
157 | { |
158 | unsigned int begin, end; | |
159 | char mesg[256]; | |
160 | int i; | |
161 | ||
162 | if (!xbsd_check_new_partition (&i)) | |
163 | return; | |
164 | ||
165 | #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) | |
166 | begin = get_start_sect(xbsd_part); | |
167 | end = begin + get_nr_sects(xbsd_part) - 1; | |
168 | #else | |
169 | begin = 0; | |
170 | end = xbsd_dlabel.d_secperunit - 1; | |
171 | #endif | |
172 | ||
173 | snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); | |
174 | begin = read_int (cxt, bsd_cround (begin), bsd_cround (begin), bsd_cround (end), | |
175 | 0, mesg); | |
176 | ||
177 | if (display_in_cyl_units) | |
178 | begin = (begin - 1) * xbsd_dlabel.d_secpercyl; | |
179 | ||
180 | snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"), | |
181 | str_units(SINGULAR)); | |
182 | end = read_int (cxt, bsd_cround (begin), bsd_cround (end), bsd_cround (end), | |
183 | bsd_cround (begin), mesg); | |
184 | ||
185 | if (display_in_cyl_units) | |
186 | end = end * xbsd_dlabel.d_secpercyl - 1; | |
187 | ||
188 | xbsd_dlabel.d_partitions[i].p_size = end - begin + 1; | |
189 | xbsd_dlabel.d_partitions[i].p_offset = begin; | |
190 | xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED; | |
191 | } | |
192 | ||
639f1d56 DB |
193 | static int xbsd_create_disklabel (struct fdisk_context *cxt) |
194 | { | |
195 | char c; | |
196 | ||
197 | #if defined (__alpha__) | |
198 | fprintf (stderr, _("%s contains no disklabel.\n"), cxt->dev_path); | |
199 | #else | |
200 | fprintf (stderr, _("%s contains no disklabel.\n"), | |
201 | partname(cxt->dev_path, xbsd_part_index+1, 0)); | |
202 | #endif | |
203 | ||
204 | while (1) { | |
205 | c = read_char (_("Do you want to create a disklabel? (y/n) ")); | |
206 | if (tolower(c) == 'y') { | |
207 | if (xbsd_initlabel (cxt, | |
208 | #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \ | |
209 | defined (__s390__) || defined (__s390x__) | |
210 | NULL, &xbsd_dlabel, 0 | |
211 | #else | |
212 | xbsd_part, &xbsd_dlabel, xbsd_part_index | |
213 | #endif | |
214 | ) == 1) { | |
215 | xbsd_print_disklabel (cxt, 1); | |
216 | return 1; | |
217 | } else | |
218 | return 0; | |
219 | } else if (c == 'n') | |
220 | return 0; | |
221 | } | |
222 | } | |
223 | ||
726f69e2 | 224 | void |
7737f698 | 225 | bsd_command_prompt (struct fdisk_context *cxt) |
e97a991a | 226 | { |
22853e4a | 227 | #if !defined (__alpha__) |
2b6fc908 | 228 | int t, ss; |
22853e4a | 229 | struct partition *p; |
726f69e2 | 230 | |
22853e4a KZ |
231 | for (t=0; t<4; t++) { |
232 | p = get_part_table(t); | |
e8f26419 | 233 | if (p && is_bsd_partition_type(p->sys_ind)) { |
22853e4a | 234 | xbsd_part = p; |
fd6b7a7f | 235 | xbsd_part_index = t; |
2b6fc908 | 236 | ss = get_start_sect(xbsd_part); |
5c36a0eb | 237 | if (ss == 0) { |
22853e4a | 238 | fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"), |
823f0fd1 | 239 | partname(cxt->dev_path, t+1, 0)); |
22853e4a | 240 | return; |
726f69e2 | 241 | } |
22853e4a | 242 | printf (_("Reading disklabel of %s at sector %d.\n"), |
823f0fd1 | 243 | partname(cxt->dev_path, t+1, 0), ss + BSD_LABELSECTOR); |
7737f698 DB |
244 | if (xbsd_readlabel (cxt, xbsd_part, &xbsd_dlabel) == 0) |
245 | if (xbsd_create_disklabel (cxt) == 0) | |
726f69e2 KZ |
246 | return; |
247 | break; | |
248 | } | |
22853e4a | 249 | } |
726f69e2 | 250 | |
5c36a0eb | 251 | if (t == 4) { |
823f0fd1 | 252 | printf (_("There is no *BSD partition on %s.\n"), cxt->dev_path); |
726f69e2 KZ |
253 | return; |
254 | } | |
255 | ||
256 | #elif defined (__alpha__) | |
257 | ||
7737f698 DB |
258 | if (xbsd_readlabel (cxt, NULL, &xbsd_dlabel) == 0) |
259 | if (xbsd_create_disklabel (cxt) == 0) | |
726f69e2 KZ |
260 | exit ( EXIT_SUCCESS ); |
261 | ||
262 | #endif | |
263 | ||
22853e4a | 264 | while (1) { |
726f69e2 | 265 | putchar ('\n'); |
22853e4a | 266 | switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) { |
726f69e2 | 267 | case 'd': |
61c4cb85 DB |
268 | xbsd_delete_part(cxt, xbsd_get_part_index(xbsd_dlabel.d_npartitions)); |
269 | break; | |
726f69e2 | 270 | case 'e': |
22853e4a | 271 | xbsd_edit_disklabel (); |
726f69e2 KZ |
272 | break; |
273 | case 'i': | |
7737f698 | 274 | xbsd_write_bootstrap (cxt); |
726f69e2 KZ |
275 | break; |
276 | case 'l': | |
7b575fcc | 277 | list_partition_types (cxt); |
726f69e2 KZ |
278 | break; |
279 | case 'n': | |
0f639e54 DB |
280 | xbsd_add_part (cxt, 0, 0); |
281 | break; | |
726f69e2 | 282 | case 'p': |
7737f698 | 283 | xbsd_print_disklabel (cxt, 0); |
726f69e2 KZ |
284 | break; |
285 | case 'q': | |
823f0fd1 | 286 | close (cxt->dev_fd); |
726f69e2 | 287 | exit ( EXIT_SUCCESS ); |
22853e4a KZ |
288 | case 'r': |
289 | return; | |
726f69e2 | 290 | case 's': |
7737f698 | 291 | xbsd_print_disklabel (cxt, 1); |
726f69e2 KZ |
292 | break; |
293 | case 't': | |
749af4b6 | 294 | xbsd_change_fstype (cxt); |
22853e4a KZ |
295 | break; |
296 | case 'u': | |
24cd580b | 297 | change_units(cxt); |
726f69e2 KZ |
298 | break; |
299 | case 'w': | |
7737f698 | 300 | xbsd_write_disklabel (cxt); |
726f69e2 | 301 | break; |
22853e4a | 302 | #if !defined (__alpha__) |
726f69e2 | 303 | case 'x': |
e53ced85 | 304 | xbsd_link_part (cxt); |
726f69e2 KZ |
305 | break; |
306 | #endif | |
307 | default: | |
c482303e | 308 | print_menu(MAIN_MENU); |
726f69e2 KZ |
309 | break; |
310 | } | |
311 | } | |
312 | } | |
313 | ||
4ae4a8af KZ |
314 | static void xbsd_delete_part(struct fdisk_context *cxt __attribute__((__unused__)), |
315 | int partnum) | |
726f69e2 | 316 | { |
61c4cb85 DB |
317 | xbsd_dlabel.d_partitions[partnum].p_size = 0; |
318 | xbsd_dlabel.d_partitions[partnum].p_offset = 0; | |
319 | xbsd_dlabel.d_partitions[partnum].p_fstype = BSD_FS_UNUSED; | |
320 | if (xbsd_dlabel.d_npartitions == partnum + 1) | |
321 | while (!xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size) | |
322 | xbsd_dlabel.d_npartitions--; | |
726f69e2 KZ |
323 | } |
324 | ||
22853e4a | 325 | void |
7737f698 | 326 | xbsd_print_disklabel (struct fdisk_context *cxt, int show_all) { |
fd6b7a7f KZ |
327 | struct xbsd_disklabel *lp = &xbsd_dlabel; |
328 | struct xbsd_partition *pp; | |
726f69e2 KZ |
329 | FILE *f = stdout; |
330 | int i, j; | |
331 | ||
22853e4a KZ |
332 | if (show_all) { |
333 | #if defined (__alpha__) | |
823f0fd1 | 334 | fprintf(f, "# %s:\n", cxt->dev_path); |
22853e4a | 335 | #else |
823f0fd1 | 336 | fprintf(f, "# %s:\n", partname(cxt->dev_path, xbsd_part_index+1, 0)); |
726f69e2 KZ |
337 | #endif |
338 | if ((unsigned) lp->d_type < BSD_DKMAXTYPES) | |
7eda085c | 339 | fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]); |
726f69e2 | 340 | else |
7eda085c KZ |
341 | fprintf(f, _("type: %d\n"), lp->d_type); |
342 | fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename); | |
343 | fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname); | |
344 | fprintf(f, _("flags:")); | |
726f69e2 | 345 | if (lp->d_flags & BSD_D_REMOVABLE) |
7eda085c | 346 | fprintf(f, _(" removable")); |
726f69e2 | 347 | if (lp->d_flags & BSD_D_ECC) |
7eda085c | 348 | fprintf(f, _(" ecc")); |
726f69e2 | 349 | if (lp->d_flags & BSD_D_BADSECT) |
7eda085c | 350 | fprintf(f, _(" badsect")); |
726f69e2 | 351 | fprintf(f, "\n"); |
fd6b7a7f KZ |
352 | /* On various machines the fields of *lp are short/int/long */ |
353 | /* In order to avoid problems, we cast them all to long. */ | |
7eda085c KZ |
354 | fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize); |
355 | fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors); | |
356 | fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks); | |
357 | fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl); | |
358 | fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders); | |
359 | fprintf(f, _("rpm: %d\n"), lp->d_rpm); | |
360 | fprintf(f, _("interleave: %d\n"), lp->d_interleave); | |
361 | fprintf(f, _("trackskew: %d\n"), lp->d_trackskew); | |
362 | fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew); | |
22853e4a KZ |
363 | fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"), |
364 | (long) lp->d_headswitch); | |
365 | fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"), | |
366 | (long) lp->d_trkseek); | |
7eda085c | 367 | fprintf(f, _("drivedata: ")); |
726f69e2 KZ |
368 | for (i = NDDATA - 1; i >= 0; i--) |
369 | if (lp->d_drivedata[i]) | |
370 | break; | |
371 | if (i < 0) | |
372 | i = 0; | |
373 | for (j = 0; j <= i; j++) | |
fd6b7a7f | 374 | fprintf(f, "%ld ", (long) lp->d_drivedata[j]); |
726f69e2 | 375 | } |
7eda085c | 376 | fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions); |
22853e4a | 377 | fprintf (f, _("# start end size fstype [fsize bsize cpg]\n")); |
726f69e2 KZ |
378 | pp = lp->d_partitions; |
379 | for (i = 0; i < lp->d_npartitions; i++, pp++) { | |
380 | if (pp->p_size) { | |
22853e4a KZ |
381 | if (display_in_cyl_units && lp->d_secpercyl) { |
382 | fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ", | |
383 | 'a' + i, | |
384 | (long) pp->p_offset / lp->d_secpercyl + 1, | |
385 | (pp->p_offset % lp->d_secpercyl) ? '*' : ' ', | |
386 | (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) | |
387 | / lp->d_secpercyl, | |
388 | ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ', | |
389 | (long) pp->p_size / lp->d_secpercyl, | |
390 | (pp->p_size % lp->d_secpercyl) ? '*' : ' '); | |
391 | } else { | |
392 | fprintf(f, " %c: %8ld %8ld %8ld ", | |
393 | 'a' + i, | |
394 | (long) pp->p_offset, | |
395 | (long) pp->p_offset + pp->p_size - 1, | |
396 | (long) pp->p_size); | |
397 | } | |
726f69e2 | 398 | if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES) |
fd6b7a7f | 399 | fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name); |
726f69e2 KZ |
400 | else |
401 | fprintf(f, "%8x", pp->p_fstype); | |
22853e4a KZ |
402 | switch (pp->p_fstype) { |
403 | case BSD_FS_UNUSED: | |
fd6b7a7f KZ |
404 | fprintf(f, " %5ld %5ld %5.5s ", |
405 | (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, ""); | |
726f69e2 | 406 | break; |
50ea6795 | 407 | |
726f69e2 | 408 | case BSD_FS_BSDFFS: |
fd6b7a7f KZ |
409 | fprintf(f, " %5ld %5ld %5d ", |
410 | (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, | |
726f69e2 KZ |
411 | pp->p_cpg); |
412 | break; | |
50ea6795 | 413 | |
726f69e2 | 414 | default: |
22853e4a | 415 | fprintf(f, "%22.22s", ""); |
726f69e2 KZ |
416 | break; |
417 | } | |
22853e4a | 418 | fprintf(f, "\n"); |
726f69e2 KZ |
419 | } |
420 | } | |
421 | } | |
422 | ||
726f69e2 KZ |
423 | static int |
424 | edit_int (int def, char *mesg) | |
425 | { | |
426 | do { | |
427 | fputs (mesg, stdout); | |
428 | printf (" (%d): ", def); | |
8feb31e5 | 429 | if (!read_line (NULL)) |
726f69e2 KZ |
430 | return def; |
431 | } | |
432 | while (!isdigit (*line_ptr)); | |
433 | return atoi (line_ptr); | |
50ea6795 | 434 | } |
726f69e2 KZ |
435 | |
436 | static void | |
fd6b7a7f | 437 | xbsd_edit_disklabel (void) |
726f69e2 | 438 | { |
fd6b7a7f | 439 | struct xbsd_disklabel *d; |
726f69e2 | 440 | |
fd6b7a7f | 441 | d = &xbsd_dlabel; |
726f69e2 | 442 | |
22853e4a | 443 | #if defined (__alpha__) || defined (__ia64__) |
95961ee2 JW |
444 | d -> d_secsize = (unsigned long) edit_int ((unsigned long) d -> d_secsize ,_("bytes/sector")); |
445 | d -> d_nsectors = (unsigned long) edit_int ((unsigned long) d -> d_nsectors ,_("sectors/track")); | |
446 | d -> d_ntracks = (unsigned long) edit_int ((unsigned long) d -> d_ntracks ,_("tracks/cylinder")); | |
447 | d -> d_ncylinders = (unsigned long) edit_int ((unsigned long) d -> d_ncylinders ,_("cylinders")); | |
726f69e2 KZ |
448 | #endif |
449 | ||
450 | /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */ | |
451 | while (1) | |
452 | { | |
95961ee2 | 453 | d -> d_secpercyl = (unsigned long) edit_int ((unsigned long) d -> d_nsectors * d -> d_ntracks, |
7eda085c | 454 | _("sectors/cylinder")); |
726f69e2 KZ |
455 | if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks) |
456 | break; | |
457 | ||
7eda085c | 458 | printf (_("Must be <= sectors/track * tracks/cylinder (default).\n")); |
726f69e2 | 459 | } |
95961ee2 JW |
460 | d -> d_rpm = (unsigned short) edit_int ((unsigned short) d -> d_rpm ,_("rpm")); |
461 | d -> d_interleave = (unsigned short) edit_int ((unsigned short) d -> d_interleave,_("interleave")); | |
462 | d -> d_trackskew = (unsigned short) edit_int ((unsigned short) d -> d_trackskew ,_("trackskew")); | |
463 | d -> d_cylskew = (unsigned short) edit_int ((unsigned short) d -> d_cylskew ,_("cylinderskew")); | |
464 | d -> d_headswitch = (unsigned long) edit_int ((unsigned long) d -> d_headswitch ,_("headswitch")); | |
465 | d -> d_trkseek = (unsigned long) edit_int ((unsigned long) d -> d_trkseek ,_("track-to-track seek")); | |
726f69e2 KZ |
466 | |
467 | d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; | |
468 | } | |
469 | ||
470 | static int | |
fd6b7a7f | 471 | xbsd_get_bootstrap (char *path, void *ptr, int size) |
726f69e2 KZ |
472 | { |
473 | int fd; | |
474 | ||
475 | if ((fd = open (path, O_RDONLY)) < 0) | |
476 | { | |
477 | perror (path); | |
478 | return 0; | |
479 | } | |
480 | if (read (fd, ptr, size) < 0) | |
481 | { | |
482 | perror (path); | |
483 | close (fd); | |
484 | return 0; | |
485 | } | |
486 | printf (" ... %s\n", path); | |
487 | close (fd); | |
488 | return 1; | |
489 | } | |
490 | ||
491 | static void | |
7737f698 | 492 | xbsd_write_bootstrap (struct fdisk_context *cxt) |
726f69e2 KZ |
493 | { |
494 | char *bootdir = BSD_LINUX_BOOTDIR; | |
7e5fad47 | 495 | char path[sizeof(BSD_LINUX_BOOTDIR) + 1 + 2 + 4]; /* BSD_LINUX_BOOTDIR + / + {sd,wd} + boot */ |
726f69e2 | 496 | char *dkbasename; |
fd6b7a7f | 497 | struct xbsd_disklabel dl; |
726f69e2 KZ |
498 | char *d, *p, *e; |
499 | int sector; | |
500 | ||
fd6b7a7f | 501 | if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI) |
726f69e2 KZ |
502 | dkbasename = "sd"; |
503 | else | |
504 | dkbasename = "wd"; | |
505 | ||
c07ebfa1 KZ |
506 | printf (_("Bootstrap: %sboot -> boot%s (%s): "), |
507 | dkbasename, dkbasename, dkbasename); | |
8feb31e5 | 508 | if (read_line (NULL)) { |
726f69e2 KZ |
509 | line_ptr[strlen (line_ptr)-1] = '\0'; |
510 | dkbasename = line_ptr; | |
511 | } | |
c07ebfa1 | 512 | snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename); |
22853e4a | 513 | if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize)) |
726f69e2 KZ |
514 | return; |
515 | ||
fd6b7a7f | 516 | /* We need a backup of the disklabel (xbsd_dlabel might have changed). */ |
22853e4a | 517 | d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE]; |
c0f19ccf | 518 | memmove (&dl, d, sizeof (struct xbsd_disklabel)); |
726f69e2 KZ |
519 | |
520 | /* The disklabel will be overwritten by 0's from bootxx anyway */ | |
56054a79 | 521 | memset (d, 0, sizeof (struct xbsd_disklabel)); |
726f69e2 | 522 | |
c07ebfa1 | 523 | snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename); |
22853e4a | 524 | if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize], |
fd6b7a7f | 525 | (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize)) |
726f69e2 KZ |
526 | return; |
527 | ||
fd6b7a7f | 528 | e = d + sizeof (struct xbsd_disklabel); |
726f69e2 | 529 | for (p=d; p < e; p++) |
c07ebfa1 | 530 | if (*p) { |
7eda085c | 531 | fprintf (stderr, _("Bootstrap overlaps with disk label!\n")); |
726f69e2 KZ |
532 | exit ( EXIT_FAILURE ); |
533 | } | |
534 | ||
c0f19ccf | 535 | memmove (d, &dl, sizeof (struct xbsd_disklabel)); |
726f69e2 | 536 | |
364cda48 | 537 | #if defined (__powerpc__) || defined (__hppa__) |
5c36a0eb | 538 | sector = 0; |
726f69e2 KZ |
539 | #elif defined (__alpha__) |
540 | sector = 0; | |
22853e4a KZ |
541 | alpha_bootblock_checksum (disklabelbuffer); |
542 | #else | |
543 | sector = get_start_sect(xbsd_part); | |
726f69e2 KZ |
544 | #endif |
545 | ||
823f0fd1 | 546 | if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1) |
7737f698 | 547 | fatal (cxt, unable_to_seek); |
823f0fd1 | 548 | if (BSD_BBSIZE != write (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE)) |
7737f698 | 549 | fatal (cxt, unable_to_write); |
726f69e2 | 550 | |
22853e4a | 551 | #if defined (__alpha__) |
823f0fd1 | 552 | printf (_("Bootstrap installed on %s.\n"), cxt->dev_path); |
22853e4a KZ |
553 | #else |
554 | printf (_("Bootstrap installed on %s.\n"), | |
823f0fd1 | 555 | partname (cxt->dev_path, xbsd_part_index+1, 0)); |
726f69e2 KZ |
556 | #endif |
557 | ||
558 | sync_disks (); | |
559 | } | |
560 | ||
02460b8a | 561 | /* TODO: remove this, use regular change_partition_type() in fdisk.c */ |
726f69e2 | 562 | static void |
749af4b6 | 563 | xbsd_change_fstype (struct fdisk_context *cxt) |
726f69e2 KZ |
564 | { |
565 | int i; | |
559d921e | 566 | struct fdisk_parttype *t; |
726f69e2 | 567 | |
fd6b7a7f | 568 | i = xbsd_get_part_index (xbsd_dlabel.d_npartitions); |
559d921e KZ |
569 | t = read_partition_type(cxt); |
570 | ||
571 | if (t) { | |
572 | xbsd_dlabel.d_partitions[i].p_fstype = t->type; | |
573 | fdisk_free_parttype(t); | |
574 | } | |
726f69e2 KZ |
575 | } |
576 | ||
577 | static int | |
fd6b7a7f | 578 | xbsd_get_part_index (int max) |
726f69e2 | 579 | { |
eb63b9b8 | 580 | char prompt[256]; |
726f69e2 KZ |
581 | char l; |
582 | ||
c07ebfa1 | 583 | snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1); |
726f69e2 KZ |
584 | do |
585 | l = tolower (read_char (prompt)); | |
586 | while (l < 'a' || l > 'a' + max - 1); | |
587 | return l - 'a'; | |
588 | } | |
589 | ||
590 | static int | |
63cccae4 | 591 | xbsd_check_new_partition (int *i) { |
726f69e2 | 592 | |
63cccae4 KZ |
593 | /* room for more? various BSD flavours have different maxima */ |
594 | if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) { | |
595 | int t; | |
726f69e2 | 596 | |
63cccae4 KZ |
597 | for (t = 0; t < BSD_MAXPARTITIONS; t++) |
598 | if (xbsd_dlabel.d_partitions[t].p_size == 0) | |
599 | break; | |
726f69e2 | 600 | |
63cccae4 KZ |
601 | if (t == BSD_MAXPARTITIONS) { |
602 | fprintf (stderr, _("The maximum number of partitions " | |
603 | "has been created\n")); | |
604 | return 0; | |
605 | } | |
606 | } | |
726f69e2 | 607 | |
63cccae4 KZ |
608 | *i = xbsd_get_part_index (BSD_MAXPARTITIONS); |
609 | ||
610 | if (*i >= xbsd_dlabel.d_npartitions) | |
611 | xbsd_dlabel.d_npartitions = (*i) + 1; | |
612 | ||
613 | if (xbsd_dlabel.d_partitions[*i].p_size != 0) { | |
614 | fprintf (stderr, _("This partition already exists.\n")); | |
615 | return 0; | |
616 | } | |
617 | ||
618 | return 1; | |
726f69e2 KZ |
619 | } |
620 | ||
95961ee2 | 621 | static unsigned short |
63cccae4 | 622 | xbsd_dkcksum (struct xbsd_disklabel *lp) { |
95961ee2 JW |
623 | unsigned short *start, *end; |
624 | unsigned short sum = 0; | |
50ea6795 | 625 | |
95961ee2 JW |
626 | start = (unsigned short *) lp; |
627 | end = (unsigned short *) &lp->d_partitions[lp->d_npartitions]; | |
63cccae4 KZ |
628 | while (start < end) |
629 | sum ^= *start++; | |
630 | return sum; | |
726f69e2 KZ |
631 | } |
632 | ||
633 | static int | |
7737f698 | 634 | xbsd_initlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d, |
e99da659 | 635 | int pindex __attribute__((__unused__))) { |
63cccae4 | 636 | struct xbsd_partition *pp; |
726f69e2 | 637 | |
56054a79 | 638 | memset (d, 0, sizeof (struct xbsd_disklabel)); |
726f69e2 | 639 | |
63cccae4 | 640 | d -> d_magic = BSD_DISKMAGIC; |
726f69e2 | 641 | |
823f0fd1 | 642 | if (strncmp (cxt->dev_path, "/dev/sd", 7) == 0) |
63cccae4 KZ |
643 | d -> d_type = BSD_DTYPE_SCSI; |
644 | else | |
645 | d -> d_type = BSD_DTYPE_ST506; | |
726f69e2 KZ |
646 | |
647 | #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */ | |
63cccae4 | 648 | d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex; |
726f69e2 KZ |
649 | #endif |
650 | ||
22853e4a | 651 | #if !defined (__alpha__) |
63cccae4 | 652 | d -> d_flags = BSD_D_DOSPART; |
726f69e2 | 653 | #else |
63cccae4 | 654 | d -> d_flags = 0; |
726f69e2 | 655 | #endif |
63cccae4 | 656 | d -> d_secsize = SECTOR_SIZE; /* bytes/sector */ |
24cd580b DB |
657 | d -> d_nsectors = cxt->geom.sectors; /* sectors/track */ |
658 | d -> d_ntracks = cxt->geom.heads; /* tracks/cylinder (heads) */ | |
659 | d -> d_ncylinders = cxt->geom.cylinders; | |
660 | d -> d_secpercyl = cxt->geom.sectors * cxt->geom.heads;/* sectors/cylinder */ | |
63cccae4 KZ |
661 | if (d -> d_secpercyl == 0) |
662 | d -> d_secpercyl = 1; /* avoid segfaults */ | |
663 | d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; | |
664 | ||
665 | d -> d_rpm = 3600; | |
666 | d -> d_interleave = 1; | |
667 | d -> d_trackskew = 0; | |
668 | d -> d_cylskew = 0; | |
669 | d -> d_headswitch = 0; | |
670 | d -> d_trkseek = 0; | |
671 | ||
672 | d -> d_magic2 = BSD_DISKMAGIC; | |
673 | d -> d_bbsize = BSD_BBSIZE; | |
674 | d -> d_sbsize = BSD_SBSIZE; | |
726f69e2 | 675 | |
22853e4a | 676 | #if !defined (__alpha__) |
63cccae4 KZ |
677 | d -> d_npartitions = 4; |
678 | pp = &d -> d_partitions[2]; /* Partition C should be | |
679 | the NetBSD partition */ | |
680 | pp -> p_offset = get_start_sect(p); | |
681 | pp -> p_size = get_nr_sects(p); | |
682 | pp -> p_fstype = BSD_FS_UNUSED; | |
683 | pp = &d -> d_partitions[3]; /* Partition D should be | |
684 | the whole disk */ | |
685 | pp -> p_offset = 0; | |
686 | pp -> p_size = d -> d_secperunit; | |
687 | pp -> p_fstype = BSD_FS_UNUSED; | |
726f69e2 | 688 | #elif defined (__alpha__) |
63cccae4 KZ |
689 | d -> d_npartitions = 3; |
690 | pp = &d -> d_partitions[2]; /* Partition C should be | |
691 | the whole disk */ | |
692 | pp -> p_offset = 0; | |
693 | pp -> p_size = d -> d_secperunit; | |
50ea6795 | 694 | pp -> p_fstype = BSD_FS_UNUSED; |
726f69e2 KZ |
695 | #endif |
696 | ||
63cccae4 | 697 | return 1; |
726f69e2 KZ |
698 | } |
699 | ||
63cccae4 KZ |
700 | /* |
701 | * Read a xbsd_disklabel from sector 0 or from the starting sector of p. | |
702 | * If it has the right magic, return 1. | |
703 | */ | |
726f69e2 | 704 | static int |
7737f698 | 705 | xbsd_readlabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d) |
726f69e2 | 706 | { |
63cccae4 | 707 | int t, sector; |
726f69e2 | 708 | |
63cccae4 | 709 | /* p is used only to get the starting sector */ |
22853e4a | 710 | #if !defined (__alpha__) |
63cccae4 | 711 | sector = (p ? get_start_sect(p) : 0); |
726f69e2 | 712 | #elif defined (__alpha__) |
63cccae4 | 713 | sector = 0; |
726f69e2 KZ |
714 | #endif |
715 | ||
823f0fd1 | 716 | if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE, SEEK_SET) == -1) |
7737f698 | 717 | fatal (cxt, unable_to_seek); |
823f0fd1 | 718 | if (BSD_BBSIZE != read (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE)) |
7737f698 | 719 | fatal (cxt, unable_to_read); |
726f69e2 | 720 | |
c0f19ccf DM |
721 | memmove (d, |
722 | &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], | |
723 | sizeof (struct xbsd_disklabel)); | |
726f69e2 | 724 | |
63cccae4 KZ |
725 | if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC) |
726 | return 0; | |
726f69e2 | 727 | |
63cccae4 KZ |
728 | for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) { |
729 | d -> d_partitions[t].p_size = 0; | |
730 | d -> d_partitions[t].p_offset = 0; | |
50ea6795 | 731 | d -> d_partitions[t].p_fstype = BSD_FS_UNUSED; |
63cccae4 KZ |
732 | } |
733 | ||
734 | if (d -> d_npartitions > BSD_MAXPARTITIONS) | |
735 | fprintf (stderr, _("Warning: too many partitions " | |
736 | "(%d, maximum is %d).\n"), | |
737 | d -> d_npartitions, BSD_MAXPARTITIONS); | |
738 | return 1; | |
726f69e2 KZ |
739 | } |
740 | ||
741 | static int | |
7737f698 | 742 | xbsd_writelabel (struct fdisk_context *cxt, struct partition *p, struct xbsd_disklabel *d) |
726f69e2 | 743 | { |
df1dddf9 | 744 | unsigned int sector; |
726f69e2 | 745 | |
364cda48 | 746 | #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) |
2b6fc908 | 747 | sector = get_start_sect(p) + BSD_LABELSECTOR; |
364cda48 | 748 | #else |
726f69e2 KZ |
749 | sector = BSD_LABELSECTOR; |
750 | #endif | |
751 | ||
752 | d -> d_checksum = 0; | |
fd6b7a7f | 753 | d -> d_checksum = xbsd_dkcksum (d); |
726f69e2 KZ |
754 | |
755 | /* This is necessary if we want to write the bootstrap later, | |
756 | otherwise we'd write the old disklabel with the bootstrap. | |
757 | */ | |
c0f19ccf DM |
758 | memmove (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET], d, |
759 | sizeof (struct xbsd_disklabel)); | |
726f69e2 KZ |
760 | |
761 | #if defined (__alpha__) && BSD_LABELSECTOR == 0 | |
22853e4a | 762 | alpha_bootblock_checksum (disklabelbuffer); |
823f0fd1 | 763 | if (lseek (cxt->dev_fd, (off_t) 0, SEEK_SET) == -1) |
7737f698 | 764 | fatal (cxt, unable_to_seek); |
823f0fd1 | 765 | if (BSD_BBSIZE != write (cxt->dev_fd, disklabelbuffer, BSD_BBSIZE)) |
7737f698 | 766 | fatal (cxt, unable_to_write); |
726f69e2 | 767 | #else |
823f0fd1 | 768 | if (lseek (cxt->dev_fd, (off_t) sector * SECTOR_SIZE + BSD_LABELOFFSET, |
22853e4a | 769 | SEEK_SET) == -1) |
7737f698 | 770 | fatal (cxt, unable_to_seek); |
823f0fd1 | 771 | if (sizeof (struct xbsd_disklabel) != write (cxt->dev_fd, d, sizeof (struct xbsd_disklabel))) |
7737f698 | 772 | fatal (cxt, unable_to_write); |
726f69e2 KZ |
773 | #endif |
774 | ||
775 | sync_disks (); | |
776 | ||
777 | return 1; | |
778 | } | |
779 | ||
780 | static void | |
781 | sync_disks (void) | |
782 | { | |
7eda085c | 783 | printf (_("\nSyncing disks.\n")); |
726f69e2 KZ |
784 | sync (); |
785 | sleep (4); | |
786 | } | |
787 | ||
22853e4a | 788 | #if !defined (__alpha__) |
726f69e2 | 789 | static int |
fd6b7a7f | 790 | xbsd_translate_fstype (int linux_type) |
726f69e2 KZ |
791 | { |
792 | switch (linux_type) | |
793 | { | |
794 | case 0x01: /* DOS 12-bit FAT */ | |
795 | case 0x04: /* DOS 16-bit <32M */ | |
796 | case 0x06: /* DOS 16-bit >=32M */ | |
797 | case 0xe1: /* DOS access */ | |
798 | case 0xe3: /* DOS R/O */ | |
799 | case 0xf2: /* DOS secondary */ | |
800 | return BSD_FS_MSDOS; | |
801 | case 0x07: /* OS/2 HPFS */ | |
802 | return BSD_FS_HPFS; | |
803 | default: | |
804 | return BSD_FS_OTHER; | |
805 | } | |
806 | } | |
807 | ||
808 | static void | |
e53ced85 | 809 | xbsd_link_part (struct fdisk_context *cxt) |
726f69e2 KZ |
810 | { |
811 | int k, i; | |
22853e4a | 812 | struct partition *p; |
726f69e2 | 813 | |
e53ced85 | 814 | k = get_partition (cxt, 1, partitions); |
726f69e2 | 815 | |
fd6b7a7f | 816 | if (!xbsd_check_new_partition (&i)) |
726f69e2 KZ |
817 | return; |
818 | ||
22853e4a KZ |
819 | p = get_part_table(k); |
820 | ||
821 | xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p); | |
822 | xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p); | |
823 | xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind); | |
726f69e2 KZ |
824 | } |
825 | #endif | |
826 | ||
827 | #if defined (__alpha__) | |
726f69e2 | 828 | |
eb63b9b8 | 829 | #if !defined(__GLIBC__) |
2b6fc908 KZ |
830 | typedef unsigned long long u_int64_t; |
831 | #endif | |
832 | ||
726f69e2 KZ |
833 | void |
834 | alpha_bootblock_checksum (char *boot) | |
835 | { | |
836 | u_int64_t *dp, sum; | |
837 | int i; | |
50ea6795 | 838 | |
726f69e2 KZ |
839 | dp = (u_int64_t *)boot; |
840 | sum = 0; | |
841 | for (i = 0; i < 63; i++) | |
842 | sum += dp[i]; | |
843 | dp[63] = sum; | |
844 | } | |
845 | #endif /* __alpha__ */ | |
b8855c86 | 846 | |
010186f2 KZ |
847 | static struct fdisk_parttype *xbsd_get_parttype(struct fdisk_context *cxt, int n) |
848 | { | |
849 | struct fdisk_parttype *t; | |
850 | ||
851 | if (n >= xbsd_dlabel.d_npartitions) | |
852 | return NULL; | |
853 | ||
854 | t = fdisk_get_parttype_from_code(cxt, xbsd_dlabel.d_partitions[n].p_fstype); | |
855 | if (!t) | |
856 | t = fdisk_new_unknown_parttype(xbsd_dlabel.d_partitions[n].p_fstype, NULL); | |
857 | return t; | |
858 | } | |
859 | ||
02460b8a KZ |
860 | static int xbsd_set_parttype(struct fdisk_context *cxt, int partnum, |
861 | struct fdisk_parttype *t) | |
862 | { | |
863 | struct xbsd_partition *p; | |
864 | ||
865 | if (partnum >= xbsd_dlabel.d_npartitions || !t || t->type > UINT8_MAX) | |
866 | return -EINVAL; | |
867 | ||
868 | p = &xbsd_dlabel.d_partitions[partnum]; | |
869 | if (t->type == p->p_fstype) | |
870 | return 0; | |
871 | ||
872 | p->p_fstype = t->type; | |
873 | return 0; | |
874 | } | |
875 | ||
b8855c86 DB |
876 | const struct fdisk_label bsd_label = |
877 | { | |
878 | .name = "bsd", | |
749af4b6 | 879 | .parttypes = xbsd_fstypes, |
559d921e | 880 | .nparttypes = ARRAY_SIZE(xbsd_fstypes), |
749af4b6 | 881 | |
da4ea9f5 | 882 | .probe = osf_probe_label, |
fae7b1bc | 883 | .write = xbsd_write_disklabel, |
2ca61a61 | 884 | .verify = NULL, |
639f1d56 | 885 | .create = xbsd_create_disklabel, |
2ca61a61 | 886 | .part_add = xbsd_add_part, |
61c4cb85 | 887 | .part_delete = xbsd_delete_part, |
010186f2 | 888 | .part_get_type = xbsd_get_parttype, |
02460b8a | 889 | .part_set_type = xbsd_set_parttype, |
b8855c86 | 890 | }; |