]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libfdisk/src/label.c
tests: check for wipefs and helpers in fdisk tests
[thirdparty/util-linux.git] / libfdisk / src / label.c
CommitLineData
8adbcf0c
KZ
1
2#include "fdiskP.h"
3
aa36c2cf 4
5175ae87
KZ
5/**
6 * SECTION: label
7 * @title: Label specific driver
8 * @short_description: label (PT) specific data and functions
9 *
10 * The fdisk_new_context() initializes all label drivers, and allocate
11 * per-label specific data struct. This concept allows to store label specific
12 * settings to the label driver independently on the currently active label
13 * driver.
14 *
15 * Anyway, all label drives share in-memory first sector. The function
16 * fdisk_create_disklabel() overwrites the sector. But it's possible that
17 * label driver also uses another buffers, for example GPT uses more than only
18 * the first sector.
19 *
20 * All label operations are in-memory only, except fdisk_write_disklabel().
21 *
22 * All functions that use "struct fdisk_context" rather than "struct
23 * fdisk_label" use the currently active label driver.
7ce10975
KZ
24 */
25int fdisk_probe_labels(struct fdisk_context *cxt)
26{
27 size_t i;
28
4e0e8253 29 cxt->label = NULL;
7ce10975 30
0c5d095e 31 for (i = 0; i < cxt->nlabels; i++) {
4e0e8253 32 struct fdisk_label *lb = cxt->labels[i];
aa36c2cf 33 struct fdisk_label *org = fdisk_get_label(cxt, NULL);
d71ef5a4 34 int rc;
4e0e8253
KZ
35
36 if (!lb->op->probe)
7ce10975 37 continue;
7a188aed 38 if (lb->disabled) {
d71bd2f0 39 DBG(CXT, ul_debugobj(cxt, "%s: disabled -- ignore", lb->name));
7a188aed
KZ
40 continue;
41 }
d71bd2f0 42 DBG(CXT, ul_debugobj(cxt, "probing for %s", lb->name));
d71ef5a4
KZ
43
44 cxt->label = lb;
9ffeb235 45 rc = lb->op->probe(cxt);
d71ef5a4
KZ
46 cxt->label = org;
47
48 if (rc != 1) {
4e0e8253
KZ
49 if (lb->op->deinit)
50 lb->op->deinit(lb); /* for sure */
51 continue;
52 }
7ce10975 53
6a632136 54 __fdisk_switch_label(cxt, lb);
7ce10975
KZ
55 return 0;
56 }
57
d71bd2f0 58 DBG(CXT, ul_debugobj(cxt, "no label found"));
7ce10975
KZ
59 return 1; /* not found */
60}
61
8adbcf0c 62/**
aa36c2cf
KZ
63 * fdisk_label_get_name:
64 * @lb: label
8adbcf0c 65 *
aa36c2cf 66 * Returns: label name
8adbcf0c 67 */
eac3aac9 68const char *fdisk_label_get_name(const struct fdisk_label *lb)
8adbcf0c 69{
aa36c2cf 70 return lb ? lb->name : NULL;
8adbcf0c
KZ
71}
72
4af064f3
KZ
73/**
74 * fdisk_label_is_labeltype:
75 * @lb: label
4af064f3 76 *
1753a234 77 * Returns: FDISK_DISKLABEL_*.
4af064f3 78 */
eac3aac9 79int fdisk_label_get_type(const struct fdisk_label *lb)
4af064f3 80{
1753a234 81 return lb->id;
4af064f3
KZ
82}
83
72d2965c
KZ
84/**
85 * fdisk_label_require_geometry:
86 * @lb: label
87 *
88 * Returns: 1 if label requires CHS geometry
89 */
eac3aac9 90int fdisk_label_require_geometry(const struct fdisk_label *lb)
72d2965c
KZ
91{
92 assert(lb);
93
94 return lb->flags & FDISK_LABEL_FL_REQUIRE_GEOMETRY ? 1 : 0;
95}
96
8adbcf0c 97/**
11ee1177
KZ
98 * fdisk_label_get_fields_ids
99 * @lb: label (or NULL for the current label)
bd85d11f
KZ
100 * @ids: returns allocated array with FDISK_FIELD_* IDs
101 * @nids: returns number of items in fields
8152753d 102 *
11ee1177
KZ
103 * This function returns the default fields for the label.
104 *
105 * Note that the set of the default fields depends on fdisk_enable_details()
106 * function. If the details are enabled then this function usually returns more
107 * fields.
d6faa8e0 108 *
8152753d
KZ
109 * Returns 0 on success, otherwise, a corresponding error.
110 */
11ee1177 111int fdisk_label_get_fields_ids(
eac3aac9 112 const struct fdisk_label *lb,
11ee1177
KZ
113 struct fdisk_context *cxt,
114 int **ids, size_t *nids)
8152753d
KZ
115{
116 size_t i, n;
117 int *c;
118
119 assert(cxt);
120
11ee1177
KZ
121 if (!lb)
122 lb = cxt->label;
123 if (!lb)
8152753d 124 return -EINVAL;
11ee1177 125 if (!lb->fields || !lb->nfields)
8152753d 126 return -ENOSYS;
11ee1177 127 c = calloc(lb->nfields, sizeof(int));
8152753d
KZ
128 if (!c)
129 return -ENOMEM;
11ee1177
KZ
130 for (n = 0, i = 0; i < lb->nfields; i++) {
131 int id = lb->fields[i].id;
d0059a24 132
11ee1177
KZ
133 if ((fdisk_is_details(cxt) &&
134 (lb->fields[i].flags & FDISK_FIELDFL_EYECANDY))
6a632136 135 || (!fdisk_is_details(cxt) &&
11ee1177 136 (lb->fields[i].flags & FDISK_FIELDFL_DETAIL))
bd85d11f 137 || (id == FDISK_FIELD_SECTORS &&
6a632136 138 fdisk_use_cylinders(cxt))
bd85d11f 139 || (id == FDISK_FIELD_CYLINDERS &&
11ee1177 140 !fdisk_use_cylinders(cxt)))
8152753d 141 continue;
d0059a24
KZ
142
143 c[n++] = id;
8152753d 144 }
bd85d11f
KZ
145 if (ids)
146 *ids = c;
1671b2ed
KZ
147 else
148 free(c);
bd85d11f
KZ
149 if (nids)
150 *nids = n;
8152753d
KZ
151 return 0;
152}
153
5175ae87
KZ
154/**
155 * fdisk_label_get_field:
156 * @lb: label
157 * @id: FDISK_FIELD_*
158 *
159 * The field struct describes data stored in struct fdisk_partition. The info
160 * about data is usable for example to generate human readable output (e.g.
161 * fdisk 'p'rint command). See fdisk_partition_to_stirng() and fdisk code.
162 *
163 * Returns: pointer to static instance of the field.
164 */
eac3aac9 165const struct fdisk_field *fdisk_label_get_field(const struct fdisk_label *lb, int id)
8152753d
KZ
166{
167 size_t i;
168
169 assert(lb);
170 assert(id > 0);
171
bd85d11f
KZ
172 for (i = 0; i < lb->nfields; i++) {
173 if (lb->fields[i].id == id)
174 return &lb->fields[i];
8152753d
KZ
175 }
176
177 return NULL;
178}
179
eac3aac9
KZ
180/**
181 * fdisk_label_get_field_by_name
182 * @lb: label
183 * @name: field name
184 *
185 * Returns: pointer to static instance of the field.
186 */
187const struct fdisk_field *fdisk_label_get_field_by_name(
188 const struct fdisk_label *lb,
189 const char *name)
190{
191 size_t i;
192
193 assert(lb);
194 assert(name);
195
196 for (i = 0; i < lb->nfields; i++) {
197 if (lb->fields[i].name && strcasecmp(lb->fields[i].name, name) == 0)
198 return &lb->fields[i];
199 }
200
201 return NULL;
202}
203
204
5175ae87
KZ
205/**
206 * fdisk_field_get_id:
207 * @field: field instance
208 *
209 * Returns: field Id (FDISK_FIELD_*)
210 */
bd85d11f 211int fdisk_field_get_id(const struct fdisk_field *field)
d44115f3 212{
bd85d11f 213 return field ? field->id : -EINVAL;
d44115f3
KZ
214}
215
5175ae87
KZ
216/**
217 * fdisk_field_get_name:
218 * @field: field instance
219 *
220 * Returns: field name
221 */
bd85d11f 222const char *fdisk_field_get_name(const struct fdisk_field *field)
d44115f3 223{
bd85d11f 224 return field ? field->name : NULL;
d44115f3
KZ
225}
226
5175ae87
KZ
227/**
228 * fdisk_field_get_width:
229 * @field: field instance
230 *
231 * Returns: libsmartcols compatible width.
232 */
bd85d11f 233double fdisk_field_get_width(const struct fdisk_field *field)
d44115f3 234{
bd85d11f 235 return field ? field->width : -EINVAL;
d44115f3
KZ
236}
237
5175ae87
KZ
238/**
239 * fdisk_field_is_number:
240 * @field: field instance
241 *
242 * Returns: 1 if field represent number
243 */
bd85d11f 244int fdisk_field_is_number(const struct fdisk_field *field)
d44115f3 245{
bd85d11f 246 return field->flags ? field->flags & FDISK_FIELDFL_NUMBER : 0;
d44115f3
KZ
247}
248
11ee1177
KZ
249
250/**
251 * fdisk_write_disklabel:
252 * @cxt: fdisk context
253 *
5175ae87 254 * Write in-memory changes to disk. Be careful!
11ee1177
KZ
255 *
256 * Returns 0 on success, otherwise, a corresponding error.
257 */
258int fdisk_write_disklabel(struct fdisk_context *cxt)
259{
260 if (!cxt || !cxt->label || cxt->readonly)
261 return -EINVAL;
262 if (!cxt->label->op->write)
263 return -ENOSYS;
264 return cxt->label->op->write(cxt);
265}
266
8adbcf0c
KZ
267/**
268 * fdisk_verify_disklabel:
269 * @cxt: fdisk context
270 *
271 * Verifies the partition table.
272 *
8c0a7f91 273 * Returns: 0 on success, otherwise, a corresponding error.
8adbcf0c
KZ
274 */
275int fdisk_verify_disklabel(struct fdisk_context *cxt)
276{
277 if (!cxt || !cxt->label)
278 return -EINVAL;
0c5d095e 279 if (!cxt->label->op->verify)
8adbcf0c 280 return -ENOSYS;
0b52b94c
KZ
281 if (fdisk_missing_geometry(cxt))
282 return -EINVAL;
8adbcf0c 283
9ffeb235 284 return cxt->label->op->verify(cxt);
8adbcf0c
KZ
285}
286
3c5fb475
KZ
287/**
288 * fdisk_list_disklabel:
289 * @cxt: fdisk context
290 *
6c89f750 291 * Lists details about disklabel, but no partitions.
8152753d
KZ
292 *
293 * This function uses libfdisk ASK interface to print data. The details about
6c89f750 294 * partitions table are printed by FDISK_ASKTYPE_INFO.
3c5fb475
KZ
295 *
296 * Returns 0 on success, otherwise, a corresponding error.
297 */
298int fdisk_list_disklabel(struct fdisk_context *cxt)
299{
300 if (!cxt || !cxt->label)
301 return -EINVAL;
302 if (!cxt->label->op->list)
303 return -ENOSYS;
304
305 return cxt->label->op->list(cxt);
306}
307
7ce10975
KZ
308/**
309 * fdisk_create_disklabel:
310 * @cxt: fdisk context
311 * @name: label name
312 *
5175ae87
KZ
313 * Creates a new disk label of type @name. If @name is NULL, then it will
314 * create a default system label type, either SUN or DOS. The function
315 * automaticaly switches the current label driver to @name. The function
316 * fdisk_get_label() returns the current label driver.
317 *
318 * The function modifies in-memory data only.
7ce10975
KZ
319 *
320 * Returns 0 on success, otherwise, a corresponding error.
321 */
322int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name)
323{
1653f0b0 324 int haslabel = 0;
8a9256f9 325 struct fdisk_label *lb;
1653f0b0 326
7ce10975
KZ
327 if (!cxt)
328 return -EINVAL;
329
7ce10975
KZ
330 if (!name) { /* use default label creation */
331#ifdef __sparc__
0c5d095e 332 name = "sun";
7ce10975 333#else
0c5d095e 334 name = "dos";
7ce10975 335#endif
7ce10975
KZ
336 }
337
1653f0b0 338 if (cxt->label) {
0559e742 339 fdisk_deinit_label(cxt->label);
1653f0b0
KZ
340 haslabel = 1;
341 }
4e0e8253 342
6a632136 343 lb = fdisk_get_label(cxt, name);
7a188aed 344 if (!lb || lb->disabled)
7ce10975 345 return -EINVAL;
8a9256f9 346 if (!lb->op->create)
7ce10975
KZ
347 return -ENOSYS;
348
6a632136 349 __fdisk_switch_label(cxt, lb);
8a9256f9
KZ
350
351 if (haslabel && !cxt->parent)
1653f0b0 352 fdisk_reset_device_properties(cxt);
8a9256f9 353
d71bd2f0 354 DBG(CXT, ul_debugobj(cxt, "create a new %s label", lb->name));
9ffeb235 355 return cxt->label->op->create(cxt);
7ce10975 356}
21fe3dde 357
5ab37600
KZ
358/**
359 * fdisk_locate_disklabel:
360 * @cxt: context
361 * @n: N item
362 * @name: return item name
363 * @offset: return offset where is item
364 * @size: of the item
365 *
366 * Locate disklabel and returns info about @n item of the label. For example
367 * GPT is composed from two items, PMBR and GPT, n=0 return offset to PMBR and n=1
368 * return offset to GPT. For more details see 'D' expect fdisk command.
369 *
370 * Returns: 0 on succes, <0 on error, 1 no more items.
371 */
c0d20aae
KZ
372int fdisk_locate_disklabel(struct fdisk_context *cxt, int n, const char **name,
373 off_t *offset, size_t *size)
374{
375 if (!cxt || !cxt->label)
376 return -EINVAL;
377 if (!cxt->label->op->locate)
378 return -ENOSYS;
379
d71bd2f0 380 DBG(CXT, ul_debugobj(cxt, "locating %d chunk of %s.", n, cxt->label->name));
c0d20aae
KZ
381 return cxt->label->op->locate(cxt, n, name, offset, size);
382}
383
384
21fe3dde
KZ
385/**
386 * fdisk_get_disklabel_id:
387 * @cxt: fdisk context
5175ae87 388 * @id: returns pointer to allocated string (MBR Id or GPT dirk UUID)
21fe3dde
KZ
389 *
390 * Returns 0 on success, otherwise, a corresponding error.
391 */
392int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id)
393{
394 if (!cxt || !cxt->label)
395 return -EINVAL;
396 if (!cxt->label->op->get_id)
397 return -ENOSYS;
398
d71bd2f0 399 DBG(CXT, ul_debugobj(cxt, "asking for disk %s ID", cxt->label->name));
21fe3dde
KZ
400 return cxt->label->op->get_id(cxt, id);
401}
35b1f0a4
KZ
402
403/**
5ab37600 404 * fdisk_set_disklabel_id:
35b1f0a4
KZ
405 * @cxt: fdisk context
406 *
407 * Returns 0 on success, otherwise, a corresponding error.
408 */
409int fdisk_set_disklabel_id(struct fdisk_context *cxt)
410{
411 if (!cxt || !cxt->label)
412 return -EINVAL;
413 if (!cxt->label->op->set_id)
414 return -ENOSYS;
415
d71bd2f0 416 DBG(CXT, ul_debugobj(cxt, "setting %s disk ID", cxt->label->name));
35b1f0a4
KZ
417 return cxt->label->op->set_id(cxt);
418}
171372d3 419
171372d3
KZ
420/**
421 * fdisk_set_partition_type:
422 * @cxt: fdisk context
423 * @partnum: partition number
424 * @t: new type
425 *
426 * Returns 0 on success, < 0 on error.
427 */
9ffeb235
KZ
428int fdisk_set_partition_type(struct fdisk_context *cxt,
429 size_t partnum,
171372d3
KZ
430 struct fdisk_parttype *t)
431{
ea50ba5b 432 if (!cxt || !cxt->label || !t)
171372d3
KZ
433 return -EINVAL;
434
b305ad40
KZ
435
436 if (cxt->label->op->set_part) {
437 struct fdisk_partition pa = { .type = t };
b305ad40 438
ea50ba5b
KZ
439 DBG(CXT, ul_debugobj(cxt, "partition: %zd: set type", partnum));
440 return cxt->label->op->set_part(cxt, partnum, &pa);
441 }
b305ad40
KZ
442
443 return -ENOSYS;
171372d3
KZ
444}
445
4e0e8253 446
fb1caca7
KZ
447/**
448 * fdisk_partition_taggle_flag:
449 * @cxt: fdisk context
450 * @partnum: partition number
451 * @status: flags
452 *
453 * Returns 0 on success, otherwise, a corresponding error.
454 */
455int fdisk_partition_toggle_flag(struct fdisk_context *cxt,
456 size_t partnum,
457 unsigned long flag)
458{
459 int rc;
460
461 if (!cxt || !cxt->label)
462 return -EINVAL;
463 if (!cxt->label->op->part_toggle_flag)
464 return -ENOSYS;
465
466 rc = cxt->label->op->part_toggle_flag(cxt, partnum, flag);
467
d71bd2f0 468 DBG(CXT, ul_debugobj(cxt, "partition: %zd: toggle: 0x%04lx [rc=%d]", partnum, flag, rc));
7845ca8d 469 return rc;
47b8e7c0
KZ
470}
471
dd7ba604
KZ
472/**
473 * fdisk_reorder_partitions
474 * @cxt: fdisk context
475 *
476 * Sort partitions according to the partition start sector.
477 *
478 * Returns 0 on success, otherwise, a corresponding error.
479 */
480int fdisk_reorder_partitions(struct fdisk_context *cxt)
481{
482 if (!cxt || !cxt->label)
483 return -EINVAL;
484 if (!cxt->label->op->reorder)
485 return -ENOSYS;
486
487 return cxt->label->op->reorder(cxt);
488}
489
4e0e8253
KZ
490/*
491 * Resets the current used label driver to initial state
492 */
0559e742 493void fdisk_deinit_label(struct fdisk_label *lb)
4e0e8253 494{
0559e742 495 assert(lb);
4e0e8253 496
0559e742
KZ
497 /* private label information */
498 if (lb->op->deinit)
499 lb->op->deinit(lb);
4e0e8253 500}
2e3b40d3 501
5175ae87
KZ
502/**
503 * fdisk_label_set_changed:
504 * @lb: label
505 * @changed: 0/1
506 *
507 * Marks in-memory data as changed, to force fdisk_write_disklabel() to write
508 * to device. This should be unnecessar by default, the library keeps track
509 * about changes.
510 */
2e3b40d3
KZ
511void fdisk_label_set_changed(struct fdisk_label *lb, int changed)
512{
513 assert(lb);
2e3b40d3
KZ
514 lb->changed = changed ? 1 : 0;
515}
516
5175ae87
KZ
517/**
518 * fdisk_label_is_changed:
519 * @lb: label
520 *
521 * Returns: 1 if in-memory data has been changed.
522 */
eac3aac9 523int fdisk_label_is_changed(const struct fdisk_label *lb)
2e3b40d3
KZ
524{
525 assert(lb);
526 return lb ? lb->changed : 0;
527}
7a188aed 528
5175ae87
KZ
529/**
530 * fdisk_label_set_disabled:
531 * @lb: label
532 *
533 * Mark label as disabled, then libfdisk is going to ignore the label when
534 * probe device for labels.
535 */
7a188aed
KZ
536void fdisk_label_set_disabled(struct fdisk_label *lb, int disabled)
537{
538 assert(lb);
539
88141067 540 DBG(LABEL, ul_debug("%s label %s",
7a188aed
KZ
541 lb->name,
542 disabled ? "DISABLED" : "ENABLED"));
543 lb->disabled = disabled ? 1 : 0;
544}
545
5175ae87
KZ
546/**
547 * fdisk_label_is_disabled:
548 * @lb: label
549 *
550 * Returns: 1 if label driver disabled.
551 */
eac3aac9 552int fdisk_label_is_disabled(const struct fdisk_label *lb)
7a188aed
KZ
553{
554 assert(lb);
555 return lb ? lb->disabled : 0;
556}