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