]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libfdisk/src/partition.c
libfdisk: rename fdisk_column to fdisk_field
[thirdparty/util-linux.git] / libfdisk / src / partition.c
CommitLineData
8c0a7f91
KZ
1
2#include "c.h"
3#include "strutils.h"
4
5#include "fdiskP.h"
6
7struct fdisk_partition *fdisk_new_partition(void)
8{
9 struct fdisk_partition *pa = calloc(1, sizeof(*pa));
10
d6cfa8b3 11 pa->refcount = 1;
6c89f750 12 INIT_LIST_HEAD(&pa->parts);
77d6a70a 13 pa->partno = FDISK_EMPTY_PARTNO;
bd5e8291 14 pa->parent_partno = FDISK_EMPTY_PARTNO;
d71bd2f0 15 DBG(PART, ul_debugobj(pa, "alloc"));
8c0a7f91
KZ
16 return pa;
17}
18
19void fdisk_reset_partition(struct fdisk_partition *pa)
20{
d6cfa8b3
KZ
21 int ref;
22
8c0a7f91
KZ
23 if (!pa)
24 return;
d6cfa8b3 25
d71bd2f0 26 DBG(PART, ul_debugobj(pa, "reset"));
d6cfa8b3 27 ref = pa->refcount;
8c0a7f91
KZ
28 fdisk_free_parttype(pa->type);
29 free(pa->name);
30 free(pa->uuid);
31 free(pa->attrs);
32 memset(pa, 0, sizeof(*pa));
77d6a70a 33 pa->partno = FDISK_EMPTY_PARTNO;
bd5e8291 34 pa->parent_partno = FDISK_EMPTY_PARTNO;
d6cfa8b3 35 pa->refcount = ref;
6c89f750 36 INIT_LIST_HEAD(&pa->parts);
8c0a7f91
KZ
37}
38
d6cfa8b3
KZ
39void fdisk_ref_partition(struct fdisk_partition *pa)
40{
41 if (pa)
42 pa->refcount++;
43}
44
45void fdisk_unref_partition(struct fdisk_partition *pa)
8c0a7f91
KZ
46{
47 if (!pa)
48 return;
d6cfa8b3
KZ
49
50 pa->refcount--;
51 if (pa->refcount <= 0) {
d71bd2f0 52 DBG(PART, ul_debugobj(pa, "free"));
6c89f750
KZ
53 fdisk_reset_partition(pa);
54 list_del(&pa->parts);
d6cfa8b3
KZ
55 free(pa);
56 }
8c0a7f91
KZ
57}
58
5139eca7
KZ
59int fdisk_dump_partition(struct fdisk_partition *pa, FILE *f)
60{
61 assert(pa);
62 assert(f);
63
64 if (pa->partno == FDISK_EMPTY_PARTNO)
65 fputs("# ", f);
66 else
67 fprintf(f, "#%zu ", pa->partno);
68
69 fprintf(f, "[%p] start=%ju, end=%ju, size=%ju",
70 pa, pa->start, pa->end, pa->size);
71 if (pa->parent_partno != FDISK_EMPTY_PARTNO)
72 fprintf(f, ", parent=%zu", pa->parent_partno);
73 if (fdisk_partition_is_freespace(pa))
74 fputs(" freespace", f);
75 if (fdisk_partition_is_container(pa))
76 fputs(" container", f);
77 if (fdisk_partition_is_nested(pa))
78 fputs(" nested", f);
79 fputc('\n', f);
80 return 0;
81}
82
8c0a7f91
KZ
83int fdisk_partition_set_start(struct fdisk_partition *pa, uint64_t off)
84{
85 if (!pa)
86 return -EINVAL;
87 pa->start = off;
88 return 0;
89}
90
91uint64_t fdisk_partition_get_start(struct fdisk_partition *pa)
92{
93 return pa ? pa->start : 0;
94}
95
e5c93999
KZ
96int fdisk_partition_cmp_start(struct fdisk_partition *a,
97 struct fdisk_partition *b)
98{
99 return a->start - b->start;
100}
101
03643931 102int fdisk_partition_set_end(struct fdisk_partition *pa, uint64_t off)
8c0a7f91
KZ
103{
104 if (!pa)
105 return -EINVAL;
106 pa->end = off;
107 pa->size = 0;
8c0a7f91
KZ
108 return 0;
109}
110
111uint64_t fdisk_partition_get_end(struct fdisk_partition *pa)
112{
732aefdf 113 return pa ? pa->end : 0;
8c0a7f91
KZ
114}
115
116
117int fdisk_partition_set_size(struct fdisk_partition *pa, uint64_t size)
118{
119 if (!pa)
120 return -EINVAL;
121 pa->size = size;
122 pa->end = 0;
123 return 0;
124}
125
126uint64_t fdisk_partition_get_size(struct fdisk_partition *pa)
127{
128 return pa ? pa->size : 0;
129}
130
131int fdisk_partition_set_partno(struct fdisk_partition *pa, size_t n)
132{
133 if (!pa)
134 return -EINVAL;
135 pa->partno = n;
136 return 0;
137}
138
139size_t fdisk_partition_get_partno(struct fdisk_partition *pa)
140{
141 return pa ? pa->partno : (size_t) -1;
142}
143
e5c93999
KZ
144int fdisk_partition_cmp_partno(struct fdisk_partition *a,
145 struct fdisk_partition *b)
146{
147 return a->partno - b->partno;
148}
149
8c0a7f91
KZ
150int fdisk_partition_set_type(struct fdisk_partition *pa, struct fdisk_parttype *type)
151{
152 if (!pa)
153 return -EINVAL;
85151521 154 fdisk_free_parttype(pa->type);
8c0a7f91
KZ
155 pa->type = type;
156 return 0;
157}
158
159const struct fdisk_parttype *fdisk_partition_get_type(struct fdisk_partition *pa)
160{
161 return pa ? pa->type : NULL;
162}
163
164int fdisk_partition_set_name(struct fdisk_partition *pa, const char *name)
165{
166 char *p = NULL;
167
168 if (!pa)
169 return -EINVAL;
170 if (name) {
171 p = strdup(name);
172 if (!p)
173 return -ENOMEM;
174 }
175 free(pa->name);
176 pa->name = p;
177 return 0;
178}
179
180const char *fdisk_partition_get_name(struct fdisk_partition *pa)
181{
182 return pa ? pa->name : NULL;
183}
184
185int fdisk_partition_set_uuid(struct fdisk_partition *pa, const char *uuid)
186{
187 char *p = NULL;
188
189 if (!pa)
190 return -EINVAL;
191 if (uuid) {
192 p = strdup(uuid);
193 if (!p)
194 return -ENOMEM;
195 }
196 free(pa->uuid);
197 pa->uuid = p;
198 return 0;
199}
200
732aefdf
KZ
201int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable)
202{
203 if (!pa)
204 return -EINVAL;
205 pa->partno_follow_default = enable ? 1 : 0;
206 return 0;
207}
208
209int fdisk_partition_start_follow_default(struct fdisk_partition *pa, int enable)
210{
211 if (!pa)
212 return -EINVAL;
213 pa->start_follow_default = enable ? 1 : 0;
214 return 0;
215}
216
217int fdisk_partition_end_follow_default(struct fdisk_partition *pa, int enable)
218{
219 if (!pa)
220 return -EINVAL;
221 pa->end_follow_default = enable ? 1 : 0;
222 return 0;
223}
224
8c0a7f91
KZ
225const char *fdisk_partition_get_uuid(struct fdisk_partition *pa)
226{
227 return pa ? pa->uuid : NULL;
228}
229
230const char *fdisk_partition_get_attrs(struct fdisk_partition *pa)
231{
232 return pa ? pa->attrs : NULL;
233}
234
bd5e8291 235int fdisk_partition_is_nested(struct fdisk_partition *pa)
8c0a7f91 236{
bd5e8291 237 return pa && pa->parent_partno != FDISK_EMPTY_PARTNO;
8c0a7f91
KZ
238}
239
bd5e8291 240int fdisk_partition_is_container(struct fdisk_partition *pa)
8c0a7f91 241{
bd5e8291 242 return pa && pa->container;
8c0a7f91
KZ
243}
244
03643931
KZ
245int fdisk_partition_get_parent(struct fdisk_partition *pa, size_t *parent)
246{
247 if (pa && parent)
248 *parent = pa->parent_partno;
249 else
250 return -EINVAL;
251 return 0;
252}
253
8c0a7f91
KZ
254int fdisk_partition_is_used(struct fdisk_partition *pa)
255{
256 return pa && pa->used;
257}
258
1de9fddb
KZ
259int fdisk_partition_is_freespace(struct fdisk_partition *pa)
260{
261 return pa && pa->freespace;
262}
263
77d6a70a 264int fdisk_partition_next_partno(
77d6a70a 265 struct fdisk_partition *pa,
6c89f750 266 struct fdisk_context *cxt,
77d6a70a
KZ
267 size_t *n)
268{
269 assert(cxt);
270 assert(n);
271
272 if (pa && pa->partno_follow_default) {
273 size_t i;
274
d71bd2f0 275 DBG(PART, ul_debugobj(pa, "next partno (follow default)"));
732aefdf 276
6c89f750 277 for (i = 0; i < cxt->label->nparts_max; i++) {
77d6a70a
KZ
278 if (!fdisk_is_partition_used(cxt, i)) {
279 *n = i;
732aefdf 280 return 0;
77d6a70a
KZ
281 }
282 }
732aefdf
KZ
283 return -ERANGE;
284
77d6a70a 285 } else if (pa && pa->partno != FDISK_EMPTY_PARTNO) {
732aefdf 286
d71bd2f0 287 DBG(PART, ul_debugobj(pa, "next partno (specified=%zu)", pa->partno));
732aefdf 288
6c89f750 289 if (pa->partno >= cxt->label->nparts_max)
77d6a70a
KZ
290 return -ERANGE;
291 *n = pa->partno;
292 } else
293 return fdisk_ask_partnum(cxt, n, 1);
294
295 return 0;
296}
8c0a7f91
KZ
297
298/**
299 * fdisk_partition_to_string:
300 * @pa: partition
bd85d11f 301 * @id: field (FDISK_FIELD_*)
8c0a7f91
KZ
302 * @data: returns string with allocated data
303 *
304 * Returns info about partition converted to printable string.
305 *
0e65dcde 306 * For example
8c0a7f91 307 *
d6cfa8b3 308 * struct fdisk_parition *pa;
8c0a7f91
KZ
309 *
310 * fdisk_get_partition(cxt, 0, &pa);
bd85d11f 311 * fdisk_partition_to_string(pa, FDISK_FIELD_UUID, &data);
8c0a7f91
KZ
312 * printf("first partition uuid: %s\n", data);
313 * free(data);
d6cfa8b3 314 * fdisk_unref_partition(pa);
8c0a7f91
KZ
315 *
316 * returns UUID for the first partition.
317 *
318 * Returns 0 on success, otherwise, a corresponding error.
319 */
320
321int fdisk_partition_to_string(struct fdisk_partition *pa,
6c89f750 322 struct fdisk_context *cxt,
8c0a7f91
KZ
323 int id,
324 char **data)
325{
326 char *p = NULL;
327 int rc = 0;
77d6a70a 328 uint64_t x;
8c0a7f91 329
6c89f750 330 if (!pa || !cxt)
8c0a7f91
KZ
331 return -EINVAL;
332
333 switch (id) {
bd85d11f 334 case FDISK_FIELD_DEVICE:
1de9fddb
KZ
335 if (pa->freespace)
336 p = strdup(_("Free space"));
6c89f750 337 else if (cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO)
82ebc7de
KZ
338 rc = asprintf(&p, "%c", (int) pa->partno + 'a');
339 else
6c89f750 340 p = fdisk_partname(cxt->dev_path, pa->partno + 1);
8c0a7f91 341 break;
bd85d11f 342 case FDISK_FIELD_BOOT:
d6faa8e0
KZ
343 rc = asprintf(&p, "%c", pa->boot);
344 break;
bd85d11f 345 case FDISK_FIELD_START:
6c89f750 346 x = fdisk_cround(cxt, pa->start);
82ebc7de 347 rc = pa->start_post ?
77d6a70a
KZ
348 asprintf(&p, "%ju%c", x, pa->start_post) :
349 asprintf(&p, "%ju", x);
8c0a7f91 350 break;
bd85d11f 351 case FDISK_FIELD_END:
6c89f750 352 x = fdisk_cround(cxt, pa->end);
82ebc7de 353 rc = pa->end_post ?
77d6a70a
KZ
354 asprintf(&p, "%ju%c", x, pa->end_post) :
355 asprintf(&p, "%ju", x);
8c0a7f91 356 break;
bd85d11f 357 case FDISK_FIELD_SIZE:
77d6a70a 358 {
6c89f750 359 uint64_t sz = pa->size * cxt->sector_size;
77d6a70a 360
6c89f750 361 if (fdisk_context_display_details(cxt)) {
82ebc7de 362 rc = pa->size_post ?
77d6a70a
KZ
363 asprintf(&p, "%ju%c", sz, pa->size_post) :
364 asprintf(&p, "%ju", sz);
8c0a7f91 365 } else {
77d6a70a 366 p = size_to_human_string(SIZE_SUFFIX_1LETTER, sz);
8c0a7f91
KZ
367 if (!p)
368 rc = -ENOMEM;
369 }
370 break;
77d6a70a 371 }
bd85d11f 372 case FDISK_FIELD_CYLINDERS:
77d6a70a 373 rc = asprintf(&p, "%ju", (uintmax_t)
6c89f750 374 fdisk_cround(cxt, pa->size));
77d6a70a 375 break;
bd85d11f 376 case FDISK_FIELD_SECTORS:
77d6a70a 377 rc = asprintf(&p, "%ju", pa->size);
d6faa8e0 378 break;
bd85d11f 379 case FDISK_FIELD_BSIZE:
82ebc7de
KZ
380 rc = asprintf(&p, "%ju", pa->bsize);
381 break;
bd85d11f 382 case FDISK_FIELD_FSIZE:
82ebc7de
KZ
383 rc = asprintf(&p, "%ju", pa->fsize);
384 break;
bd85d11f 385 case FDISK_FIELD_CPG:
82ebc7de
KZ
386 rc = asprintf(&p, "%ju", pa->cpg);
387 break;
bd85d11f 388 case FDISK_FIELD_TYPE:
8c0a7f91
KZ
389 p = pa->type && pa->type->name ? strdup(pa->type->name) : NULL;
390 break;
bd85d11f 391 case FDISK_FIELD_TYPEID:
d6faa8e0
KZ
392 if (pa->type && pa->type->typestr)
393 rc = asprintf(&p, "%s", pa->type->typestr);
394 else if (pa->type)
395 rc = asprintf(&p, "%x", pa->type->type);
396 break;
bd85d11f 397 case FDISK_FIELD_UUID:
8c0a7f91
KZ
398 p = pa->uuid ? strdup(pa->uuid) : NULL;
399 break;
bd85d11f 400 case FDISK_FIELD_NAME:
8c0a7f91
KZ
401 p = pa->name ? strdup(pa->name) : NULL;
402 break;
bd85d11f 403 case FDISK_FIELD_ATTR:
8c0a7f91
KZ
404 p = pa->attrs ? strdup(pa->attrs) : NULL;
405 break;
bd85d11f 406 case FDISK_FIELD_SADDR:
d6faa8e0
KZ
407 p = pa->start_addr ? strdup(pa->start_addr) : NULL;
408 break;
bd85d11f 409 case FDISK_FIELD_EADDR:
d6faa8e0
KZ
410 p = pa->end_addr ? strdup(pa->end_addr) : NULL;
411 break;
8c0a7f91
KZ
412 default:
413 return -EINVAL;
414 }
415
82ebc7de
KZ
416 if (rc < 0)
417 rc = -ENOMEM;
418 else if (rc > 0)
419 rc = 0;
420
8c0a7f91
KZ
421 if (data)
422 *data = p;
423 return rc;
424}
187de51c
KZ
425
426/**
427 * fdisk_get_partition:
428 * @cxt:
429 * @partno:
430 * @pa: pointer to partition struct
431 *
432 * Fills in @pa with data about partition @n.
433 *
434 * Returns: 0 on success, otherwise, a corresponding error.
435 */
436int fdisk_get_partition(struct fdisk_context *cxt, size_t partno,
437 struct fdisk_partition **pa)
438{
439 int rc;
6c89f750 440 struct fdisk_partition *np = NULL;
187de51c
KZ
441
442 if (!cxt || !cxt->label || !pa)
443 return -EINVAL;
444 if (!cxt->label->op->get_part)
445 return -ENOSYS;
6c89f750
KZ
446 if (!fdisk_is_partition_used(cxt, partno))
447 return -EINVAL;
187de51c
KZ
448
449 if (!*pa) {
6c89f750 450 np = *pa = fdisk_new_partition();
187de51c
KZ
451 if (!*pa)
452 return -ENOMEM;
453 } else
454 fdisk_reset_partition(*pa);
6c89f750 455
187de51c
KZ
456 (*pa)->partno = partno;
457 rc = cxt->label->op->get_part(cxt, partno, *pa);
6c89f750
KZ
458
459 if (rc) {
460 if (np) {
461 fdisk_unref_partition(np);
462 *pa = NULL;
463 } else
464 fdisk_reset_partition(*pa);
465 }
187de51c
KZ
466 return rc;
467}
468
469/*
470 * This is faster than fdisk_get_partition() + fdisk_partition_is_used()
471 */
472int fdisk_is_partition_used(struct fdisk_context *cxt, size_t n)
473{
474 if (!cxt || !cxt->label)
475 return -EINVAL;
476 if (!cxt->label->op->part_is_used)
477 return -ENOSYS;
478
479 return cxt->label->op->part_is_used(cxt, n);
480}
481
482/**
483 * fdisk_add_partition:
484 * @cxt: fdisk context
485 * @pa: template for the partition
486 *
487 * If @pa is not specified or any @pa item is missiong the libfdisk will ask by
488 * fdisk_ask_ API.
489 *
490 * Creates a new partition.
491 *
492 * Returns 0.
493 */
494int fdisk_add_partition(struct fdisk_context *cxt,
495 struct fdisk_partition *pa)
496{
732aefdf
KZ
497 int rc;
498
187de51c
KZ
499 assert(cxt);
500 assert(cxt->label);
501
502 if (!cxt || !cxt->label)
503 return -EINVAL;
504 if (!cxt->label->op->add_part)
505 return -ENOSYS;
506 if (fdisk_missing_geometry(cxt))
507 return -EINVAL;
508
d71bd2f0 509 DBG(CXT, ul_debugobj(cxt, "adding new partition (start=%ju, end=%ju, size=%ju, "
732aefdf
KZ
510 "defaults(start=%s, end=%s, partno=%s)",
511 pa ? pa->start : 0,
512 pa ? pa->end : 0,
513 pa ? pa->size : 0,
514 pa && pa->start_follow_default ? "yes" : "no",
515 pa && pa->end_follow_default ? "yes" : "no",
516 pa && pa->partno_follow_default ? "yes" : "no"));
517
518 rc = cxt->label->op->add_part(cxt, pa);
519
d71bd2f0 520 DBG(CXT, ul_debugobj(cxt, "add partition done (rc=%d)", rc));
732aefdf 521 return rc;
187de51c
KZ
522}
523
524/**
525 * fdisk_delete_partition:
526 * @cxt: fdisk context
527 * @partnum: partition number to delete
528 *
529 * Deletes a @partnum partition.
530 *
531 * Returns 0 on success, otherwise, a corresponding error.
532 */
533int fdisk_delete_partition(struct fdisk_context *cxt, size_t partnum)
534{
535 if (!cxt || !cxt->label)
536 return -EINVAL;
537 if (!cxt->label->op->part_delete)
538 return -ENOSYS;
539
d71bd2f0 540 DBG(CXT, ul_debugobj(cxt, "deleting %s partition number %zd",
187de51c
KZ
541 cxt->label->name, partnum));
542 return cxt->label->op->part_delete(cxt, partnum);
543}