]>
Commit | Line | Data |
---|---|---|
726f69e2 | 1 | /* |
d5b2b8db KZ |
2 | * Copyright (C) 2007-2013 Karel Zak <kzak@redhat.com> |
3 | * | |
4 | * Based on the original code from fdisk | |
5 | * written by Bernhard Fastenrath (fasten@informatik.uni-bonn.de) | |
6 | * with code from the NetBSD disklabel command. | |
7 | * | |
8 | * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, March 1999 | |
9 | * David Huggins-Daines <dhuggins@linuxcare.com>, January 2000 | |
10 | */ | |
726f69e2 KZ |
11 | #include <unistd.h> |
12 | #include <stdio.h> | |
13 | #include <stdlib.h> | |
14 | #include <string.h> | |
15 | #include <fcntl.h> | |
726f69e2 | 16 | #include <errno.h> |
726f69e2 KZ |
17 | #include <sys/param.h> |
18 | ||
d5b2b8db KZ |
19 | #include "blkdev.h" |
20 | #include "fdiskP.h" | |
bb58112e | 21 | #include "pt-mbr.h" |
d5b2b8db | 22 | #include "pt-bsd.h" |
9e346a02 | 23 | #include "all-io.h" |
726f69e2 | 24 | |
a4e6a45e KZ |
25 | |
26 | /** | |
27 | * SECTION: bsd | |
705854f3 KZ |
28 | * @title: BSD |
29 | * @short_description: disk label specific functions | |
a4e6a45e KZ |
30 | * |
31 | */ | |
32 | ||
19c2cc4e | 33 | static const char *bsd_dktypenames[] = { |
e11858e2 KZ |
34 | "unknown", |
35 | "SMD", | |
36 | "MSCP", | |
37 | "old DEC", | |
38 | "SCSI", | |
39 | "ESDI", | |
40 | "ST506", | |
41 | "HP-IB", | |
42 | "HP-FL", | |
43 | "type 9", | |
44 | "floppy", | |
87918040 | 45 | NULL |
e11858e2 | 46 | }; |
2872ffa0 | 47 | #define BSD_DKMAXTYPES (ARRAY_SIZE(bsd_dktypenames) - 1) |
e11858e2 | 48 | |
2872ffa0 | 49 | static struct fdisk_parttype bsd_fstypes[] = { |
e11858e2 KZ |
50 | {BSD_FS_UNUSED, "unused"}, |
51 | {BSD_FS_SWAP, "swap"}, | |
52 | {BSD_FS_V6, "Version 6"}, | |
53 | {BSD_FS_V7, "Version 7"}, | |
54 | {BSD_FS_SYSV, "System V"}, | |
55 | {BSD_FS_V71K, "4.1BSD"}, | |
56 | {BSD_FS_V8, "Eighth Edition"}, | |
57 | {BSD_FS_BSDFFS, "4.2BSD"}, | |
58 | #ifdef __alpha__ | |
59 | {BSD_FS_EXT2, "ext2"}, | |
60 | #else | |
61 | {BSD_FS_MSDOS, "MS-DOS"}, | |
62 | #endif | |
63 | {BSD_FS_BSDLFS, "4.4LFS"}, | |
64 | {BSD_FS_OTHER, "unknown"}, | |
65 | {BSD_FS_HPFS, "HPFS"}, | |
66 | {BSD_FS_ISO9660,"ISO-9660"}, | |
67 | {BSD_FS_BOOT, "boot"}, | |
68 | {BSD_FS_ADOS, "ADOS"}, | |
69 | {BSD_FS_HFS, "HFS"}, | |
70 | {BSD_FS_ADVFS, "AdvFS"}, | |
71 | { 0, NULL } | |
72 | }; | |
2872ffa0 | 73 | #define BSD_FSMAXTYPES (ARRAY_SIZE(bsd_fstypes)-1) |
e11858e2 | 74 | |
0c5d095e KZ |
75 | /* |
76 | * in-memory fdisk BSD stuff | |
77 | */ | |
78 | struct fdisk_bsd_label { | |
79 | struct fdisk_label head; /* generic part */ | |
0efc6c57 KZ |
80 | |
81 | struct dos_partition *dos_part; /* parent */ | |
82 | struct bsd_disklabel bsd; /* on disk label */ | |
87ed95ff KZ |
83 | #if defined (__alpha__) |
84 | /* We access this through a u_int64_t * when checksumming */ | |
85 | char bsdbuffer[BSD_BBSIZE] __attribute__((aligned(8))); | |
86 | #else | |
87 | char bsdbuffer[BSD_BBSIZE]; | |
88 | #endif | |
0c5d095e KZ |
89 | }; |
90 | ||
2872ffa0 KZ |
91 | static int bsd_initlabel(struct fdisk_context *cxt); |
92 | static int bsd_readlabel(struct fdisk_context *cxt); | |
296b856d | 93 | static void sync_disks(struct fdisk_context *cxt); |
0efc6c57 | 94 | |
0efc6c57 KZ |
95 | static inline struct fdisk_bsd_label *self_label(struct fdisk_context *cxt) |
96 | { | |
97 | assert(cxt); | |
98 | assert(cxt->label); | |
aa36c2cf | 99 | assert(fdisk_is_label(cxt, BSD)); |
0efc6c57 KZ |
100 | |
101 | return (struct fdisk_bsd_label *) cxt->label; | |
102 | } | |
103 | ||
104 | static inline struct bsd_disklabel *self_disklabel(struct fdisk_context *cxt) | |
105 | { | |
106 | assert(cxt); | |
107 | assert(cxt->label); | |
aa36c2cf | 108 | assert(fdisk_is_label(cxt, BSD)); |
0efc6c57 KZ |
109 | |
110 | return &((struct fdisk_bsd_label *) cxt->label)->bsd; | |
111 | } | |
22853e4a | 112 | |
a699b27d KZ |
113 | static struct fdisk_parttype *bsd_partition_parttype( |
114 | struct fdisk_context *cxt, | |
115 | struct bsd_partition *p) | |
116 | { | |
117 | struct fdisk_parttype *t | |
a745611d | 118 | = fdisk_label_get_parttype_from_code(cxt->label, p->p_fstype); |
a699b27d KZ |
119 | return t ? : fdisk_new_unknown_parttype(p->p_fstype, NULL); |
120 | } | |
121 | ||
122 | ||
0bf367ed | 123 | #if defined (__alpha__) |
19c2cc4e | 124 | static void alpha_bootblock_checksum (char *boot) |
0bf367ed KZ |
125 | { |
126 | uint64_t *dp = (uint64_t *) boot, sum = 0; | |
127 | int i; | |
128 | ||
129 | for (i = 0; i < 63; i++) | |
130 | sum += dp[i]; | |
131 | dp[63] = sum; | |
132 | } | |
133 | #endif /* __alpha__ */ | |
134 | ||
818d7924 KZ |
135 | #define HIDDEN_MASK 0x10 |
136 | ||
137 | static int is_bsd_partition_type(int type) | |
138 | { | |
139 | return (type == MBR_FREEBSD_PARTITION || | |
140 | type == (MBR_FREEBSD_PARTITION ^ HIDDEN_MASK) || | |
141 | type == MBR_NETBSD_PARTITION || | |
142 | type == (MBR_NETBSD_PARTITION ^ HIDDEN_MASK) || | |
143 | type == MBR_OPENBSD_PARTITION || | |
144 | type == (MBR_OPENBSD_PARTITION ^ HIDDEN_MASK)); | |
145 | } | |
146 | ||
63cccae4 | 147 | /* |
818d7924 | 148 | * look for DOS partition usable for nested BSD partition table |
63cccae4 | 149 | */ |
0efc6c57 | 150 | static int bsd_assign_dos_partition(struct fdisk_context *cxt) |
8a95621d | 151 | { |
0efc6c57 | 152 | struct fdisk_bsd_label *l = self_label(cxt); |
818d7924 KZ |
153 | size_t i; |
154 | ||
818d7924 | 155 | for (i = 0; i < 4; i++) { |
0073a4cf | 156 | fdisk_sector_t ss; |
818d7924 | 157 | |
0efc6c57 | 158 | l->dos_part = fdisk_dos_get_partition(cxt->parent, i); |
0dd3dfb8 | 159 | |
0efc6c57 | 160 | if (!l->dos_part || !is_bsd_partition_type(l->dos_part->sys_ind)) |
818d7924 KZ |
161 | continue; |
162 | ||
0efc6c57 | 163 | ss = dos_partition_get_start(l->dos_part); |
818d7924 | 164 | if (!ss) { |
296b856d KZ |
165 | fdisk_warnx(cxt, _("Partition %zd: has invalid starting " |
166 | "sector 0."), i + 1); | |
818d7924 KZ |
167 | return -1; |
168 | } | |
169 | ||
170 | if (cxt->parent->dev_path) { | |
171 | free(cxt->dev_path); | |
172 | cxt->dev_path = fdisk_partname( | |
173 | cxt->parent->dev_path, i + 1); | |
174 | } | |
175 | ||
88141067 | 176 | DBG(LABEL, ul_debug("partition %zu assigned to BSD", i + 1)); |
63cccae4 | 177 | return 0; |
818d7924 KZ |
178 | } |
179 | ||
296b856d KZ |
180 | fdisk_warnx(cxt, _("There is no *BSD partition on %s."), |
181 | cxt->parent->dev_path); | |
0efc6c57 KZ |
182 | free(cxt->dev_path); |
183 | cxt->dev_path = NULL; | |
184 | l->dos_part = NULL; | |
63cccae4 | 185 | return 1; |
22853e4a KZ |
186 | } |
187 | ||
818d7924 KZ |
188 | static int bsd_probe_label(struct fdisk_context *cxt) |
189 | { | |
190 | int rc = 0; | |
818d7924 KZ |
191 | |
192 | if (cxt->parent) | |
9e930041 | 193 | rc = bsd_assign_dos_partition(cxt); /* nested BSD partition table */ |
818d7924 | 194 | if (!rc) |
2872ffa0 | 195 | rc = bsd_readlabel(cxt); |
818d7924 KZ |
196 | if (!rc) |
197 | return 1; /* found BSD */ | |
198 | return 0; /* not found */ | |
199 | } | |
200 | ||
7f63194a KZ |
201 | static int set_parttype( |
202 | struct fdisk_context *cxt, | |
203 | size_t partnum, | |
204 | struct fdisk_parttype *t) | |
205 | { | |
206 | struct bsd_partition *p; | |
207 | struct bsd_disklabel *d = self_disklabel(cxt); | |
208 | ||
209 | if (partnum >= d->d_npartitions || !t || t->code > UINT8_MAX) | |
210 | return -EINVAL; | |
211 | ||
212 | p = &d->d_partitions[partnum]; | |
213 | if (t->code == p->p_fstype) | |
214 | return 0; | |
215 | ||
216 | p->p_fstype = t->code; | |
217 | fdisk_label_set_changed(cxt->label, 1); | |
218 | return 0; | |
219 | } | |
220 | ||
77d6a70a | 221 | static int bsd_add_partition(struct fdisk_context *cxt, |
c3bc7483 KZ |
222 | struct fdisk_partition *pa, |
223 | size_t *partno) | |
0f639e54 | 224 | { |
0efc6c57 KZ |
225 | struct fdisk_bsd_label *l = self_label(cxt); |
226 | struct bsd_disklabel *d = self_disklabel(cxt); | |
77d6a70a | 227 | size_t i; |
0efc6c57 | 228 | unsigned int begin = 0, end; |
77d6a70a | 229 | int rc = 0; |
0f639e54 | 230 | |
6c89f750 | 231 | rc = fdisk_partition_next_partno(pa, cxt, &i); |
77d6a70a KZ |
232 | if (rc) |
233 | return rc; | |
0b08fb07 | 234 | if (i >= BSD_MAXPARTITIONS) |
77d6a70a | 235 | return -ERANGE; |
0efc6c57 KZ |
236 | if (l->dos_part) { |
237 | begin = dos_partition_get_start(l->dos_part); | |
238 | end = begin + dos_partition_get_size(l->dos_part) - 1; | |
239 | } else | |
240 | end = d->d_secperunit - 1; | |
9ffeb235 | 241 | |
682802db KZ |
242 | /* |
243 | * First sector | |
244 | */ | |
77d6a70a KZ |
245 | if (pa && pa->start_follow_default) |
246 | ; | |
ecf40cda | 247 | else if (pa && fdisk_partition_has_start(pa)) { |
77d6a70a KZ |
248 | if (pa->start < begin || pa->start > end) |
249 | return -ERANGE; | |
250 | begin = pa->start; | |
251 | } else { | |
252 | struct fdisk_ask *ask = fdisk_new_ask(); | |
253 | ||
254 | if (!ask) | |
255 | return -ENOMEM; | |
256 | fdisk_ask_set_query(ask, | |
6a632136 | 257 | fdisk_use_cylinders(cxt) ? |
77d6a70a KZ |
258 | _("First cylinder") : _("First sector")); |
259 | fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER); | |
260 | fdisk_ask_number_set_low(ask, fdisk_cround(cxt, begin)); | |
261 | fdisk_ask_number_set_default(ask, fdisk_cround(cxt, begin)); | |
262 | fdisk_ask_number_set_high(ask, fdisk_cround(cxt, end)); | |
263 | ||
264 | rc = fdisk_do_ask(cxt, ask); | |
265 | begin = fdisk_ask_number_get_result(ask); | |
a3d83488 | 266 | fdisk_unref_ask(ask); |
77d6a70a KZ |
267 | if (rc) |
268 | return rc; | |
6a632136 | 269 | if (fdisk_use_cylinders(cxt)) |
77d6a70a | 270 | begin = (begin - 1) * d->d_secpercyl; |
682802db | 271 | } |
682802db KZ |
272 | |
273 | /* | |
274 | * Last sector | |
275 | */ | |
77d6a70a KZ |
276 | if (pa && pa->end_follow_default) |
277 | ; | |
ecf40cda | 278 | else if (pa && fdisk_partition_has_size(pa)) { |
77d6a70a KZ |
279 | if (begin + pa->size > end) |
280 | return -ERANGE; | |
7f63194a | 281 | end = begin + pa->size - 1ULL; |
682802db | 282 | } else { |
77d6a70a KZ |
283 | /* ask user by dialog */ |
284 | struct fdisk_ask *ask = fdisk_new_ask(); | |
285 | ||
286 | if (!ask) | |
287 | return -ENOMEM; | |
288 | fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET); | |
289 | ||
6a632136 | 290 | if (fdisk_use_cylinders(cxt)) { |
757cefbb | 291 | fdisk_ask_set_query(ask, _("Last cylinder, +/-cylinders or +/-size{K,M,G,T,P}")); |
77d6a70a KZ |
292 | fdisk_ask_number_set_unit(ask, |
293 | cxt->sector_size * | |
6a632136 | 294 | fdisk_get_units_per_sector(cxt)); |
77d6a70a | 295 | } else { |
757cefbb | 296 | fdisk_ask_set_query(ask, _("Last sector, +/-sectors or +/-size{K,M,G,T,P}")); |
77d6a70a KZ |
297 | fdisk_ask_number_set_unit(ask,cxt->sector_size); |
298 | } | |
682802db | 299 | |
77d6a70a KZ |
300 | fdisk_ask_number_set_low(ask, fdisk_cround(cxt, begin)); |
301 | fdisk_ask_number_set_default(ask, fdisk_cround(cxt, end)); | |
302 | fdisk_ask_number_set_high(ask, fdisk_cround(cxt, end)); | |
303 | fdisk_ask_number_set_base(ask, fdisk_cround(cxt, begin)); | |
757cefbb | 304 | fdisk_ask_number_set_wrap_negative(ask, 1); /* wrap negative around high */ |
0f639e54 | 305 | |
77d6a70a KZ |
306 | rc = fdisk_do_ask(cxt, ask); |
307 | end = fdisk_ask_number_get_result(ask); | |
a3d83488 | 308 | fdisk_unref_ask(ask); |
77d6a70a KZ |
309 | if (rc) |
310 | return rc; | |
6a632136 | 311 | if (fdisk_use_cylinders(cxt)) |
77d6a70a KZ |
312 | end = end * d->d_secpercyl - 1; |
313 | } | |
0f639e54 | 314 | |
0efc6c57 KZ |
315 | d->d_partitions[i].p_size = end - begin + 1; |
316 | d->d_partitions[i].p_offset = begin; | |
317 | d->d_partitions[i].p_fstype = BSD_FS_UNUSED; | |
8254c3a5 | 318 | |
0b08fb07 KZ |
319 | if (i >= d->d_npartitions) |
320 | d->d_npartitions = i + 1; | |
0efc6c57 | 321 | cxt->label->nparts_cur = d->d_npartitions; |
acf263d5 | 322 | |
77d6a70a | 323 | if (pa && pa->type) |
7f63194a | 324 | set_parttype(cxt, i, pa->type); |
77d6a70a | 325 | |
0b08fb07 | 326 | fdisk_label_set_changed(cxt->label, 1); |
c3bc7483 KZ |
327 | if (partno) |
328 | *partno = i; | |
8254c3a5 | 329 | return 0; |
0f639e54 DB |
330 | } |
331 | ||
7f63194a KZ |
332 | static int bsd_set_partition(struct fdisk_context *cxt, size_t n, |
333 | struct fdisk_partition *pa) | |
334 | { | |
335 | struct bsd_partition *p; | |
336 | struct fdisk_bsd_label *l = self_label(cxt); | |
337 | struct bsd_disklabel *d = self_disklabel(cxt); | |
338 | ||
339 | if (n >= d->d_npartitions) | |
340 | return -EINVAL; | |
341 | ||
342 | p = &d->d_partitions[n]; | |
343 | ||
344 | /* we have to stay within parental DOS partition */ | |
ecf40cda KZ |
345 | if (l->dos_part && (fdisk_partition_has_start(pa) || |
346 | fdisk_partition_has_size(pa))) { | |
347 | ||
0073a4cf KZ |
348 | fdisk_sector_t dosbegin = dos_partition_get_start(l->dos_part); |
349 | fdisk_sector_t dosend = dosbegin + dos_partition_get_size(l->dos_part) - 1; | |
350 | fdisk_sector_t begin = fdisk_partition_has_start(pa) ? pa->start : p->p_offset; | |
351 | fdisk_sector_t end = begin + (fdisk_partition_has_size(pa) ? pa->size : p->p_size) - 1; | |
7f63194a KZ |
352 | |
353 | if (begin < dosbegin || begin > dosend) | |
354 | return -ERANGE; | |
355 | if (end < dosbegin || end > dosend) | |
356 | return -ERANGE; | |
357 | } | |
358 | ||
359 | if (pa->type) { | |
360 | int rc = set_parttype(cxt, n, pa->type); | |
361 | if (rc) | |
362 | return rc; | |
363 | } | |
364 | ||
ecf40cda | 365 | if (fdisk_partition_has_start(pa)) |
7f63194a | 366 | d->d_partitions[n].p_offset = pa->start; |
ecf40cda | 367 | if (fdisk_partition_has_size(pa)) |
7f63194a KZ |
368 | d->d_partitions[n].p_size = pa->size; |
369 | ||
370 | fdisk_label_set_changed(cxt->label, 1); | |
371 | return 0; | |
372 | } | |
373 | ||
374 | ||
75d059ef | 375 | /* Returns 0 on success, < 0 on error. */ |
2872ffa0 | 376 | static int bsd_create_disklabel(struct fdisk_context *cxt) |
639f1d56 | 377 | { |
75d059ef | 378 | int rc, yes = 0; |
0efc6c57 | 379 | struct bsd_disklabel *d = self_disklabel(cxt); |
9ffeb235 | 380 | |
818d7924 | 381 | fdisk_info(cxt, _("The device %s does not contain BSD disklabel."), cxt->dev_path); |
75d059ef KZ |
382 | rc = fdisk_ask_yesno(cxt, |
383 | _("Do you want to create a BSD disklabel?"), | |
384 | &yes); | |
243631e7 | 385 | if (rc) |
818d7924 | 386 | return rc; |
243631e7 KZ |
387 | if (!yes) |
388 | return 1; | |
818d7924 | 389 | if (cxt->parent) { |
0efc6c57 | 390 | rc = bsd_assign_dos_partition(cxt); |
818d7924 KZ |
391 | if (rc == 1) |
392 | /* not found DOS partition usable for BSD label */ | |
393 | rc = -EINVAL; | |
394 | } | |
395 | if (rc) | |
396 | return rc; | |
397 | ||
2872ffa0 | 398 | rc = bsd_initlabel(cxt); |
818d7924 | 399 | if (!rc) { |
0efc6c57 | 400 | cxt->label->nparts_cur = d->d_npartitions; |
818d7924 | 401 | cxt->label->nparts_max = BSD_MAXPARTITIONS; |
639f1d56 | 402 | } |
75d059ef KZ |
403 | |
404 | return rc; | |
639f1d56 DB |
405 | } |
406 | ||
2872ffa0 | 407 | static int bsd_delete_part( |
9ffeb235 KZ |
408 | struct fdisk_context *cxt, |
409 | size_t partnum) | |
726f69e2 | 410 | { |
0efc6c57 KZ |
411 | struct bsd_disklabel *d = self_disklabel(cxt); |
412 | ||
413 | d->d_partitions[partnum].p_size = 0; | |
414 | d->d_partitions[partnum].p_offset = 0; | |
415 | d->d_partitions[partnum].p_fstype = BSD_FS_UNUSED; | |
9ffeb235 | 416 | |
0efc6c57 KZ |
417 | if (d->d_npartitions == partnum + 1) |
418 | while (!d->d_partitions[d->d_npartitions - 1].p_size) | |
419 | d->d_npartitions--; | |
1f5eb51b | 420 | |
0efc6c57 | 421 | cxt->label->nparts_cur = d->d_npartitions; |
9ffeb235 | 422 | fdisk_label_set_changed(cxt->label, 1); |
1f5eb51b | 423 | return 0; |
726f69e2 KZ |
424 | } |
425 | ||
5989556a | 426 | static int bsd_get_disklabel_item(struct fdisk_context *cxt, struct fdisk_labelitem *item) |
9ffeb235 | 427 | { |
5989556a KZ |
428 | struct bsd_disklabel *d; |
429 | int rc = 0; | |
50ea6795 | 430 | |
e563f055 KZ |
431 | assert(cxt); |
432 | assert(cxt->label); | |
aa36c2cf | 433 | assert(fdisk_is_label(cxt, BSD)); |
e563f055 | 434 | |
5989556a | 435 | d = self_disklabel(cxt); |
e563f055 | 436 | |
5989556a KZ |
437 | switch (item->id) { |
438 | case BSD_LABELITEM_TYPE: | |
439 | item->name = _("Type"); | |
440 | item->type = 's'; | |
441 | if ((unsigned) d->d_type < BSD_DKMAXTYPES) { | |
442 | item->data.str = strdup(bsd_dktypenames[d->d_type]); | |
443 | if (!item->data.str) | |
444 | rc = -ENOMEM; | |
445 | } else if (asprintf(&item->data.str, "%d", d->d_type) < 0) | |
446 | rc = -ENOMEM; | |
447 | break; | |
448 | case BSD_LABELITEM_DISK: | |
449 | item->name = _("Disk"); | |
450 | item->type = 's'; | |
451 | item->data.str = strndup(d->d_typename, sizeof(d->d_typename)); | |
452 | if (!item->data.str) | |
453 | rc = -ENOMEM; | |
454 | break; | |
455 | case BSD_LABELITEM_PACKNAME: | |
456 | item->name = _("Packname"); | |
457 | item->type = 's'; | |
458 | item->data.str = strndup(d->d_packname, sizeof(d->d_packname)); | |
459 | if (!item->data.str) | |
460 | rc = -ENOMEM; | |
461 | break; | |
462 | case BSD_LABELITEM_FLAGS: | |
463 | item->name = _("Flags"); | |
464 | item->type = 's'; | |
465 | item->data.str = strdup( | |
e563f055 KZ |
466 | d->d_flags & BSD_D_REMOVABLE ? _(" removable") : |
467 | d->d_flags & BSD_D_ECC ? _(" ecc") : | |
468 | d->d_flags & BSD_D_BADSECT ? _(" badsect") : ""); | |
5989556a KZ |
469 | if (!item->data.str) |
470 | rc = -ENOMEM; | |
471 | break; | |
e563f055 | 472 | |
5989556a KZ |
473 | /* On various machines the fields of *lp are short/int/long */ |
474 | /* In order to avoid problems, we cast them all uint64. */ | |
475 | case BSD_LABELITEM_SECSIZE: | |
476 | item->name = _("Bytes/Sector"); | |
477 | item->type = 'j'; | |
478 | item->data.num64 = (uint64_t) d->d_secsize; | |
479 | break; | |
480 | case BSD_LABELITEM_NTRACKS: | |
481 | item->name = _("Tracks/Cylinder"); | |
482 | item->type = 'j'; | |
483 | item->data.num64 = (uint64_t) d->d_ntracks; | |
484 | break; | |
485 | case BSD_LABELITEM_SECPERCYL: | |
486 | item->name = _("Sectors/Cylinder"); | |
487 | item->data.num64 = (uint64_t) d->d_secpercyl; | |
488 | item->type = 'j'; | |
489 | break; | |
490 | case BSD_LABELITEM_CYLINDERS: | |
491 | item->name = _("Cylinders"); | |
492 | item->data.num64 = (uint64_t) d->d_ncylinders; | |
493 | item->type = 'j'; | |
494 | break; | |
495 | case BSD_LABELITEM_RPM: | |
496 | item->name = _("Rpm"); | |
497 | item->data.num64 = (uint64_t) d->d_rpm; | |
498 | item->type = 'j'; | |
499 | break; | |
500 | case BSD_LABELITEM_INTERLEAVE: | |
501 | item->name = _("Interleave"); | |
502 | item->data.num64 = (uint64_t) d->d_interleave; | |
503 | item->type = 'j'; | |
504 | break; | |
505 | case BSD_LABELITEM_TRACKSKEW: | |
506 | item->name = _("Trackskew"); | |
507 | item->data.num64 = (uint64_t) d->d_trackskew; | |
508 | item->type = 'j'; | |
509 | break; | |
510 | case BSD_LABELITEM_CYLINDERSKEW: | |
511 | item->name = _("Cylinderskew"); | |
512 | item->data.num64 = (uint64_t) d->d_cylskew; | |
513 | item->type = 'j'; | |
514 | break; | |
515 | case BSD_LABELITEM_HEADSWITCH: | |
516 | item->name = _("Headswitch"); | |
517 | item->data.num64 = (uint64_t) d->d_headswitch; | |
518 | item->type = 'j'; | |
519 | break; | |
520 | case BSD_LABELITEM_TRKSEEK: | |
521 | item->name = _("Track-to-track seek"); | |
522 | item->data.num64 = (uint64_t) d->d_trkseek; | |
523 | item->type = 'j'; | |
524 | break; | |
525 | default: | |
526 | if (item->id < __FDISK_NLABELITEMS) | |
9e930041 | 527 | rc = 1; /* unsupported generic item */ |
5989556a KZ |
528 | else |
529 | rc = 2; /* out of range */ | |
530 | break; | |
e563f055 KZ |
531 | } |
532 | ||
5989556a | 533 | return rc; |
d48419f3 | 534 | } |
e563f055 | 535 | |
d48419f3 KZ |
536 | static int bsd_get_partition(struct fdisk_context *cxt, size_t n, |
537 | struct fdisk_partition *pa) | |
538 | { | |
539 | struct bsd_partition *p; | |
540 | struct bsd_disklabel *d = self_disklabel(cxt); | |
e563f055 | 541 | |
d48419f3 KZ |
542 | assert(cxt); |
543 | assert(cxt->label); | |
aa36c2cf | 544 | assert(fdisk_is_label(cxt, BSD)); |
e563f055 | 545 | |
d48419f3 KZ |
546 | if (n >= d->d_npartitions) |
547 | return -EINVAL; | |
e563f055 | 548 | |
d48419f3 | 549 | p = &d->d_partitions[n]; |
e563f055 | 550 | |
d48419f3 KZ |
551 | pa->used = p->p_size ? 1 : 0; |
552 | if (!pa->used) | |
553 | return 0; | |
e563f055 | 554 | |
6a632136 | 555 | if (fdisk_use_cylinders(cxt) && d->d_secpercyl) { |
d48419f3 | 556 | pa->start_post = p->p_offset % d->d_secpercyl ? '*' : ' '; |
d48419f3 | 557 | pa->end_post = (p->p_offset + p->p_size) % d->d_secpercyl ? '*' : ' '; |
e563f055 KZ |
558 | } |
559 | ||
41050b7e | 560 | pa->start = p->p_offset; |
77d6a70a | 561 | pa->size = p->p_size; |
a699b27d | 562 | pa->type = bsd_partition_parttype(cxt, p); |
e563f055 | 563 | |
d48419f3 KZ |
564 | if (p->p_fstype == BSD_FS_UNUSED || p->p_fstype == BSD_FS_BSDFFS) { |
565 | pa->fsize = p->p_fsize; | |
566 | pa->bsize = p->p_fsize * p->p_frag; | |
567 | } | |
568 | if (p->p_fstype == BSD_FS_BSDFFS) | |
569 | pa->cpg = p->p_cpg; | |
570 | ||
571 | return 0; | |
726f69e2 KZ |
572 | } |
573 | ||
6a0b468f KZ |
574 | static uint32_t ask_uint32(struct fdisk_context *cxt, |
575 | uint32_t dflt, char *mesg) | |
576 | { | |
577 | uintmax_t res; | |
578 | ||
579 | if (fdisk_ask_number(cxt, min(dflt, (uint32_t) 1), dflt, | |
580 | UINT32_MAX, mesg, &res) == 0) | |
581 | return res; | |
582 | return dflt; | |
583 | } | |
584 | ||
585 | static uint16_t ask_uint16(struct fdisk_context *cxt, | |
586 | uint16_t dflt, char *mesg) | |
726f69e2 | 587 | { |
6a0b468f KZ |
588 | uintmax_t res; |
589 | ||
590 | if (fdisk_ask_number(cxt, min(dflt, (uint16_t) 1), | |
591 | dflt, UINT16_MAX, mesg, &res) == 0) | |
592 | return res; | |
593 | return dflt; | |
50ea6795 | 594 | } |
726f69e2 | 595 | |
a4e6a45e KZ |
596 | /** |
597 | * fdisk_bsd_edit_disklabel: | |
598 | * @cxt: context | |
599 | * | |
600 | * Edits fields in BSD disk label. | |
601 | * | |
602 | * Returns: 0 on success, <0 on error | |
603 | */ | |
b529ea2a | 604 | int fdisk_bsd_edit_disklabel(struct fdisk_context *cxt) |
726f69e2 | 605 | { |
0efc6c57 | 606 | struct bsd_disklabel *d = self_disklabel(cxt); |
6a0b468f | 607 | uintmax_t res; |
726f69e2 | 608 | |
22853e4a | 609 | #if defined (__alpha__) || defined (__ia64__) |
6a0b468f KZ |
610 | if (fdisk_ask_number(cxt, DEFAULT_SECTOR_SIZE, d->d_secsize, |
611 | UINT32_MAX, _("bytes/sector"), &res) == 0) | |
612 | d->d_secsize = res; | |
613 | ||
614 | d->d_nsectors = ask_uint32(cxt, d->d_nsectors, _("sectors/track")); | |
615 | d->d_ntracks = ask_uint32(cxt, d->d_ntracks, _("tracks/cylinder")); | |
616 | d->d_ncylinders = ask_uint32(cxt, d->d_ncylinders ,_("cylinders")); | |
726f69e2 | 617 | #endif |
6a0b468f KZ |
618 | if (fdisk_ask_number(cxt, 1, d->d_nsectors * d->d_ntracks, |
619 | d->d_nsectors * d->d_ntracks, | |
620 | _("sectors/cylinder"), &res) == 0) | |
621 | d->d_secpercyl = res; | |
726f69e2 | 622 | |
6a0b468f KZ |
623 | d->d_rpm = ask_uint16(cxt, d->d_rpm, _("rpm")); |
624 | d->d_interleave = ask_uint16(cxt, d->d_interleave, _("interleave")); | |
625 | d->d_trackskew = ask_uint16(cxt, d->d_trackskew, _("trackskew")); | |
626 | d->d_cylskew = ask_uint16(cxt, d->d_cylskew, _("cylinderskew")); | |
627 | ||
628 | d->d_headswitch = ask_uint32(cxt, d->d_headswitch, _("headswitch")); | |
629 | d->d_trkseek = ask_uint32(cxt, d->d_trkseek, _("track-to-track seek")); | |
630 | ||
631 | d->d_secperunit = d->d_secpercyl * d->d_ncylinders; | |
b529ea2a | 632 | return 0; |
726f69e2 KZ |
633 | } |
634 | ||
2872ffa0 | 635 | static int bsd_get_bootstrap(struct fdisk_context *cxt, |
9e346a02 | 636 | char *path, void *ptr, int size) |
726f69e2 | 637 | { |
9e346a02 | 638 | int fd; |
726f69e2 | 639 | |
9e346a02 | 640 | if ((fd = open(path, O_RDONLY)) < 0) { |
77274f88 | 641 | fdisk_warn(cxt, _("cannot open %s"), path); |
9e346a02 KZ |
642 | return -errno; |
643 | } | |
644 | ||
645 | if (read_all(fd, ptr, size) != size) { | |
77274f88 | 646 | fdisk_warn(cxt, _("cannot read %s"), path); |
9e346a02 KZ |
647 | close(fd); |
648 | return -errno; | |
649 | } | |
650 | ||
0477369a | 651 | fdisk_info(cxt, _("The bootstrap file %s successfully loaded."), path); |
9e346a02 KZ |
652 | close (fd); |
653 | return 0; | |
726f69e2 KZ |
654 | } |
655 | ||
a4e6a45e KZ |
656 | /** |
657 | * fdisk_bsd_write_bootstrap: | |
658 | * @cxt: context | |
659 | * | |
660 | * Install bootstrap file to the BSD device | |
661 | */ | |
b529ea2a | 662 | int fdisk_bsd_write_bootstrap(struct fdisk_context *cxt) |
726f69e2 | 663 | { |
0efc6c57 KZ |
664 | struct bsd_disklabel dl, *d = self_disklabel(cxt); |
665 | struct fdisk_bsd_label *l = self_label(cxt); | |
666 | char *name = d->d_type == BSD_DTYPE_SCSI ? "sd" : "wd"; | |
9e346a02 | 667 | char buf[BUFSIZ]; |
0efc6c57 | 668 | char *res, *dp, *p; |
9e346a02 | 669 | int rc; |
0073a4cf | 670 | fdisk_sector_t sector; |
9e346a02 KZ |
671 | |
672 | snprintf(buf, sizeof(buf), | |
673 | _("Bootstrap: %1$sboot -> boot%1$s (default %1$s)"), | |
674 | name); | |
675 | rc = fdisk_ask_string(cxt, buf, &res); | |
676 | if (rc) | |
677 | goto done; | |
678 | if (res && *res) | |
679 | name = res; | |
680 | ||
681 | snprintf(buf, sizeof(buf), "%s/%sboot", BSD_LINUX_BOOTDIR, name); | |
2872ffa0 | 682 | rc = bsd_get_bootstrap(cxt, buf, l->bsdbuffer, (int) d->d_secsize); |
9e346a02 KZ |
683 | if (rc) |
684 | goto done; | |
685 | ||
0efc6c57 | 686 | /* We need a backup of the disklabel (might have changed). */ |
87ed95ff | 687 | dp = &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE]; |
0efc6c57 | 688 | memmove(&dl, dp, sizeof(struct bsd_disklabel)); |
9e346a02 KZ |
689 | |
690 | /* The disklabel will be overwritten by 0's from bootxx anyway */ | |
0efc6c57 | 691 | memset(dp, 0, sizeof(struct bsd_disklabel)); |
9e346a02 KZ |
692 | |
693 | snprintf(buf, sizeof(buf), "%s/boot%s", BSD_LINUX_BOOTDIR, name); | |
2872ffa0 | 694 | rc = bsd_get_bootstrap(cxt, buf, |
87ed95ff | 695 | &l->bsdbuffer[d->d_secsize], |
0efc6c57 | 696 | (int) d->d_bbsize - d->d_secsize); |
9e346a02 KZ |
697 | if (rc) |
698 | goto done; | |
699 | ||
700 | /* check end of the bootstrap */ | |
0efc6c57 | 701 | for (p = dp; p < dp + sizeof(struct bsd_disklabel); p++) { |
9e346a02 KZ |
702 | if (!*p) |
703 | continue; | |
fd56121a | 704 | fdisk_warnx(cxt, _("Bootstrap overlaps with disklabel!")); |
9e346a02 KZ |
705 | return -EINVAL; |
706 | } | |
726f69e2 | 707 | |
9e346a02 | 708 | /* move disklabel back */ |
0efc6c57 | 709 | memmove(dp, &dl, sizeof(struct bsd_disklabel)); |
726f69e2 | 710 | |
9e346a02 | 711 | sector = 0; |
0efc6c57 KZ |
712 | if (l->dos_part) |
713 | sector = dos_partition_get_start(l->dos_part); | |
714 | #if defined (__alpha__) | |
87ed95ff | 715 | alpha_bootblock_checksum(l->bsdbuffer); |
726f69e2 | 716 | #endif |
bb58112e | 717 | if (lseek(cxt->dev_fd, (off_t) sector * DEFAULT_SECTOR_SIZE, SEEK_SET) == -1) { |
77274f88 | 718 | fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path); |
9e346a02 KZ |
719 | rc = -errno; |
720 | goto done; | |
721 | } | |
87ed95ff | 722 | if (write_all(cxt->dev_fd, l->bsdbuffer, BSD_BBSIZE)) { |
77274f88 | 723 | fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path); |
9e346a02 KZ |
724 | rc = -errno; |
725 | goto done; | |
726 | } | |
726f69e2 | 727 | |
0477369a | 728 | fdisk_info(cxt, _("Bootstrap installed on %s."), cxt->dev_path); |
296b856d | 729 | sync_disks(cxt); |
726f69e2 | 730 | |
9e346a02 KZ |
731 | rc = 0; |
732 | done: | |
733 | free(res); | |
734 | return rc; | |
726f69e2 KZ |
735 | } |
736 | ||
2872ffa0 | 737 | static unsigned short bsd_dkcksum (struct bsd_disklabel *lp) |
0bf367ed | 738 | { |
04d0701e | 739 | unsigned char *ptr, *end; |
95961ee2 | 740 | unsigned short sum = 0; |
50ea6795 | 741 | |
04d0701e KZ |
742 | ptr = (unsigned char *) lp; |
743 | end = (unsigned char *) &lp->d_partitions[lp->d_npartitions]; | |
744 | ||
745 | while (ptr < end) { | |
746 | unsigned short val; | |
747 | ||
748 | memcpy(&val, ptr, sizeof(unsigned short)); | |
749 | sum ^= val; | |
750 | ||
751 | ptr += sizeof(unsigned short); | |
752 | } | |
63cccae4 | 753 | return sum; |
726f69e2 KZ |
754 | } |
755 | ||
2872ffa0 | 756 | static int bsd_initlabel (struct fdisk_context *cxt) |
75d059ef | 757 | { |
0efc6c57 KZ |
758 | struct fdisk_bsd_label *l = self_label(cxt); |
759 | struct bsd_disklabel *d = self_disklabel(cxt); | |
66ea9847 | 760 | struct bsd_partition *pp; |
726f69e2 | 761 | |
66ea9847 | 762 | memset (d, 0, sizeof (struct bsd_disklabel)); |
726f69e2 | 763 | |
63cccae4 | 764 | d -> d_magic = BSD_DISKMAGIC; |
726f69e2 | 765 | |
823f0fd1 | 766 | if (strncmp (cxt->dev_path, "/dev/sd", 7) == 0) |
63cccae4 KZ |
767 | d -> d_type = BSD_DTYPE_SCSI; |
768 | else | |
769 | d -> d_type = BSD_DTYPE_ST506; | |
726f69e2 | 770 | |
22853e4a | 771 | #if !defined (__alpha__) |
63cccae4 | 772 | d -> d_flags = BSD_D_DOSPART; |
726f69e2 | 773 | #else |
63cccae4 | 774 | d -> d_flags = 0; |
726f69e2 | 775 | #endif |
bb58112e | 776 | d -> d_secsize = DEFAULT_SECTOR_SIZE; /* bytes/sector */ |
24cd580b DB |
777 | d -> d_nsectors = cxt->geom.sectors; /* sectors/track */ |
778 | d -> d_ntracks = cxt->geom.heads; /* tracks/cylinder (heads) */ | |
779 | d -> d_ncylinders = cxt->geom.cylinders; | |
780 | d -> d_secpercyl = cxt->geom.sectors * cxt->geom.heads;/* sectors/cylinder */ | |
63cccae4 KZ |
781 | if (d -> d_secpercyl == 0) |
782 | d -> d_secpercyl = 1; /* avoid segfaults */ | |
783 | d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders; | |
784 | ||
785 | d -> d_rpm = 3600; | |
786 | d -> d_interleave = 1; | |
787 | d -> d_trackskew = 0; | |
788 | d -> d_cylskew = 0; | |
789 | d -> d_headswitch = 0; | |
790 | d -> d_trkseek = 0; | |
791 | ||
792 | d -> d_magic2 = BSD_DISKMAGIC; | |
793 | d -> d_bbsize = BSD_BBSIZE; | |
794 | d -> d_sbsize = BSD_SBSIZE; | |
726f69e2 | 795 | |
0efc6c57 KZ |
796 | if (l->dos_part) { |
797 | d->d_npartitions = 4; | |
d48419f3 KZ |
798 | |
799 | pp = &d->d_partitions[2]; /* Partition C should be the NetBSD partition */ | |
0efc6c57 KZ |
800 | pp->p_offset = dos_partition_get_start(l->dos_part); |
801 | pp->p_size = dos_partition_get_size(l->dos_part); | |
802 | pp->p_fstype = BSD_FS_UNUSED; | |
d48419f3 KZ |
803 | |
804 | pp = &d -> d_partitions[3]; /* Partition D should be the whole disk */ | |
0efc6c57 KZ |
805 | pp->p_offset = 0; |
806 | pp->p_size = d->d_secperunit; | |
807 | pp->p_fstype = BSD_FS_UNUSED; | |
808 | } else { | |
809 | d->d_npartitions = 3; | |
d48419f3 KZ |
810 | |
811 | pp = &d->d_partitions[2]; /* Partition C should be the whole disk */ | |
0efc6c57 KZ |
812 | pp->p_offset = 0; |
813 | pp->p_size = d->d_secperunit; | |
814 | pp->p_fstype = BSD_FS_UNUSED; | |
815 | } | |
726f69e2 | 816 | |
75d059ef | 817 | return 0; |
726f69e2 KZ |
818 | } |
819 | ||
63cccae4 | 820 | /* |
2872ffa0 | 821 | * Read a bsd_disklabel from sector 0 or from the starting sector of p. |
818d7924 | 822 | * If it has the right magic, return 0. |
63cccae4 | 823 | */ |
2872ffa0 | 824 | static int bsd_readlabel(struct fdisk_context *cxt) |
726f69e2 | 825 | { |
0efc6c57 KZ |
826 | struct fdisk_bsd_label *l; |
827 | struct bsd_disklabel *d; | |
0dd3dfb8 KZ |
828 | int t; |
829 | off_t offset = 0; | |
726f69e2 | 830 | |
0efc6c57 KZ |
831 | l = self_label(cxt); |
832 | d = self_disklabel(cxt); | |
acf263d5 | 833 | |
0efc6c57 | 834 | if (l->dos_part) |
0dd3dfb8 KZ |
835 | /* BSD is nested within DOS partition, get the begin of the |
836 | * partition. Note that DOS uses native sector size. */ | |
0efc6c57 | 837 | offset = dos_partition_get_start(l->dos_part) * cxt->sector_size; |
726f69e2 | 838 | |
0dd3dfb8 | 839 | if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1) |
818d7924 | 840 | return -1; |
87ed95ff | 841 | if (read_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer)) < 0) |
0dd3dfb8 | 842 | return errno ? -errno : -1; |
726f69e2 | 843 | |
0dd3dfb8 KZ |
844 | /* The offset to begin of the disk label. Note that BSD uses |
845 | * 512-byte (default) sectors. */ | |
87ed95ff | 846 | memmove(d, &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE |
0efc6c57 | 847 | + BSD_LABELOFFSET], sizeof(*d)); |
726f69e2 | 848 | |
0dd3dfb8 | 849 | if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC) { |
88141067 | 850 | DBG(LABEL, ul_debug("not found magic")); |
818d7924 | 851 | return -1; |
e36e1631 | 852 | } |
726f69e2 | 853 | |
0dd3dfb8 KZ |
854 | for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) { |
855 | d->d_partitions[t].p_size = 0; | |
856 | d->d_partitions[t].p_offset = 0; | |
857 | d->d_partitions[t].p_fstype = BSD_FS_UNUSED; | |
63cccae4 KZ |
858 | } |
859 | ||
0dd3dfb8 KZ |
860 | if (d->d_npartitions > BSD_MAXPARTITIONS) |
861 | fdisk_warnx(cxt, ("Too many partitions (%d, maximum is %d)."), | |
862 | d->d_npartitions, BSD_MAXPARTITIONS); | |
acf263d5 | 863 | |
77d6a70a KZ |
864 | /* let's follow in-PT geometry */ |
865 | cxt->geom.sectors = d->d_nsectors; | |
866 | cxt->geom.heads = d->d_ntracks; | |
867 | cxt->geom.cylinders = d->d_ncylinders; | |
868 | ||
502dd53c KZ |
869 | if (fdisk_has_user_device_geometry(cxt)) |
870 | fdisk_apply_user_device_properties(cxt); | |
871 | ||
acf263d5 KZ |
872 | cxt->label->nparts_cur = d->d_npartitions; |
873 | cxt->label->nparts_max = BSD_MAXPARTITIONS; | |
88141067 | 874 | DBG(LABEL, ul_debug("read BSD label")); |
818d7924 | 875 | return 0; |
726f69e2 KZ |
876 | } |
877 | ||
d5b2b8db | 878 | static int bsd_write_disklabel(struct fdisk_context *cxt) |
726f69e2 | 879 | { |
0dd3dfb8 | 880 | off_t offset = 0; |
d5b2b8db KZ |
881 | struct fdisk_bsd_label *l = self_label(cxt); |
882 | struct bsd_disklabel *d = self_disklabel(cxt); | |
0efc6c57 | 883 | |
726f69e2 | 884 | |
0efc6c57 KZ |
885 | if (l->dos_part) |
886 | offset = dos_partition_get_start(l->dos_part) * cxt->sector_size; | |
726f69e2 | 887 | |
0dd3dfb8 | 888 | d->d_checksum = 0; |
2872ffa0 | 889 | d->d_checksum = bsd_dkcksum(d); |
726f69e2 | 890 | |
88f91eb4 | 891 | /* Update label within boot block. */ |
87ed95ff | 892 | memmove(&l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE |
0efc6c57 | 893 | + BSD_LABELOFFSET], d, sizeof(*d)); |
726f69e2 KZ |
894 | |
895 | #if defined (__alpha__) && BSD_LABELSECTOR == 0 | |
88f91eb4 | 896 | /* Write the checksum to the end of the first sector. */ |
87ed95ff | 897 | alpha_bootblock_checksum(l->bsdbuffer); |
726f69e2 | 898 | #endif |
0dd3dfb8 | 899 | if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1) { |
77274f88 | 900 | fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path); |
0dd3dfb8 KZ |
901 | return -errno; |
902 | } | |
87ed95ff | 903 | if (write_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer))) { |
77274f88 | 904 | fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path); |
0dd3dfb8 KZ |
905 | return -errno; |
906 | } | |
296b856d | 907 | sync_disks(cxt); |
ac1a559a | 908 | |
5cea5be0 | 909 | if (cxt->parent && fdisk_label_is_changed(cxt->parent->label)) |
e906ab3c | 910 | fdisk_info(cxt, _("Disklabel written to %s. (Don't forget to write the %s disklabel too.)"), |
5cea5be0 KZ |
911 | cxt->dev_path, cxt->parent->dev_path); |
912 | else | |
913 | fdisk_info(cxt, _("Disklabel written to %s."), cxt->dev_path); | |
0dd3dfb8 | 914 | return 0; |
726f69e2 KZ |
915 | } |
916 | ||
296b856d | 917 | static void sync_disks(struct fdisk_context *cxt) |
726f69e2 | 918 | { |
296b856d KZ |
919 | fdisk_info(cxt, _("Syncing disks.")); |
920 | sync(); | |
726f69e2 KZ |
921 | } |
922 | ||
2872ffa0 | 923 | static int bsd_translate_fstype (int linux_type) |
726f69e2 | 924 | { |
bcef4db4 KZ |
925 | switch (linux_type) { |
926 | case 0x01: /* DOS 12-bit FAT */ | |
927 | case 0x04: /* DOS 16-bit <32M */ | |
928 | case 0x06: /* DOS 16-bit >=32M */ | |
929 | case 0xe1: /* DOS access */ | |
930 | case 0xe3: /* DOS R/O */ | |
0b166f24 | 931 | #if !defined (__alpha__) |
bcef4db4 KZ |
932 | case 0xf2: /* DOS secondary */ |
933 | return BSD_FS_MSDOS; | |
0b166f24 | 934 | #endif |
bcef4db4 KZ |
935 | case 0x07: /* OS/2 HPFS */ |
936 | return BSD_FS_HPFS; | |
937 | default: | |
19c2cc4e | 938 | break; |
bcef4db4 | 939 | } |
19c2cc4e KZ |
940 | |
941 | return BSD_FS_OTHER; | |
726f69e2 KZ |
942 | } |
943 | ||
a4e6a45e KZ |
944 | /** |
945 | * fdisk_bsd_link_partition: | |
946 | * @cxt: context | |
947 | * | |
948 | * Links partition from parent (DOS) to nested BSD partition table. | |
949 | * | |
950 | * Returns: 0 on success, <0 on error | |
e09435aa | 951 | */ |
b529ea2a | 952 | int fdisk_bsd_link_partition(struct fdisk_context *cxt) |
726f69e2 | 953 | { |
0b08fb07 KZ |
954 | size_t k, i; |
955 | int rc; | |
f540fe15 | 956 | struct dos_partition *p; |
0efc6c57 | 957 | struct bsd_disklabel *d = self_disklabel(cxt); |
726f69e2 | 958 | |
aa36c2cf | 959 | if (!cxt->parent || !fdisk_is_label(cxt->parent, DOS)) { |
09af3db4 | 960 | fdisk_warnx(cxt, _("BSD label is not nested within a DOS partition.")); |
b529ea2a KZ |
961 | return -EINVAL; |
962 | } | |
b4fb2a61 | 963 | |
0b08fb07 | 964 | /* ask for DOS partition */ |
b529ea2a KZ |
965 | rc = fdisk_ask_partnum(cxt->parent, &k, FALSE); |
966 | if (rc) | |
967 | return rc; | |
0b08fb07 KZ |
968 | /* ask for BSD partition */ |
969 | rc = fdisk_ask_partnum(cxt, &i, TRUE); | |
b529ea2a KZ |
970 | if (rc) |
971 | return rc; | |
726f69e2 | 972 | |
0b08fb07 KZ |
973 | if (i >= BSD_MAXPARTITIONS) |
974 | return -EINVAL; | |
975 | ||
af0df606 | 976 | p = fdisk_dos_get_partition(cxt->parent, k); |
22853e4a | 977 | |
0efc6c57 KZ |
978 | d->d_partitions[i].p_size = dos_partition_get_size(p); |
979 | d->d_partitions[i].p_offset = dos_partition_get_start(p); | |
2872ffa0 | 980 | d->d_partitions[i].p_fstype = bsd_translate_fstype(p->sys_ind); |
b529ea2a | 981 | |
0b08fb07 KZ |
982 | if (i >= d->d_npartitions) |
983 | d->d_npartitions = i + 1; | |
984 | ||
985 | cxt->label->nparts_cur = d->d_npartitions; | |
986 | fdisk_label_set_changed(cxt->label, 1); | |
987 | ||
0477369a | 988 | fdisk_info(cxt, _("BSD partition '%c' linked to DOS partition %zu."), |
829f4206 | 989 | 'a' + (int) i, k + 1); |
b529ea2a | 990 | return 0; |
726f69e2 | 991 | } |
726f69e2 | 992 | |
02460b8a | 993 | |
8c0a7f91 | 994 | static int bsd_partition_is_used( |
e36e1631 | 995 | struct fdisk_context *cxt, |
8c0a7f91 | 996 | size_t partnum) |
e36e1631 | 997 | { |
0efc6c57 | 998 | struct bsd_disklabel *d = self_disklabel(cxt); |
e36e1631 | 999 | |
8c0a7f91 KZ |
1000 | if (partnum >= BSD_MAXPARTITIONS) |
1001 | return 0; | |
e36e1631 | 1002 | |
8c0a7f91 | 1003 | return d->d_partitions[partnum].p_size ? 1 : 0; |
e36e1631 KZ |
1004 | } |
1005 | ||
1006 | ||
0c5d095e | 1007 | static const struct fdisk_label_operations bsd_operations = |
b8855c86 | 1008 | { |
818d7924 | 1009 | .probe = bsd_probe_label, |
5989556a | 1010 | .get_item = bsd_get_disklabel_item, |
2872ffa0 KZ |
1011 | .write = bsd_write_disklabel, |
1012 | .create = bsd_create_disklabel, | |
d48419f3 | 1013 | |
e11c6684 | 1014 | .del_part = bsd_delete_part, |
d48419f3 | 1015 | .get_part = bsd_get_partition, |
7f63194a | 1016 | .set_part = bsd_set_partition, |
77d6a70a | 1017 | .add_part = bsd_add_partition, |
d48419f3 | 1018 | |
8c0a7f91 | 1019 | .part_is_used = bsd_partition_is_used, |
b8855c86 | 1020 | }; |
0c5d095e | 1021 | |
bd85d11f | 1022 | static const struct fdisk_field bsd_fields[] = |
d48419f3 | 1023 | { |
bd85d11f KZ |
1024 | { FDISK_FIELD_DEVICE, N_("Slice"), 1, 0 }, |
1025 | { FDISK_FIELD_START, N_("Start"), 5, FDISK_FIELDFL_NUMBER }, | |
1026 | { FDISK_FIELD_END, N_("End"), 5, FDISK_FIELDFL_NUMBER }, | |
1027 | { FDISK_FIELD_SECTORS, N_("Sectors"), 5, FDISK_FIELDFL_NUMBER }, | |
1028 | { FDISK_FIELD_CYLINDERS,N_("Cylinders"), 5, FDISK_FIELDFL_NUMBER }, | |
1029 | { FDISK_FIELD_SIZE, N_("Size"), 5, FDISK_FIELDFL_NUMBER }, | |
1030 | { FDISK_FIELD_TYPE, N_("Type"), 8, 0 }, | |
1031 | { FDISK_FIELD_FSIZE, N_("Fsize"), 5, FDISK_FIELDFL_NUMBER }, | |
1032 | { FDISK_FIELD_BSIZE, N_("Bsize"), 5, FDISK_FIELDFL_NUMBER }, | |
1033 | { FDISK_FIELD_CPG, N_("Cpg"), 5, FDISK_FIELDFL_NUMBER } | |
d48419f3 | 1034 | }; |
0c5d095e KZ |
1035 | |
1036 | /* | |
1037 | * allocates BSD label driver | |
1038 | */ | |
01aec449 | 1039 | struct fdisk_label *fdisk_new_bsd_label(struct fdisk_context *cxt __attribute__ ((__unused__))) |
0c5d095e KZ |
1040 | { |
1041 | struct fdisk_label *lb; | |
1042 | struct fdisk_bsd_label *bsd; | |
1043 | ||
0c5d095e KZ |
1044 | bsd = calloc(1, sizeof(*bsd)); |
1045 | if (!bsd) | |
1046 | return NULL; | |
1047 | ||
1048 | /* initialize generic part of the driver */ | |
1049 | lb = (struct fdisk_label *) bsd; | |
1050 | lb->name = "bsd"; | |
22ddf547 | 1051 | lb->id = FDISK_DISKLABEL_BSD; |
0c5d095e | 1052 | lb->op = &bsd_operations; |
2872ffa0 | 1053 | lb->parttypes = bsd_fstypes; |
a745611d | 1054 | lb->nparttypes = ARRAY_SIZE(bsd_fstypes) - 1; |
0c5d095e | 1055 | |
bd85d11f KZ |
1056 | lb->fields = bsd_fields; |
1057 | lb->nfields = ARRAY_SIZE(bsd_fields); | |
d48419f3 | 1058 | |
e36e1631 | 1059 | lb->flags |= FDISK_LABEL_FL_INCHARS_PARTNO; |
caad8583 | 1060 | lb->flags |= FDISK_LABEL_FL_REQUIRE_GEOMETRY; |
baa7cccc | 1061 | |
0c5d095e KZ |
1062 | return lb; |
1063 | } |