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