]>
Commit | Line | Data |
---|---|---|
1 | ||
2 | #include "fdiskP.h" | |
3 | #include "cctype.h" | |
4 | ||
5 | ||
6 | /** | |
7 | * SECTION: label | |
8 | * @title: Label | |
9 | * @short_description: disk label (PT) specific data and functions | |
10 | * | |
11 | * The fdisk_new_context() initializes all label drivers, and allocate | |
12 | * per-label specific data struct. This concept can be used to store label specific | |
13 | * settings to the label driver independently on the currently active label | |
14 | * driver. Note that label struct cannot be deallocated, so there is no | |
15 | * reference counting for fdisk_label objects. All is destroyed by | |
16 | * fdisk_unref_context() only. | |
17 | * | |
18 | * Anyway, all label drives share in-memory first sector. The function | |
19 | * fdisk_create_disklabel() overwrites this in-memory sector. But it's possible that | |
20 | * label driver also uses another buffers, for example GPT reads more sectors | |
21 | * from the device. | |
22 | * | |
23 | * All label operations are in-memory only, except fdisk_write_disklabel(). | |
24 | * | |
25 | * All functions that use "struct fdisk_context" rather than "struct | |
26 | * fdisk_label" use the currently active label driver. | |
27 | */ | |
28 | ||
29 | ||
30 | int fdisk_probe_labels(struct fdisk_context *cxt) | |
31 | { | |
32 | size_t i; | |
33 | ||
34 | cxt->label = NULL; | |
35 | ||
36 | for (i = 0; i < cxt->nlabels; i++) { | |
37 | struct fdisk_label *lb = cxt->labels[i]; | |
38 | struct fdisk_label *org = fdisk_get_label(cxt, NULL); | |
39 | int rc; | |
40 | ||
41 | if (!lb->op->probe) | |
42 | continue; | |
43 | if (lb->disabled) { | |
44 | DBG(CXT, ul_debugobj(cxt, "%s: disabled -- ignore", lb->name)); | |
45 | continue; | |
46 | } | |
47 | DBG(CXT, ul_debugobj(cxt, "probing for %s", lb->name)); | |
48 | ||
49 | cxt->label = lb; | |
50 | rc = lb->op->probe(cxt); | |
51 | cxt->label = org; | |
52 | ||
53 | if (rc != 1) { | |
54 | if (lb->op->deinit) | |
55 | lb->op->deinit(lb); /* for sure */ | |
56 | continue; | |
57 | } | |
58 | ||
59 | __fdisk_switch_label(cxt, lb); | |
60 | return 0; | |
61 | } | |
62 | ||
63 | DBG(CXT, ul_debugobj(cxt, "no label found")); | |
64 | return 1; /* not found */ | |
65 | } | |
66 | ||
67 | /** | |
68 | * fdisk_label_get_name: | |
69 | * @lb: label | |
70 | * | |
71 | * Returns: label name | |
72 | */ | |
73 | const char *fdisk_label_get_name(const struct fdisk_label *lb) | |
74 | { | |
75 | return lb ? lb->name : NULL; | |
76 | } | |
77 | ||
78 | /** | |
79 | * fdisk_label_is_labeltype: | |
80 | * @lb: label | |
81 | * | |
82 | * Returns: FDISK_DISKLABEL_*. | |
83 | */ | |
84 | int fdisk_label_get_type(const struct fdisk_label *lb) | |
85 | { | |
86 | return lb->id; | |
87 | } | |
88 | ||
89 | /** | |
90 | * fdisk_label_require_geometry: | |
91 | * @lb: label | |
92 | * | |
93 | * Returns: 1 if label requires CHS geometry | |
94 | */ | |
95 | int fdisk_label_require_geometry(const struct fdisk_label *lb) | |
96 | { | |
97 | assert(lb); | |
98 | ||
99 | return lb->flags & FDISK_LABEL_FL_REQUIRE_GEOMETRY ? 1 : 0; | |
100 | } | |
101 | ||
102 | /** | |
103 | * fdisk_label_get_fields_ids | |
104 | * @lb: label (or NULL for the current label) | |
105 | * @cxt: context | |
106 | * @ids: returns allocated array with FDISK_FIELD_* IDs | |
107 | * @nids: returns number of items in fields | |
108 | * | |
109 | * This function returns the default fields for the label. | |
110 | * | |
111 | * Note that the set of the default fields depends on fdisk_enable_details() | |
112 | * function. If the details are enabled then this function usually returns more | |
113 | * fields. | |
114 | * | |
115 | * Returns: 0 on success, otherwise, a corresponding error. | |
116 | */ | |
117 | int fdisk_label_get_fields_ids( | |
118 | const struct fdisk_label *lb, | |
119 | struct fdisk_context *cxt, | |
120 | int **ids, size_t *nids) | |
121 | { | |
122 | size_t i, n; | |
123 | int *c; | |
124 | ||
125 | if (!cxt || (!lb && !cxt->label)) | |
126 | return -EINVAL; | |
127 | ||
128 | lb = cxt->label; | |
129 | if (!lb->fields || !lb->nfields) | |
130 | return -ENOSYS; | |
131 | c = calloc(lb->nfields, sizeof(int)); | |
132 | if (!c) | |
133 | return -ENOMEM; | |
134 | for (n = 0, i = 0; i < lb->nfields; i++) { | |
135 | int id = lb->fields[i].id; | |
136 | ||
137 | if ((fdisk_is_details(cxt) && | |
138 | (lb->fields[i].flags & FDISK_FIELDFL_EYECANDY)) | |
139 | || (!fdisk_is_details(cxt) && | |
140 | (lb->fields[i].flags & FDISK_FIELDFL_DETAIL)) | |
141 | || (id == FDISK_FIELD_SECTORS && | |
142 | fdisk_use_cylinders(cxt)) | |
143 | || (id == FDISK_FIELD_CYLINDERS && | |
144 | !fdisk_use_cylinders(cxt))) | |
145 | continue; | |
146 | ||
147 | c[n++] = id; | |
148 | } | |
149 | if (ids) | |
150 | *ids = c; | |
151 | else | |
152 | free(c); | |
153 | if (nids) | |
154 | *nids = n; | |
155 | return 0; | |
156 | } | |
157 | ||
158 | /** | |
159 | * fdisk_label_get_fields_ids_all | |
160 | * @lb: label (or NULL for the current label) | |
161 | * @cxt: context | |
162 | * @ids: returns allocated array with FDISK_FIELD_* IDs | |
163 | * @nids: returns number of items in fields | |
164 | * | |
165 | * This function returns all fields for the label. | |
166 | * | |
167 | * Returns: 0 on success, otherwise, a corresponding error. | |
168 | */ | |
169 | int fdisk_label_get_fields_ids_all( | |
170 | const struct fdisk_label *lb, | |
171 | struct fdisk_context *cxt, | |
172 | int **ids, size_t *nids) | |
173 | { | |
174 | size_t i, n; | |
175 | int *c; | |
176 | ||
177 | if (!cxt || (!lb && !cxt->label)) | |
178 | return -EINVAL; | |
179 | ||
180 | lb = cxt->label; | |
181 | if (!lb->fields || !lb->nfields) | |
182 | return -ENOSYS; | |
183 | c = calloc(lb->nfields, sizeof(int)); | |
184 | if (!c) | |
185 | return -ENOMEM; | |
186 | for (n = 0, i = 0; i < lb->nfields; i++) | |
187 | c[n++] = lb->fields[i].id; | |
188 | if (ids) | |
189 | *ids = c; | |
190 | else | |
191 | free(c); | |
192 | if (nids) | |
193 | *nids = n; | |
194 | return 0; | |
195 | } | |
196 | ||
197 | /** | |
198 | * fdisk_label_get_field: | |
199 | * @lb: label | |
200 | * @id: FDISK_FIELD_* | |
201 | * | |
202 | * The field struct describes data stored in struct fdisk_partition. The info | |
203 | * about data is usable for example to generate human readable output (e.g. | |
204 | * fdisk 'p'rint command). See fdisk_partition_to_string() and fdisk code. | |
205 | * | |
206 | * Returns: pointer to static instance of the field. | |
207 | */ | |
208 | const struct fdisk_field *fdisk_label_get_field(const struct fdisk_label *lb, int id) | |
209 | { | |
210 | size_t i; | |
211 | ||
212 | assert(lb); | |
213 | assert(id > 0); | |
214 | ||
215 | for (i = 0; i < lb->nfields; i++) { | |
216 | if (lb->fields[i].id == id) | |
217 | return &lb->fields[i]; | |
218 | } | |
219 | ||
220 | return NULL; | |
221 | } | |
222 | ||
223 | /** | |
224 | * fdisk_label_get_field_by_name | |
225 | * @lb: label | |
226 | * @name: field name | |
227 | * | |
228 | * Returns: pointer to static instance of the field. | |
229 | */ | |
230 | const struct fdisk_field *fdisk_label_get_field_by_name( | |
231 | const struct fdisk_label *lb, | |
232 | const char *name) | |
233 | { | |
234 | size_t i; | |
235 | ||
236 | assert(lb); | |
237 | assert(name); | |
238 | ||
239 | for (i = 0; i < lb->nfields; i++) { | |
240 | if (lb->fields[i].name && c_strcasecmp(lb->fields[i].name, name) == 0) | |
241 | return &lb->fields[i]; | |
242 | } | |
243 | ||
244 | return NULL; | |
245 | } | |
246 | ||
247 | /** | |
248 | * fdisk_write_disklabel: | |
249 | * @cxt: fdisk context | |
250 | * | |
251 | * This function wipes the device (if enabled by fdisk_enable_wipe()) and then | |
252 | * it writes in-memory changes to disk. Be careful! | |
253 | * | |
254 | * Returns: 0 on success, otherwise, a corresponding error. | |
255 | */ | |
256 | int fdisk_write_disklabel(struct fdisk_context *cxt) | |
257 | { | |
258 | if (!cxt || !cxt->label || cxt->readonly) | |
259 | return -EINVAL; | |
260 | if (!cxt->label->op->write) | |
261 | return -ENOSYS; | |
262 | ||
263 | fdisk_do_wipe(cxt); | |
264 | return cxt->label->op->write(cxt); | |
265 | } | |
266 | ||
267 | /** | |
268 | * fdisk_verify_disklabel: | |
269 | * @cxt: fdisk context | |
270 | * | |
271 | * Verifies the partition table. | |
272 | * | |
273 | * Returns: 0 on success, <1 runtime or option errors, >0 number of detected issues | |
274 | */ | |
275 | int fdisk_verify_disklabel(struct fdisk_context *cxt) | |
276 | { | |
277 | if (!cxt || !cxt->label) | |
278 | return -EINVAL; | |
279 | if (!cxt->label->op->verify) | |
280 | return -ENOSYS; | |
281 | if (fdisk_missing_geometry(cxt)) | |
282 | return -EINVAL; | |
283 | ||
284 | return cxt->label->op->verify(cxt); | |
285 | } | |
286 | ||
287 | /** | |
288 | * fdisk_list_disklabel: | |
289 | * @cxt: fdisk context | |
290 | * | |
291 | * Lists details about disklabel, but no partitions. | |
292 | * | |
293 | * This function is based on fdisk_get_disklabel_item() and prints all label | |
294 | * specific information by ASK interface (FDISK_ASKTYPE_INFO, aka fdisk_info()). | |
295 | * The function requires enabled "details" by fdisk_enable_details(). | |
296 | * | |
297 | * It's recommended to use fdisk_get_disklabel_item() if you need better | |
298 | * control on output and formatting. | |
299 | * | |
300 | * Returns: 0 on success, otherwise, a corresponding error. | |
301 | */ | |
302 | int fdisk_list_disklabel(struct fdisk_context *cxt) | |
303 | { | |
304 | int id = 0, rc = 0; | |
305 | struct fdisk_labelitem item = { .id = id }; | |
306 | ||
307 | if (!cxt || !cxt->label) | |
308 | return -EINVAL; | |
309 | ||
310 | if (!cxt->display_details) | |
311 | return 0; | |
312 | ||
313 | /* List all label items */ | |
314 | do { | |
315 | /* rc: < 0 error, 0 success, 1 unknown item, 2 out of range */ | |
316 | rc = fdisk_get_disklabel_item(cxt, id++, &item); | |
317 | if (rc != 0) | |
318 | continue; | |
319 | switch (item.type) { | |
320 | case 'j': | |
321 | fdisk_info(cxt, "%s: %ju", item.name, item.data.num64); | |
322 | break; | |
323 | case 's': | |
324 | if (item.data.str && item.name) | |
325 | fdisk_info(cxt, "%s: %s", item.name, item.data.str); | |
326 | break; | |
327 | } | |
328 | fdisk_reset_labelitem(&item); | |
329 | } while (rc == 0 || rc == 1); | |
330 | ||
331 | return rc < 0 ? rc : 0; | |
332 | } | |
333 | ||
334 | /** | |
335 | * fdisk_create_disklabel: | |
336 | * @cxt: fdisk context | |
337 | * @name: label name | |
338 | * | |
339 | * Creates a new disk label of type @name. If @name is NULL, then it will | |
340 | * create a default system label type, either SUN or DOS. The function | |
341 | * automatically switches the current label driver to @name. The function | |
342 | * fdisk_get_label() returns the current label driver. | |
343 | * | |
344 | * The function modifies in-memory data only. | |
345 | * | |
346 | * Returns: 0 on success, otherwise, a corresponding error. | |
347 | */ | |
348 | int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name) | |
349 | { | |
350 | int haslabel = 0, rc; | |
351 | struct fdisk_label *lb; | |
352 | ||
353 | if (!cxt) | |
354 | return -EINVAL; | |
355 | ||
356 | if (!name) { /* use default label creation */ | |
357 | #ifdef __sparc__ | |
358 | name = "sun"; | |
359 | #else | |
360 | name = "dos"; | |
361 | #endif | |
362 | } | |
363 | ||
364 | if (cxt->label) { | |
365 | fdisk_deinit_label(cxt->label); | |
366 | haslabel = 1; | |
367 | } | |
368 | ||
369 | lb = fdisk_get_label(cxt, name); | |
370 | if (!lb || lb->disabled) | |
371 | return -EINVAL; | |
372 | ||
373 | if (!haslabel || (lb && cxt->label != lb)) | |
374 | fdisk_check_collisions(cxt); | |
375 | ||
376 | if (!lb->op->create) | |
377 | return -ENOSYS; | |
378 | ||
379 | rc = __fdisk_switch_label(cxt, lb); | |
380 | if (rc) | |
381 | return rc; | |
382 | ||
383 | assert(cxt->label == lb); | |
384 | ||
385 | if (haslabel && !cxt->parent) { | |
386 | rc = fdisk_reset_device_properties(cxt); | |
387 | if (rc) | |
388 | return rc; | |
389 | } | |
390 | ||
391 | DBG(CXT, ul_debugobj(cxt, "creating a new %s label", lb->name)); | |
392 | return lb->op->create(cxt); | |
393 | } | |
394 | ||
395 | /** | |
396 | * fdisk_locate_disklabel: | |
397 | * @cxt: context | |
398 | * @n: N item | |
399 | * @name: return item name | |
400 | * @offset: return offset where is item | |
401 | * @size: of the item | |
402 | * | |
403 | * Locate disklabel and returns info about @n item of the label. | |
404 | * | |
405 | * For example GPT is composed from three items, PMBR and GPT, n=0 return | |
406 | * offset to PMBR and n=1 return offset to GPT Header and n=2 returns offset to | |
407 | * GPT array of partitions, n=3 and n=4 returns location of the backup GPT | |
408 | * label at the end of the disk. | |
409 | * | |
410 | * The function returns the current in-memory situation. It's possible that a | |
411 | * header location is modified by write operation, for example when enabled | |
412 | * minimization (see fdisk_gpt_enable_minimize()). In this case it's better to | |
413 | * call this function after fdisk_write_disklabel(). | |
414 | * | |
415 | * For more details see 'D' expert fdisk command. | |
416 | * | |
417 | * Returns: 0 on success, <0 on error, 1 no more items. | |
418 | */ | |
419 | int fdisk_locate_disklabel(struct fdisk_context *cxt, int n, const char **name, | |
420 | uint64_t *offset, size_t *size) | |
421 | { | |
422 | if (!cxt || !cxt->label) | |
423 | return -EINVAL; | |
424 | if (!cxt->label->op->locate) | |
425 | return -ENOSYS; | |
426 | ||
427 | DBG(CXT, ul_debugobj(cxt, "locating %d chunk of %s.", n, cxt->label->name)); | |
428 | return cxt->label->op->locate(cxt, n, name, offset, size); | |
429 | } | |
430 | ||
431 | ||
432 | /** | |
433 | * fdisk_get_disklabel_id: | |
434 | * @cxt: fdisk context | |
435 | * @id: returns pointer to allocated string (MBR Id or GPT dirk UUID) | |
436 | * | |
437 | * Returns: 0 on success, otherwise, a corresponding error. | |
438 | */ | |
439 | int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id) | |
440 | { | |
441 | struct fdisk_labelitem item = FDISK_LABELITEM_INIT; | |
442 | int rc; | |
443 | ||
444 | if (!cxt || !cxt->label || !id) | |
445 | return -EINVAL; | |
446 | ||
447 | DBG(CXT, ul_debugobj(cxt, "asking for disk %s ID", cxt->label->name)); | |
448 | ||
449 | rc = fdisk_get_disklabel_item(cxt, FDISK_LABELITEM_ID, &item); | |
450 | if (rc == 0) { | |
451 | *id = item.data.str; | |
452 | item.data.str = NULL; | |
453 | } | |
454 | fdisk_reset_labelitem(&item); | |
455 | if (rc > 0) | |
456 | rc = 0; | |
457 | return rc; | |
458 | } | |
459 | ||
460 | /** | |
461 | * fdisk_get_disklabel_item: | |
462 | * @cxt: fdisk context | |
463 | * @id: item ID (FDISK_LABELITEM_* or *_LABELITEM_*) | |
464 | * @item: specifies and returns the item | |
465 | * | |
466 | * Note that @id is always in range 0..N. It's fine to use the function in loop | |
467 | * until it returns error or 2, the result in @item should be ignored when | |
468 | * function returns 1. Don't forget to use fdisk_reset_labelitem() or fdisk_unref_labelitem(). | |
469 | * | |
470 | * Returns: 0 on success, < 0 on error, 1 on unsupported item, 2 id out of range | |
471 | */ | |
472 | int fdisk_get_disklabel_item(struct fdisk_context *cxt, int id, struct fdisk_labelitem *item) | |
473 | { | |
474 | if (!cxt || !cxt->label || !item) | |
475 | return -EINVAL; | |
476 | ||
477 | fdisk_reset_labelitem(item); | |
478 | item->id = id; | |
479 | DBG(CXT, ul_debugobj(cxt, "asking for disk %s item %d", cxt->label->name, item->id)); | |
480 | ||
481 | if (!cxt->label->op->get_item) | |
482 | return -ENOSYS; | |
483 | ||
484 | return cxt->label->op->get_item(cxt, item); | |
485 | } | |
486 | ||
487 | /** | |
488 | * fdisk_set_disklabel_id: | |
489 | * @cxt: fdisk context | |
490 | * | |
491 | * Returns: 0 on success, otherwise, a corresponding error. | |
492 | */ | |
493 | int fdisk_set_disklabel_id(struct fdisk_context *cxt) | |
494 | { | |
495 | if (!cxt || !cxt->label) | |
496 | return -EINVAL; | |
497 | if (!cxt->label->op->set_id) | |
498 | return -ENOSYS; | |
499 | ||
500 | DBG(CXT, ul_debugobj(cxt, "setting %s disk ID", cxt->label->name)); | |
501 | return cxt->label->op->set_id(cxt, NULL); | |
502 | } | |
503 | ||
504 | /** | |
505 | * fdisk_set_disklabel_id_from_string | |
506 | * @cxt: fdisk context | |
507 | * @str: new Id | |
508 | * | |
509 | * Returns: 0 on success, otherwise, a corresponding error. | |
510 | * | |
511 | * Since: 2.36 | |
512 | */ | |
513 | int fdisk_set_disklabel_id_from_string(struct fdisk_context *cxt, const char *str) | |
514 | { | |
515 | if (!cxt || !cxt->label || !str) | |
516 | return -EINVAL; | |
517 | if (!cxt->label->op->set_id) | |
518 | return -ENOSYS; | |
519 | ||
520 | DBG(CXT, ul_debugobj(cxt, "setting %s disk ID from '%s'", cxt->label->name, str)); | |
521 | return cxt->label->op->set_id(cxt, str); | |
522 | } | |
523 | ||
524 | /** | |
525 | * fdisk_set_partition_type: | |
526 | * @cxt: fdisk context | |
527 | * @partnum: partition number | |
528 | * @t: new type | |
529 | * | |
530 | * Returns: 0 on success, < 0 on error. | |
531 | */ | |
532 | int fdisk_set_partition_type(struct fdisk_context *cxt, | |
533 | size_t partnum, | |
534 | struct fdisk_parttype *t) | |
535 | { | |
536 | if (!cxt || !cxt->label || !t) | |
537 | return -EINVAL; | |
538 | ||
539 | ||
540 | if (cxt->label->op->set_part) { | |
541 | struct fdisk_partition *pa = fdisk_new_partition(); | |
542 | int rc; | |
543 | ||
544 | if (!pa) | |
545 | return -ENOMEM; | |
546 | fdisk_partition_set_type(pa, t); | |
547 | ||
548 | DBG(CXT, ul_debugobj(cxt, "partition: %zd: set type", partnum)); | |
549 | rc = cxt->label->op->set_part(cxt, partnum, pa); | |
550 | fdisk_unref_partition(pa); | |
551 | return rc; | |
552 | } | |
553 | ||
554 | return -ENOSYS; | |
555 | } | |
556 | ||
557 | ||
558 | /** | |
559 | * fdisk_toggle_partition_flag: | |
560 | * @cxt: fdisk context | |
561 | * @partnum: partition number | |
562 | * @flag: flag ID | |
563 | * | |
564 | * Returns: 0 on success, otherwise, a corresponding error. | |
565 | */ | |
566 | int fdisk_toggle_partition_flag(struct fdisk_context *cxt, | |
567 | size_t partnum, | |
568 | unsigned long flag) | |
569 | { | |
570 | int rc; | |
571 | ||
572 | if (!cxt || !cxt->label) | |
573 | return -EINVAL; | |
574 | if (!cxt->label->op->part_toggle_flag) | |
575 | return -ENOSYS; | |
576 | ||
577 | rc = cxt->label->op->part_toggle_flag(cxt, partnum, flag); | |
578 | ||
579 | DBG(CXT, ul_debugobj(cxt, "partition: %zd: toggle: 0x%04lx [rc=%d]", partnum, flag, rc)); | |
580 | return rc; | |
581 | } | |
582 | ||
583 | /** | |
584 | * fdisk_reorder_partitions | |
585 | * @cxt: fdisk context | |
586 | * | |
587 | * Sort partitions according to the partition start sector. | |
588 | * | |
589 | * Returns: 0 on success, 1 reorder unnecessary, otherwise a corresponding error. | |
590 | */ | |
591 | int fdisk_reorder_partitions(struct fdisk_context *cxt) | |
592 | { | |
593 | int rc; | |
594 | ||
595 | if (!cxt || !cxt->label) | |
596 | return -EINVAL; | |
597 | if (!cxt->label->op->reorder) | |
598 | return -ENOSYS; | |
599 | ||
600 | rc = cxt->label->op->reorder(cxt); | |
601 | ||
602 | switch (rc) { | |
603 | case 0: | |
604 | fdisk_info(cxt, _("Partitions order fixed.")); | |
605 | break; | |
606 | case 1: | |
607 | fdisk_info(cxt, _("Nothing to do. Ordering is correct already.")); | |
608 | break; | |
609 | default: | |
610 | fdisk_warnx(cxt, _("Failed to fix partitions order.")); | |
611 | break; | |
612 | } | |
613 | ||
614 | return rc; | |
615 | } | |
616 | ||
617 | /* | |
618 | * Resets the current used label driver to initial state | |
619 | */ | |
620 | void fdisk_deinit_label(struct fdisk_label *lb) | |
621 | { | |
622 | assert(lb); | |
623 | ||
624 | /* private label information */ | |
625 | if (lb->op->deinit) | |
626 | lb->op->deinit(lb); | |
627 | } | |
628 | ||
629 | /** | |
630 | * fdisk_label_set_changed: | |
631 | * @lb: label | |
632 | * @changed: 0/1 | |
633 | * | |
634 | * Marks in-memory data as changed, to force fdisk_write_disklabel() to write | |
635 | * to device. This should be unnecessary by default, the library keeps track | |
636 | * about changes. | |
637 | */ | |
638 | void fdisk_label_set_changed(struct fdisk_label *lb, int changed) | |
639 | { | |
640 | assert(lb); | |
641 | lb->changed = changed ? 1 : 0; | |
642 | } | |
643 | ||
644 | /** | |
645 | * fdisk_label_is_changed: | |
646 | * @lb: label | |
647 | * | |
648 | * Returns: 1 if in-memory data has been changed. | |
649 | */ | |
650 | int fdisk_label_is_changed(const struct fdisk_label *lb) | |
651 | { | |
652 | return lb ? lb->changed : 0; | |
653 | } | |
654 | ||
655 | /** | |
656 | * fdisk_label_set_disabled: | |
657 | * @lb: label | |
658 | * @disabled: 0 or 1 | |
659 | * | |
660 | * Mark label as disabled, then libfdisk is going to ignore the label when | |
661 | * probe device for labels. | |
662 | */ | |
663 | void fdisk_label_set_disabled(struct fdisk_label *lb, int disabled) | |
664 | { | |
665 | assert(lb); | |
666 | ||
667 | DBG(LABEL, ul_debug("%s label %s", | |
668 | lb->name, | |
669 | disabled ? "DISABLED" : "ENABLED")); | |
670 | lb->disabled = disabled ? 1 : 0; | |
671 | } | |
672 | ||
673 | /** | |
674 | * fdisk_label_is_disabled: | |
675 | * @lb: label | |
676 | * | |
677 | * Returns: 1 if label driver disabled. | |
678 | */ | |
679 | int fdisk_label_is_disabled(const struct fdisk_label *lb) | |
680 | { | |
681 | assert(lb); | |
682 | return lb ? lb->disabled : 0; | |
683 | } | |
684 | ||
685 | /** | |
686 | * fdisk_label_get_geomrange_sectors: | |
687 | * @lb: label | |
688 | * @mi: minimal number | |
689 | * @ma: maximal number | |
690 | * | |
691 | * The function provides minimal and maximal geometry supported for the label, | |
692 | * if no range defined by library then returns -ENOSYS. | |
693 | * | |
694 | * Since: 2.32 | |
695 | * | |
696 | * Returns: 0 on success, otherwise, a corresponding error. | |
697 | */ | |
698 | int fdisk_label_get_geomrange_sectors(const struct fdisk_label *lb, | |
699 | fdisk_sector_t *mi, fdisk_sector_t *ma) | |
700 | { | |
701 | if (!lb || lb->geom_min.sectors == 0) | |
702 | return -ENOSYS; | |
703 | if (mi) | |
704 | *mi = lb->geom_min.sectors; | |
705 | if (ma) | |
706 | *ma = lb->geom_max.sectors; | |
707 | return 0; | |
708 | } | |
709 | ||
710 | /** | |
711 | * fdisk_label_get_geomrange_heads: | |
712 | * @lb: label | |
713 | * @mi: minimal number | |
714 | * @ma: maximal number | |
715 | * | |
716 | * The function provides minimal and maximal geometry supported for the label, | |
717 | * if no range defined by library then returns -ENOSYS. | |
718 | * | |
719 | * Since: 2.32 | |
720 | * | |
721 | * Returns: 0 on success, otherwise, a corresponding error. | |
722 | */ | |
723 | int fdisk_label_get_geomrange_heads(const struct fdisk_label *lb, | |
724 | unsigned int *mi, unsigned int *ma) | |
725 | { | |
726 | if (!lb || lb->geom_min.heads == 0) | |
727 | return -ENOSYS; | |
728 | if (mi) | |
729 | *mi = lb->geom_min.heads; | |
730 | if (ma) | |
731 | *ma = lb->geom_max.heads; | |
732 | return 0; | |
733 | } | |
734 | ||
735 | /** | |
736 | * fdisk_label_get_geomrange_cylinders: | |
737 | * @lb: label | |
738 | * @mi: minimal number | |
739 | * @ma: maximal number | |
740 | * | |
741 | * The function provides minimal and maximal geometry supported for the label, | |
742 | * if no range defined by library then returns -ENOSYS. | |
743 | * | |
744 | * Since: 2.32 | |
745 | * | |
746 | * Returns: 0 on success, otherwise, a corresponding error. | |
747 | */ | |
748 | int fdisk_label_get_geomrange_cylinders(const struct fdisk_label *lb, | |
749 | fdisk_sector_t *mi, fdisk_sector_t *ma) | |
750 | { | |
751 | if (!lb || lb->geom_min.cylinders == 0) | |
752 | return -ENOSYS; | |
753 | if (mi) | |
754 | *mi = lb->geom_min.cylinders; | |
755 | if (ma) | |
756 | *ma = lb->geom_max.cylinders; | |
757 | return 0; | |
758 | } | |
759 |