]> git.ipfire.org Git - thirdparty/util-linux.git/blame - libblkid/src/partitions/partitions.c
misc: remove %p from debug messages
[thirdparty/util-linux.git] / libblkid / src / partitions / partitions.c
CommitLineData
e4799a35
KZ
1/*
2 * partitions - partition tables parsing
3 *
4 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
5 *
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
8 *
9 */
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <fcntl.h>
15#include <ctype.h>
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <errno.h>
19#include <stdint.h>
94decb7c 20#include <inttypes.h>
e4799a35
KZ
21#include <stdarg.h>
22
23#include "partitions.h"
d8a84552 24#include "sysfs.h"
e4799a35
KZ
25
26/**
fd7c9e35 27 * SECTION: partitions
e4799a35
KZ
28 * @title: Partitions probing
29 * @short_description: partitions tables detection and parsing
30 *
31 * This chain supports binary and NAME=value interfaces, but complete PT
9f4664ee
KZ
32 * description is provided by binary interface only. The libblkid prober is
33 * compatible with kernel partition tables parser. The parser does not return
34 * empty (size=0) partitions or special hidden partitions.
e4799a35
KZ
35 *
36 * NAME=value interface, supported tags:
37 *
38 * @PTTYPE: partition table type (dos, gpt, etc.).
39 *
62e83b1d
KZ
40 * @PTUUID: partition table id (uuid for gpt, hex for dos).
41
385c3535
KZ
42 * @PART_ENTRY_SCHEME: partition table type
43 *
0c6dc615
KZ
44 * @PART_ENTRY_NAME: partition name (gpt and mac only)
45 *
f948a147 46 * @PART_ENTRY_UUID: partition UUID (gpt, or pseudo IDs for MBR)
0c6dc615 47 *
dcc58f62 48 * @PART_ENTRY_TYPE: partition type, 0xNN (e.g 0x82) or type UUID (gpt only) or type string (mac)
0c6dc615 49 *
75838802
KZ
50 * @PART_ENTRY_FLAGS: partition flags (e.g. boot_ind) or attributes (e.g. gpt attributes)
51 *
385c3535
KZ
52 * @PART_ENTRY_NUMBER: partition number
53 *
d945f469
KZ
54 * @PART_ENTRY_OFFSET: the begin of the partition
55 *
56 * @PART_ENTRY_SIZE: size of the partition
57 *
fd7c9e35 58 * @PART_ENTRY_DISK: whole-disk maj:min
d945f469 59 *
e4799a35
KZ
60 * Example:
61 *
62 * <informalexample>
63 * <programlisting>
64 * blkid_probe pr;
e4799a35
KZ
65 * const char *ptname;
66 *
ab347a14
KZ
67 * pr = blkid_new_probe_from_filename(devname);
68 * if (!pr)
9e930041 69 * err("%s: failed to open device", devname);
e4799a35
KZ
70 *
71 * blkid_probe_enable_partitions(pr, TRUE);
72 * blkid_do_fullprobe(pr);
73 *
74 * blkid_probe_lookup_value(pr, "PTTYPE", &ptname, NULL);
75 * printf("%s partition type detected\n", pttype);
76 *
77 * blkid_free_probe(pr);
e4799a35
KZ
78 *
79 * // don't forget to check return codes in your code!
80 * </programlisting>
81 * </informalexample>
82 *
83 * Binary interface:
84 *
85 * <informalexample>
86 * <programlisting>
87 * blkid_probe pr;
88 * blkid_partlist ls;
89 * int nparts, i;
e4799a35 90 *
ab347a14
KZ
91 * pr = blkid_new_probe_from_filename(devname);
92 * if (!pr)
9e930041 93 * err("%s: failed to open device", devname);
e4799a35
KZ
94 *
95 * ls = blkid_probe_get_partitions(pr);
96 * nparts = blkid_partlist_numof_partitions(ls);
97 *
98 * for (i = 0; i < nparts; i++) {
99 * blkid_partition par = blkid_partlist_get_partition(ls, i);
100 * printf("#%d: %llu %llu 0x%x",
101 * blkid_partition_get_partno(par),
102 * blkid_partition_get_start(par),
103 * blkid_partition_get_size(par),
104 * blkid_partition_get_type(par));
105 * }
106 *
107 * blkid_free_probe(pr);
e4799a35
KZ
108 *
109 * // don't forget to check return codes in your code!
110 * </programlisting>
111 * </informalexample>
112 */
113
114/*
115 * Chain driver function
116 */
117static int partitions_probe(blkid_probe pr, struct blkid_chain *chn);
118static void partitions_free_data(blkid_probe pr, void *data);
119
120/*
121 * Partitions chain probing functions
122 */
123static const struct blkid_idinfo *idinfos[] =
124{
c472fc8e 125 &aix_pt_idinfo,
0e728765 126 &sgi_pt_idinfo,
d23768d8 127 &sun_pt_idinfo,
60ad0bbb 128 &dos_pt_idinfo,
7a8f74e8 129 &gpt_pt_idinfo,
e3c69a7d 130 &pmbr_pt_idinfo, /* always after GPT */
5c9204dc 131 &mac_pt_idinfo,
dad504d9 132 &ultrix_pt_idinfo,
85ecbfe7
KZ
133 &bsd_pt_idinfo,
134 &unixware_pt_idinfo,
b507ce03 135 &solaris_x86_pt_idinfo,
50c71f25
VD
136 &minix_pt_idinfo,
137 &atari_pt_idinfo
e4799a35
KZ
138};
139
140/*
141 * Driver definition
142 */
143const struct blkid_chaindrv partitions_drv = {
144 .id = BLKID_CHAIN_PARTS,
145 .name = "partitions",
146 .dflt_enabled = FALSE,
147 .idinfos = idinfos,
148 .nidinfos = ARRAY_SIZE(idinfos),
149 .has_fltr = TRUE,
150 .probe = partitions_probe,
151 .safeprobe = partitions_probe,
152 .free_data = partitions_free_data
153};
154
155
156/*
157 * For compatibility with the rest of libblkid API (with the old high-level
158 * API) we use completely opaque typedefs for all structs. Don't forget that
159 * the final blkid_* types are pointers! See blkid.h.
160 *
161 * [Just for the record, I hate typedef for pointers --kzak]
162 */
163
164/* exported as opaque type "blkid_parttable" */
165struct blkid_struct_parttable {
166 const char *type; /* partition table type */
f12cd8d1 167 uint64_t offset; /* begin of the partition table (in bytes) */
e4799a35
KZ
168 int nparts; /* number of partitions */
169 blkid_partition parent; /* parent of nested partition table */
b443c177 170 char id[UUID_STR_LEN]; /* PT identifier (e.g. UUID for GPT) */
e4799a35
KZ
171
172 struct list_head t_tabs; /* all tables */
173};
174
175/* exported as opaque type "blkid_partition" */
176struct blkid_struct_partition {
f12cd8d1
KZ
177 uint64_t start; /* begin of the partition (512-bytes sectors) */
178 uint64_t size; /* size of the partitions (512-bytes sectors) */
0e8a8065 179
e4799a35 180 int type; /* partition type */
b443c177 181 char typestr[UUID_STR_LEN]; /* partition type string (GPT and Mac) */
e4799a35 182
75838802
KZ
183 unsigned long long flags; /* partition flags / attributes */
184
e4799a35 185 int partno; /* partition number */
b443c177 186 char uuid[UUID_STR_LEN]; /* UUID (when supported by PT), e.g GPT */
9e930041 187 unsigned char name[128]; /* Partition in UTF8 name (when supported by PT), e.g. Mac */
e4799a35
KZ
188
189 blkid_parttable tab; /* partition table */
190};
191
192/* exported as opaque type "blkid_partlist" */
193struct blkid_struct_partlist {
194 int next_partno; /* next partition number */
195 blkid_partition next_parent; /* next parent if parsing nested PT */
196
197 int nparts; /* number of partitions */
198 int nparts_max; /* max.number of partitions */
199 blkid_partition parts; /* array of partitions */
200
201 struct list_head l_tabs; /* list of partition tables */
202};
203
0c6dc615
KZ
204static int blkid_partitions_probe_partition(blkid_probe pr);
205
e4799a35
KZ
206/**
207 * blkid_probe_enable_partitions:
208 * @pr: probe
209 * @enable: TRUE/FALSE
210 *
211 * Enables/disables the partitions probing for non-binary interface.
212 *
213 * Returns: 0 on success, or -1 in case of error.
214 */
215int blkid_probe_enable_partitions(blkid_probe pr, int enable)
216{
e4799a35
KZ
217 pr->chains[BLKID_CHAIN_PARTS].enabled = enable;
218 return 0;
219}
220
221/**
222 * blkid_probe_set_partitions_flags:
223 * @pr: prober
224 * @flags: BLKID_PARTS_* flags
225 *
226 * Sets probing flags to the partitions prober. This function is optional.
227 *
228 * Returns: 0 on success, or -1 in case of error.
229 */
230int blkid_probe_set_partitions_flags(blkid_probe pr, int flags)
231{
e4799a35
KZ
232 pr->chains[BLKID_CHAIN_PARTS].flags = flags;
233 return 0;
234}
235
48805d56
KZ
236/**
237 * blkid_probe_reset_partitions_filter:
238 * @pr: prober
239 *
240 * Resets partitions probing filter
241 *
242 * Returns: 0 on success, or -1 in case of error.
243 */
244int blkid_probe_reset_partitions_filter(blkid_probe pr)
245{
246 return __blkid_probe_reset_filter(pr, BLKID_CHAIN_PARTS);
247}
248
249/**
250 * blkid_probe_invert_partitions_filter:
251 * @pr: prober
252 *
253 * Inverts partitions probing filter
254 *
255 * Returns: 0 on success, or -1 in case of error.
256 */
257int blkid_probe_invert_partitions_filter(blkid_probe pr)
258{
259 return __blkid_probe_invert_filter(pr, BLKID_CHAIN_PARTS);
260}
261
262/**
263 * blkid_probe_filter_partitions_type:
264 * @pr: prober
265 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
266 * @names: NULL terminated array of probing function names (e.g. "vfat").
267 *
fd7c9e35
KZ
268 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names
269 *
270 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
48805d56
KZ
271 *
272 * Returns: 0 on success, or -1 in case of error.
273 */
274int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *names[])
275{
276 return __blkid_probe_filter_types(pr, BLKID_CHAIN_PARTS, flag, names);
277}
278
e4799a35
KZ
279/**
280 * blkid_probe_get_partitions:
281 * @pr: probe
282 *
283 * This is a binary interface for partitions. See also blkid_partlist_*
284 * functions.
285 *
286 * This function is independent on blkid_do_[safe,full]probe() and
287 * blkid_probe_enable_partitions() calls.
288 *
a0fff7ce
KZ
289 * WARNING: the returned object will be overwritten by the next
290 * blkid_probe_get_partitions() call for the same @pr. If you want to
291 * use more blkid_partlist objects in the same time you have to create
292 * more blkid_probe handlers (see blkid_new_probe()).
293 *
e4799a35
KZ
294 * Returns: list of partitions, or NULL in case of error.
295 */
296blkid_partlist blkid_probe_get_partitions(blkid_probe pr)
297{
298 return (blkid_partlist) blkid_probe_get_binary_data(pr,
299 &pr->chains[BLKID_CHAIN_PARTS]);
300}
301
302/* for internal usage only */
303blkid_partlist blkid_probe_get_partlist(blkid_probe pr)
304{
305 return (blkid_partlist) pr->chains[BLKID_CHAIN_PARTS].data;
306}
307
ac8874ca
KZ
308static void blkid_probe_set_partlist(blkid_probe pr, blkid_partlist ls)
309{
310 pr->chains[BLKID_CHAIN_PARTS].data = ls;
311}
312
e4799a35
KZ
313static void ref_parttable(blkid_parttable tab)
314{
315 tab->nparts++;
316}
317
318static void unref_parttable(blkid_parttable tab)
319{
320 tab->nparts--;
321
322 if (tab->nparts <= 0) {
323 list_del(&tab->t_tabs);
324 free(tab);
325 }
326}
327
328/* free all allocated parttables */
329static void free_parttables(blkid_partlist ls)
330{
331 if (!ls || !ls->l_tabs.next)
332 return;
333
334 /* remove unassigned partition tables */
335 while (!list_empty(&ls->l_tabs)) {
336 blkid_parttable tab = list_entry(ls->l_tabs.next,
337 struct blkid_struct_parttable, t_tabs);
338 unref_parttable(tab);
339 }
340}
341
01fb8c00 342static void reset_partlist(blkid_partlist ls)
e4799a35
KZ
343{
344 if (!ls)
345 return;
346
347 free_parttables(ls);
348
349 if (ls->next_partno) {
350 /* already initialized - reset */
351 int tmp_nparts = ls->nparts_max;
352 blkid_partition tmp_parts = ls->parts;
353
354 memset(ls, 0, sizeof(struct blkid_struct_partlist));
355
356 ls->nparts_max = tmp_nparts;
357 ls->parts = tmp_parts;
358 }
359
360 ls->nparts = 0;
361 ls->next_partno = 1;
362 INIT_LIST_HEAD(&ls->l_tabs);
363
c62a6311 364 DBG(LOWPROBE, ul_debug("partlist reset"));
e4799a35
KZ
365}
366
01fb8c00 367static blkid_partlist partitions_init_data(struct blkid_chain *chn)
e4799a35
KZ
368{
369 blkid_partlist ls;
370
371 if (chn->data)
372 ls = (blkid_partlist) chn->data;
373 else {
374 /* allocate the new list of partitions */
375 ls = calloc(1, sizeof(struct blkid_struct_partlist));
376 if (!ls)
377 return NULL;
378 chn->data = (void *) ls;
379 }
380
01fb8c00 381 reset_partlist(ls);
e4799a35 382
63c9c05d 383 DBG(LOWPROBE, ul_debug("parts: initialized partitions list (size=%d)", ls->nparts_max));
e4799a35
KZ
384 return ls;
385}
386
01fb8c00
KZ
387static void partitions_free_data(blkid_probe pr __attribute__((__unused__)),
388 void *data)
e4799a35
KZ
389{
390 blkid_partlist ls = (blkid_partlist) data;
391
392 if (!ls)
393 return;
394
395 free_parttables(ls);
396
397 /* deallocate partitions and partlist */
398 free(ls->parts);
399 free(ls);
400}
401
402blkid_parttable blkid_partlist_new_parttable(blkid_partlist ls,
f12cd8d1 403 const char *type, uint64_t offset)
e4799a35
KZ
404{
405 blkid_parttable tab;
406
407 tab = calloc(1, sizeof(struct blkid_struct_parttable));
408 if (!tab)
409 return NULL;
410 tab->type = type;
411 tab->offset = offset;
412 tab->parent = ls->next_parent;
413
414 INIT_LIST_HEAD(&tab->t_tabs);
415 list_add_tail(&tab->t_tabs, &ls->l_tabs);
416
c62a6311 417 DBG(LOWPROBE, ul_debug("parts: create a new partition table "
63c9c05d 418 "(type=%s, offset=%"PRId64")", type, offset));
e4799a35
KZ
419 return tab;
420}
421
422static blkid_partition new_partition(blkid_partlist ls, blkid_parttable tab)
423{
424 blkid_partition par;
425
426 if (ls->nparts + 1 > ls->nparts_max) {
427 /* Linux kernel has DISK_MAX_PARTS=256, but it's too much for
9e930041 428 * generic Linux machine -- let start with 32 partitions.
e4799a35 429 */
8a2c2dab 430 void *tmp = realloc(ls->parts, (ls->nparts_max + 32) *
e4799a35 431 sizeof(struct blkid_struct_partition));
8a2c2dab 432 if (!tmp)
e4799a35 433 return NULL;
8a2c2dab 434 ls->parts = tmp;
e4799a35
KZ
435 ls->nparts_max += 32;
436 }
437
438 par = &ls->parts[ls->nparts++];
439 memset(par, 0, sizeof(struct blkid_struct_partition));
440
441 ref_parttable(tab);
442 par->tab = tab;
9f4664ee 443 par->partno = blkid_partlist_increment_partno(ls);
e4799a35
KZ
444
445 return par;
446}
447
448blkid_partition blkid_partlist_add_partition(blkid_partlist ls,
f12cd8d1 449 blkid_parttable tab, uint64_t start, uint64_t size)
e4799a35
KZ
450{
451 blkid_partition par = new_partition(ls, tab);
452
453 if (!par)
454 return NULL;
455
e4799a35
KZ
456 par->start = start;
457 par->size = size;
458
63c9c05d
KZ
459 DBG(LOWPROBE, ul_debug("parts: add partition (start=%"
460 PRIu64 ", size=%" PRIu64 ")",
461 par->start, par->size));
e4799a35
KZ
462 return par;
463}
464
465/* allows to modify used partitions numbers (for example for logical partitions) */
466int blkid_partlist_set_partno(blkid_partlist ls, int partno)
467{
468 if (!ls)
469 return -1;
470 ls->next_partno = partno;
471 return 0;
472}
473
9f4664ee
KZ
474int blkid_partlist_increment_partno(blkid_partlist ls)
475{
476 return ls ? ls->next_partno++ : -1;
477}
478
e4799a35 479/* allows to set "parent" for the next nested partition */
b55b9fcc 480static int blkid_partlist_set_parent(blkid_partlist ls, blkid_partition par)
e4799a35
KZ
481{
482 if (!ls)
483 return -1;
484 ls->next_parent = par;
485 return 0;
486}
487
488blkid_partition blkid_partlist_get_parent(blkid_partlist ls)
489{
490 if (!ls)
491 return NULL;
492 return ls->next_parent;
493}
494
495int blkid_partitions_need_typeonly(blkid_probe pr)
496{
497 struct blkid_chain *chn = blkid_probe_get_chain(pr);
498
499 return chn && chn->data && chn->binary ? FALSE : TRUE;
500}
501
502/* get private chain flags */
503int blkid_partitions_get_flags(blkid_probe pr)
504{
505 struct blkid_chain *chn = blkid_probe_get_chain(pr);
506
507 return chn ? chn->flags : 0;
508}
509
510/* check if @start and @size are within @par partition */
511int blkid_is_nested_dimension(blkid_partition par,
f12cd8d1 512 uint64_t start, uint64_t size)
e4799a35 513{
f12cd8d1
KZ
514 uint64_t pstart;
515 uint64_t psize;
e4799a35
KZ
516
517 if (!par)
518 return 0;
519
520 pstart = blkid_partition_get_start(par);
521 psize = blkid_partition_get_size(par);
522
523 if (start < pstart || start + size > pstart + psize)
524 return 0;
525
526 return 1;
527}
528
44765fdd
KZ
529static int idinfo_probe(blkid_probe pr, const struct blkid_idinfo *id,
530 struct blkid_chain *chn)
e4799a35 531{
c03d12d8 532 const struct blkid_idmag *mag = NULL;
f12cd8d1 533 uint64_t off;
d2a8b8d1 534 int rc = BLKID_PROBE_NONE; /* default is nothing */
e4799a35 535
b9710f1f 536 if (pr->size <= 0 || (id->minsz && (unsigned)id->minsz > pr->size))
cc62a975 537 goto nothing; /* the device is too small */
20e1c3dc
KZ
538 if (pr->flags & BLKID_FL_NOSCAN_DEV)
539 goto nothing;
cc62a975 540
296d96e2
HR
541 rc = blkid_probe_get_idmag(pr, id, &off, &mag);
542 if (rc != BLKID_PROBE_OK)
e4799a35
KZ
543 goto nothing;
544
545 /* final check by probing function */
546 if (id->probefunc) {
c62a6311 547 DBG(LOWPROBE, ul_debug(
0540ea54 548 "%s: ---> call probefunc()", id->name));
e4799a35 549 rc = id->probefunc(pr, mag);
296d96e2 550 if (rc < 0) {
e4799a35 551 /* reset after error */
01fb8c00 552 reset_partlist(blkid_probe_get_partlist(pr));
44765fdd 553 if (chn && !chn->binary)
af17d349 554 blkid_probe_chain_reset_values(pr, chn);
c62a6311 555 DBG(LOWPROBE, ul_debug("%s probefunc failed, rc %d",
296d96e2 556 id->name, rc));
e4799a35 557 }
296d96e2 558 if (rc == BLKID_PROBE_OK && mag && chn && !chn->binary)
2b6e6d55 559 rc = blkid_probe_set_magic(pr, off, mag->len,
44765fdd
KZ
560 (unsigned char *) mag->magic);
561
c62a6311 562 DBG(LOWPROBE, ul_debug("%s: <--- (rc = %d)", id->name, rc));
e4799a35
KZ
563 }
564
e4799a35 565 return rc;
d2a8b8d1
KZ
566
567nothing:
568 return BLKID_PROBE_NONE;
e4799a35
KZ
569}
570
571/*
572 * The blkid_do_probe() backend.
573 */
574static int partitions_probe(blkid_probe pr, struct blkid_chain *chn)
575{
296d96e2 576 int rc = BLKID_PROBE_NONE;
01fb8c00 577 size_t i;
e4799a35
KZ
578
579 if (!pr || chn->idx < -1)
296d96e2 580 return -EINVAL;
20e1c3dc 581
af17d349 582 blkid_probe_chain_reset_values(pr, chn);
e4799a35 583
d2a8b8d1
KZ
584 if (pr->flags & BLKID_FL_NOSCAN_DEV)
585 return BLKID_PROBE_NONE;
586
e4799a35 587 if (chn->binary)
01fb8c00 588 partitions_init_data(chn);
e4799a35 589
a9eef56c 590 if (!pr->wipe_size && (pr->prob_flags & BLKID_PROBE_FL_IGNORE_PT))
c81e7008
KZ
591 goto details_only;
592
c62a6311 593 DBG(LOWPROBE, ul_debug("--> starting probing loop [PARTS idx=%d]",
e4799a35
KZ
594 chn->idx));
595
01fb8c00 596 i = chn->idx < 0 ? 0 : chn->idx + 1U;
e4799a35
KZ
597
598 for ( ; i < ARRAY_SIZE(idinfos); i++) {
599 const char *name;
600
601 chn->idx = i;
602
603 /* apply filter */
604 if (chn->fltr && blkid_bmp_get_item(chn->fltr, i))
605 continue;
606
607 /* apply checks from idinfo */
296d96e2
HR
608 rc = idinfo_probe(pr, idinfos[i], chn);
609 if (rc < 0)
610 break;
611 if (rc != BLKID_PROBE_OK)
e4799a35
KZ
612 continue;
613
614 name = idinfos[i]->name;
615
19f87d1d 616 if (!chn->binary)
62e83b1d
KZ
617 /*
618 * Non-binary interface, set generic variables. Note
619 * that the another variables could be set in prober
620 * functions.
621 */
19f87d1d
KZ
622 blkid_probe_set_value(pr, "PTTYPE",
623 (unsigned char *) name,
624 strlen(name) + 1);
62e83b1d 625
c62a6311 626 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [PARTS idx=%d]",
e4799a35 627 name, chn->idx));
d2a8b8d1 628 rc = BLKID_PROBE_OK;
0c6dc615 629 break;
e4799a35 630 }
0c6dc615 631
296d96e2 632 if (rc != BLKID_PROBE_OK) {
c62a6311 633 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [PARTS idx=%d]",
296d96e2 634 rc, chn->idx));
0c6dc615
KZ
635 }
636
c81e7008 637details_only:
0c6dc615
KZ
638 /*
639 * Gather PART_ENTRY_* values if the current device is a partition.
640 */
5b575d43 641 if ((rc == BLKID_PROBE_OK || rc == BLKID_PROBE_NONE) && !chn->binary &&
781aa7b3
KZ
642 (blkid_partitions_get_flags(pr) & BLKID_PARTS_ENTRY_DETAILS)) {
643
5b575d43 644 int xrc = blkid_partitions_probe_partition(pr);
a6161898
KZ
645
646 /* partition entry probing is optional, and "not-found" from
647 * this sub-probing must not to overwrite previous success. */
5b575d43 648 if (xrc < 0)
a6161898
KZ
649 rc = xrc; /* always propagate errors */
650 else if (rc == BLKID_PROBE_NONE)
651 rc = xrc;
0c6dc615
KZ
652 }
653
a6161898 654 DBG(LOWPROBE, ul_debug("partitions probe done [rc=%d]", rc));
0c6dc615 655 return rc;
e4799a35
KZ
656}
657
658/* Probe for nested partition table within the parental partition */
659int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent,
660 const struct blkid_idinfo *id)
661{
ac8874ca 662 blkid_probe prc;
296d96e2 663 int rc;
e4799a35 664 blkid_partlist ls;
f12cd8d1 665 uint64_t sz, off;
e4799a35 666
c62a6311 667 DBG(LOWPROBE, ul_debug(
63c9c05d
KZ
668 "parts: ----> %s subprobe requested)",
669 id->name));
e4799a35
KZ
670
671 if (!pr || !parent || !parent->size)
296d96e2 672 return -EINVAL;
20e1c3dc
KZ
673 if (pr->flags & BLKID_FL_NOSCAN_DEV)
674 return BLKID_PROBE_NONE;
e4799a35 675
ac8874ca 676 /* range defined by parent */
f12cd8d1
KZ
677 sz = parent->size << 9;
678 off = parent->start << 9;
e4799a35 679
ac8874ca 680 if (off < pr->off || pr->off + pr->size < off + sz) {
c62a6311 681 DBG(LOWPROBE, ul_debug(
0540ea54 682 "ERROR: parts: <---- '%s' subprobe: overflow detected.",
e4799a35 683 id->name));
296d96e2 684 return -ENOSPC;
e4799a35
KZ
685 }
686
ac8874ca
KZ
687 /* create private prober */
688 prc = blkid_clone_probe(pr);
689 if (!prc)
296d96e2 690 return -ENOMEM;
ac8874ca
KZ
691
692 blkid_probe_set_dimension(prc, off, sz);
ccdf9fda 693
3b159691 694 /* clone is always with reset chain, fix it */
ac8874ca 695 prc->cur_chain = blkid_probe_get_chain(pr);
e4799a35 696
ac8874ca
KZ
697 /*
698 * Set 'parent' to the current list of the partitions and use the list
699 * in cloned prober (so the cloned prober will extend the current list
700 * of partitions rather than create a new).
701 */
702 ls = blkid_probe_get_partlist(pr);
e4799a35
KZ
703 blkid_partlist_set_parent(ls, parent);
704
ac8874ca 705 blkid_probe_set_partlist(prc, ls);
e4799a35 706
44765fdd 707 rc = idinfo_probe(prc, id, blkid_probe_get_chain(pr));
e4799a35 708
ac8874ca
KZ
709 blkid_probe_set_partlist(prc, NULL);
710 blkid_partlist_set_parent(ls, NULL);
e4799a35 711
ac8874ca 712 blkid_free_probe(prc); /* free cloned prober */
ccdf9fda 713
c62a6311 714 DBG(LOWPROBE, ul_debug(
63c9c05d
KZ
715 "parts: <---- %s subprobe done (rc=%d)",
716 id->name, rc));
e4799a35
KZ
717
718 return rc;
719}
720
0c6dc615
KZ
721static int blkid_partitions_probe_partition(blkid_probe pr)
722{
0c6dc615
KZ
723 blkid_probe disk_pr = NULL;
724 blkid_partlist ls;
725 blkid_partition par;
fd9f45e1 726 dev_t devno;
0c6dc615 727
a6161898
KZ
728 DBG(LOWPROBE, ul_debug("parts: start probing for partition entry"));
729
20e1c3dc
KZ
730 if (pr->flags & BLKID_FL_NOSCAN_DEV)
731 goto nothing;
732
0c6dc615
KZ
733 devno = blkid_probe_get_devno(pr);
734 if (!devno)
735 goto nothing;
736
fd9f45e1 737 disk_pr = blkid_probe_get_wholedisk_probe(pr);
0c6dc615
KZ
738 if (!disk_pr)
739 goto nothing;
740
741 /* parse PT */
742 ls = blkid_probe_get_partitions(disk_pr);
743 if (!ls)
744 goto nothing;
745
746 par = blkid_partlist_devno_to_partition(ls, devno);
d2a8b8d1
KZ
747 if (!par)
748 goto nothing;
749 else {
0c6dc615 750 const char *v;
fbe66f6b 751 blkid_parttable tab = blkid_partition_get_table(par);
ffb06a15 752 dev_t disk = blkid_probe_get_devno(disk_pr);
fbe66f6b
KZ
753
754 if (tab) {
755 v = blkid_parttable_get_type(tab);
756 if (v)
757 blkid_probe_set_value(pr, "PART_ENTRY_SCHEME",
758 (unsigned char *) v, strlen(v) + 1);
759 }
0c6dc615
KZ
760
761 v = blkid_partition_get_name(par);
762 if (v)
763 blkid_probe_set_value(pr, "PART_ENTRY_NAME",
764 (unsigned char *) v, strlen(v) + 1);
765
766 v = blkid_partition_get_uuid(par);
767 if (v)
768 blkid_probe_set_value(pr, "PART_ENTRY_UUID",
769 (unsigned char *) v, strlen(v) + 1);
770
771 /* type */
772 v = blkid_partition_get_type_string(par);
773 if (v)
774 blkid_probe_set_value(pr, "PART_ENTRY_TYPE",
775 (unsigned char *) v, strlen(v) + 1);
776 else
777 blkid_probe_sprintf_value(pr, "PART_ENTRY_TYPE",
75838802
KZ
778 "0x%x", blkid_partition_get_type(par));
779
780 if (blkid_partition_get_flags(par))
781 blkid_probe_sprintf_value(pr, "PART_ENTRY_FLAGS",
782 "0x%llx", blkid_partition_get_flags(par));
fbe66f6b
KZ
783
784 blkid_probe_sprintf_value(pr, "PART_ENTRY_NUMBER",
785 "%d", blkid_partition_get_partno(par));
ffb06a15
KZ
786
787 blkid_probe_sprintf_value(pr, "PART_ENTRY_OFFSET", "%jd",
fdbd7bb9 788 (intmax_t)blkid_partition_get_start(par));
ffb06a15 789 blkid_probe_sprintf_value(pr, "PART_ENTRY_SIZE", "%jd",
fdbd7bb9 790 (intmax_t)blkid_partition_get_size(par));
ffb06a15
KZ
791
792 blkid_probe_sprintf_value(pr, "PART_ENTRY_DISK", "%u:%u",
793 major(disk), minor(disk));
0c6dc615 794 }
d2a8b8d1
KZ
795
796 DBG(LOWPROBE, ul_debug("parts: end probing for partition entry [success]"));
797 return BLKID_PROBE_OK;
798
0c6dc615 799nothing:
d2a8b8d1
KZ
800 DBG(LOWPROBE, ul_debug("parts: end probing for partition entry [nothing]"));
801 return BLKID_PROBE_NONE;
802
803
0c6dc615
KZ
804}
805
c81e7008
KZ
806/*
807 * Returns 1 if the device is whole-disk and the area specified by @offset and
808 * @size is covered by any partition.
809 */
810int blkid_probe_is_covered_by_pt(blkid_probe pr,
f12cd8d1 811 uint64_t offset, uint64_t size)
c81e7008 812{
20e1c3dc 813 blkid_probe prc = NULL;
c81e7008 814 blkid_partlist ls = NULL;
f12cd8d1 815 uint64_t start, end;
c81e7008
KZ
816 int nparts, i, rc = 0;
817
c62a6311 818 DBG(LOWPROBE, ul_debug(
fdbd7bb9 819 "=> checking if off=%"PRIu64" size=%"PRIu64" covered by PT",
c81e7008
KZ
820 offset, size));
821
20e1c3dc
KZ
822 if (pr->flags & BLKID_FL_NOSCAN_DEV)
823 goto done;
824
fd9f45e1
KZ
825 prc = blkid_clone_probe(pr);
826 if (!prc)
827 goto done;
828
829 ls = blkid_probe_get_partitions(prc);
c81e7008
KZ
830 if (!ls)
831 goto done;
832
833 nparts = blkid_partlist_numof_partitions(ls);
834 if (!nparts)
835 goto done;
836
837 end = (offset + size) >> 9;
838 start = offset >> 9;
839
66d8e050
KZ
840 /* check if the partition table fits into the device */
841 for (i = 0; i < nparts; i++) {
842 blkid_partition par = &ls->parts[i];
843
a09f0933 844 if (par->start + par->size > (pr->size >> 9)) {
c62a6311 845 DBG(LOWPROBE, ul_debug("partition #%d overflows "
0540ea54 846 "device (off=%" PRId64 " size=%" PRId64 ")",
94decb7c 847 par->partno, par->start, par->size));
66d8e050
KZ
848 goto done;
849 }
850 }
851
852 /* check if the requested area is covered by PT */
c81e7008
KZ
853 for (i = 0; i < nparts; i++) {
854 blkid_partition par = &ls->parts[i];
855
856 if (start >= par->start && end <= par->start + par->size) {
857 rc = 1;
858 break;
859 }
860 }
861done:
fd9f45e1 862 blkid_free_probe(prc);
c81e7008 863
c62a6311 864 DBG(LOWPROBE, ul_debug("<= %s covered by PT", rc ? "IS" : "NOT"));
c81e7008
KZ
865 return rc;
866}
867
e4799a35
KZ
868/**
869 * blkid_known_pttype:
9e930041 870 * @pttype: partition name
e4799a35
KZ
871 *
872 * Returns: 1 for known or 0 for unknown partition type.
873 */
874int blkid_known_pttype(const char *pttype)
875{
01fb8c00 876 size_t i;
e4799a35
KZ
877
878 if (!pttype)
879 return 0;
880
881 for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
882 const struct blkid_idinfo *id = idinfos[i];
883 if (strcmp(id->name, pttype) == 0)
884 return 1;
885 }
886 return 0;
887}
888
635d9aa5
SK
889/**
890 * blkid_partitions_get_name:
891 * @idx: number >= 0
892 * @name: returns name of a supported partition
893 *
ae4e2abc
KZ
894 * Since: 2.30
895 *
635d9aa5
SK
896 * Returns: -1 if @idx is out of range, or 0 on success.
897 */
898int blkid_partitions_get_name(const size_t idx, const char **name)
899{
900 if (idx < ARRAY_SIZE(idinfos)) {
901 *name = idinfos[idx]->name;
902 return 0;
903 }
904 return -1;
905}
906
e4799a35
KZ
907/**
908 * blkid_partlist_numof_partitions:
909 * @ls: partitions list
910 *
911 * Returns: number of partitions in the list or -1 in case of error.
912 */
913int blkid_partlist_numof_partitions(blkid_partlist ls)
914{
7f787ced 915 return ls->nparts;
e4799a35
KZ
916}
917
19f87d1d
KZ
918/**
919 * blkid_partlist_get_table:
fd7c9e35 920 * @ls: partitions list
19f87d1d 921 *
fd7c9e35 922 * Returns: top-level partition table or NULL of there is not a partition table
19f87d1d
KZ
923 * on the device.
924 */
925blkid_parttable blkid_partlist_get_table(blkid_partlist ls)
926{
7f787ced 927 if (list_empty(&ls->l_tabs))
19f87d1d
KZ
928 return NULL;
929
930 return list_entry(ls->l_tabs.next,
931 struct blkid_struct_parttable, t_tabs);
932}
933
934
e4799a35
KZ
935/**
936 * blkid_partlist_get_partition:
937 * @ls: partitions list
938 * @n: partition number in range 0..N, where 'N' is blkid_partlist_numof_partitions().
939 *
940 * It's possible that the list of partitions is *empty*, but there is a valid
941 * partition table on the disk. This happen when on-disk details about
e9c2d185
KZ
942 * partitions are unknown or the partition table is empty.
943 *
944 * See also blkid_partlist_get_table().
e4799a35
KZ
945 *
946 * Returns: partition object or NULL in case or error.
947 */
948blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n)
949{
7f787ced 950 if (n < 0 || n >= ls->nparts)
e4799a35
KZ
951 return NULL;
952
953 return &ls->parts[n];
954}
955
50d1594c
KZ
956blkid_partition blkid_partlist_get_partition_by_start(blkid_partlist ls, uint64_t start)
957{
958 int i, nparts;
959 blkid_partition par;
960
961 nparts = blkid_partlist_numof_partitions(ls);
962 for (i = 0; i < nparts; i++) {
963 par = blkid_partlist_get_partition(ls, i);
964 if ((uint64_t) blkid_partition_get_start(par) == start)
965 return par;
966 }
967 return NULL;
968}
969
a3ebe0ec
KZ
970/**
971 * blkid_partlist_get_partition_by_partno
972 * @ls: partitions list
973 * @n: the partition number (e.g. 'N' from sda'N')
974 *
975 * This does not assume any order of the input blkid_partlist. And correctly
976 * handles "out of order" partition tables. partition N is located after
977 * partition N+1 on the disk.
978 *
979 * Returns: partition object or NULL in case or error.
980 */
981blkid_partition blkid_partlist_get_partition_by_partno(blkid_partlist ls, int n)
982{
983 int i, nparts;
984 blkid_partition par;
985
a3ebe0ec
KZ
986 nparts = blkid_partlist_numof_partitions(ls);
987 for (i = 0; i < nparts; i++) {
988 par = blkid_partlist_get_partition(ls, i);
989 if (n == blkid_partition_get_partno(par))
990 return par;
991 }
992 return NULL;
993}
994
995
0c6dc615
KZ
996/**
997 * blkid_partlist_devno_to_partition:
998 * @ls: partitions list
999 * @devno: requested partition
1000 *
1001 * This function tries to get start and size for @devno from sysfs and
1002 * returns a partition from @ls which matches with the values from sysfs.
1003 *
455fe9a0 1004 * This function is necessary when you want to make a relation between an entry
0c6dc615
KZ
1005 * in the partition table (@ls) and block devices in your system.
1006 *
1007 * Returns: partition object or NULL in case or error.
1008 */
1009blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno)
1010{
d8a84552 1011 struct sysfs_cxt sysfs;
0c6dc615 1012 uint64_t start, size;
a44fe768 1013 int i, rc, partno = 0;
0c6dc615 1014
9e930041 1015 DBG(LOWPROBE, ul_debug("trying to convert devno 0x%llx to partition",
c13d3432 1016 (long long) devno));
0c6dc615 1017
c13d3432 1018 if (sysfs_init(&sysfs, devno, NULL)) {
c62a6311 1019 DBG(LOWPROBE, ul_debug("failed t init sysfs context"));
c13d3432
KZ
1020 return NULL;
1021 }
a44fe768
KZ
1022 rc = sysfs_read_u64(&sysfs, "size", &size);
1023 if (!rc) {
1024 rc = sysfs_read_u64(&sysfs, "start", &start);
1025 if (rc) {
1026 /* try to get partition number from DM uuid.
1027 */
1028 char *uuid = sysfs_strdup(&sysfs, "dm/uuid");
1029 char *tmp = uuid;
1030 char *prefix = uuid ? strsep(&tmp, "-") : NULL;
1031
1032 if (prefix && strncasecmp(prefix, "part", 4) == 0) {
1033 char *end = NULL;
1034
1035 partno = strtol(prefix + 4, &end, 10);
1036 if (prefix == end || (end && *end))
1037 partno = 0;
1038 else
1039 rc = 0; /* success */
1040 }
1041 free(uuid);
1042 }
1043 }
d8a84552
KZ
1044
1045 sysfs_deinit(&sysfs);
1046
90e9fcda
KZ
1047 if (rc)
1048 return NULL;
1049
a44fe768 1050 if (partno) {
c62a6311 1051 DBG(LOWPROBE, ul_debug("mapped by DM, using partno %d", partno));
c13d3432 1052
a44fe768
KZ
1053 /*
1054 * Partition mapped by kpartx does not provide "start" offset
1055 * in /sys, but if we know partno and size of the partition
9e930041 1056 * that we can probably make the relation between the device
a44fe768
KZ
1057 * and an entry in partition table.
1058 */
1059 for (i = 0; i < ls->nparts; i++) {
1060 blkid_partition par = &ls->parts[i];
1061
1062 if (partno != blkid_partition_get_partno(par))
1063 continue;
1064
b9710f1f 1065 if (size == (uint64_t)blkid_partition_get_size(par) ||
f12cd8d1 1066 (blkid_partition_is_extended(par) && size <= 1024ULL))
a44fe768
KZ
1067 return par;
1068
1069 }
1070 return NULL;
1071 }
1072
c62a6311 1073 DBG(LOWPROBE, ul_debug("searching by offset/size"));
c13d3432 1074
0c6dc615
KZ
1075 for (i = 0; i < ls->nparts; i++) {
1076 blkid_partition par = &ls->parts[i];
1077
b9710f1f
RM
1078 if ((uint64_t)blkid_partition_get_start(par) == start &&
1079 (uint64_t)blkid_partition_get_size(par) == size)
0c6dc615 1080 return par;
4720bb19
KZ
1081
1082 /* exception for extended dos partitions */
b9710f1f 1083 if ((uint64_t)blkid_partition_get_start(par) == start &&
f12cd8d1 1084 blkid_partition_is_extended(par) && size <= 1024ULL)
4720bb19
KZ
1085 return par;
1086
0c6dc615 1087 }
c13d3432 1088
c62a6311 1089 DBG(LOWPROBE, ul_debug("not found partition for device"));
0c6dc615
KZ
1090 return NULL;
1091}
1092
a3ebe0ec 1093
635c0acc 1094int blkid_parttable_set_uuid(blkid_parttable tab, const unsigned char *id)
58312037
KZ
1095{
1096 if (!tab)
1097 return -1;
1098
635c0acc
KZ
1099 blkid_unparse_uuid(id, tab->id, sizeof(tab->id));
1100 return 0;
1101}
1102
1103int blkid_parttable_set_id(blkid_parttable tab, const unsigned char *id)
1104{
1105 if (!tab)
1106 return -1;
58312037 1107
635c0acc 1108 strncpy(tab->id, (const char *) id, sizeof(tab->id));
58312037
KZ
1109 return 0;
1110}
1111
62e83b1d
KZ
1112/* set PTUUID variable for non-binary API */
1113int blkid_partitions_set_ptuuid(blkid_probe pr, unsigned char *uuid)
1114{
1115 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1116 struct blkid_prval *v;
1117
1118 if (chn->binary || blkid_uuid_is_empty(uuid, 16))
1119 return 0;
1120
1121 v = blkid_probe_assign_value(pr, "PTUUID");
6c4a7811
OO
1122 if (!v)
1123 return -ENOMEM;
62e83b1d 1124
b443c177 1125 v->len = UUID_STR_LEN;
6c4a7811
OO
1126 v->data = calloc(1, v->len);
1127 if (v->data) {
1128 blkid_unparse_uuid(uuid, (char *) v->data, v->len);
1129 return 0;
1130 }
62e83b1d 1131
af17d349 1132 blkid_probe_free_value(v);
6c4a7811 1133 return -ENOMEM;
62e83b1d
KZ
1134}
1135
1136/* set PTUUID variable for non-binary API for tables where
1137 * the ID is just a string */
1138int blkid_partitions_strcpy_ptuuid(blkid_probe pr, char *str)
1139{
1140 struct blkid_chain *chn = blkid_probe_get_chain(pr);
62e83b1d
KZ
1141
1142 if (chn->binary || !str || !*str)
1143 return 0;
1144
6c4a7811
OO
1145 if (!blkid_probe_set_value(pr, "PTUUID", (unsigned char *) str, strlen(str) + 1))
1146 return -ENOMEM;
62e83b1d 1147
6c4a7811 1148 return 0;
62e83b1d
KZ
1149}
1150
58312037
KZ
1151/**
1152 * blkid_parttable_get_id:
1153 * @tab: partition table
1154 *
1155 * The ID is GPT disk UUID or DOS disk ID (in hex format).
1156 *
1157 * Returns: partition table ID (for example GPT disk UUID) or NULL
1158 */
1159const char *blkid_parttable_get_id(blkid_parttable tab)
1160{
7f787ced 1161 return *tab->id ? tab->id : NULL;
58312037
KZ
1162}
1163
1164
c2dacc61
KZ
1165int blkid_partition_set_type(blkid_partition par, int type)
1166{
c2dacc61
KZ
1167 par->type = type;
1168 return 0;
1169}
1170
e4799a35
KZ
1171/**
1172 * blkid_parttable_get_type:
1173 * @tab: partition table
1174 *
1175 * Returns: partition table type (type name, e.g. "dos", "gpt", ...)
1176 */
1177const char *blkid_parttable_get_type(blkid_parttable tab)
1178{
7f787ced 1179 return tab->type;
e4799a35
KZ
1180}
1181
1182/**
1183 * blkid_parttable_get_parent:
1184 * @tab: partition table
1185 *
9e930041 1186 * Returns: parent for nested partition tables or NULL.
e4799a35
KZ
1187 */
1188blkid_partition blkid_parttable_get_parent(blkid_parttable tab)
1189{
7f787ced 1190 return tab->parent;
e4799a35
KZ
1191}
1192
1193/**
1194 * blkid_parttable_get_offset:
1195 * @tab: partition table
1196 *
e4799a35
KZ
1197 * Note the position is relative to begin of the device as defined by
1198 * blkid_probe_set_device() for primary partition table, and relative
9e930041 1199 * to parental partition for nested partition tables.
e4799a35
KZ
1200 *
1201 * <informalexample>
1202 * <programlisting>
1203 * off_t offset;
1204 * blkid_partition parent = blkid_parttable_get_parent(tab);
1205 *
1206 * offset = blkid_parttable_get_offset(tab);
1207 *
1208 * if (parent)
1209 * / * 'tab' is nested partition table * /
1210 * offset += blkid_partition_get_start(parent);
1211 * </programlisting>
1212 * </informalexample>
fd7c9e35
KZ
1213
1214 * Returns: position (in bytes) of the partition table or -1 in case of error.
1215 *
e4799a35
KZ
1216 */
1217blkid_loff_t blkid_parttable_get_offset(blkid_parttable tab)
1218{
7f787ced 1219 return (blkid_loff_t)tab->offset;
e4799a35
KZ
1220}
1221
1222/**
1223 * blkid_partition_get_table:
1224 * @par: partition
1225 *
1226 * The "parttable" describes partition table. The table is usually the same for
1227 * all partitions -- except nested partition tables.
1228 *
1229 * For example bsd, solaris, etc. use a nested partition table within
1230 * standard primary dos partition:
1231 *
1232 * <informalexample>
1233 * <programlisting>
1234 *
1235 * -- dos partition table
1236 * 0: sda1 dos primary partition
1237 * 1: sda2 dos primary partition
1238 * -- bsd partition table (with in sda2)
1239 * 2: sda5 bds partition
1240 * 3: sda6 bds partition
1241 *
1242 * </programlisting>
1243 * </informalexample>
1244 *
1245 * The library does not to use a separate partition table object for dos logical
1246 * partitions (partitions within extended partition). It's possible to
1247 * differentiate between logical, extended and primary partitions by
1248 *
1249 * blkid_partition_is_{extended,primary,logical}().
1250 *
1251 * Returns: partition table object or NULL in case of error.
1252 */
1253blkid_parttable blkid_partition_get_table(blkid_partition par)
1254{
7f787ced 1255 return par->tab;
e4799a35
KZ
1256}
1257
1258static int partition_get_logical_type(blkid_partition par)
1259{
1260 blkid_parttable tab;
1261
1262 if (!par)
1263 return -1;
1264
1265 tab = blkid_partition_get_table(par);
1266 if (!tab || !tab->type)
1267 return -1;
1268
1269 if (tab->parent)
1270 return 'L'; /* report nested partitions as logical */
1271
1272 if (!strcmp(tab->type, "dos")) {
1273 if (par->partno > 4)
1274 return 'L'; /* logical */
1275
7e5f8f38
KZ
1276 if(par->type == MBR_DOS_EXTENDED_PARTITION ||
1277 par->type == MBR_W95_EXTENDED_PARTITION ||
1278 par->type == MBR_LINUX_EXTENDED_PARTITION)
e4799a35
KZ
1279 return 'E';
1280 }
1281 return 'P';
1282}
1283
1284/**
1285 * blkid_partition_is_primary:
1286 * @par: partition
1287 *
1288 * Note, this function returns FALSE for DOS extended partitions and
1289 * all partitions in nested partition tables.
1290 *
1291 * Returns: 1 if the partitions is primary partition or 0 if not.
1292 */
1293int blkid_partition_is_primary(blkid_partition par)
1294{
1295 return partition_get_logical_type(par) == 'P' ? TRUE : FALSE;
1296}
1297
1298/**
1299 * blkid_partition_is_extended:
1300 * @par: partition
1301 *
1302 * Returns: 1 if the partitions is extended (dos, windows or linux)
1303 * partition or 0 if not.
1304 */
1305int blkid_partition_is_extended(blkid_partition par)
1306{
1307 return partition_get_logical_type(par) == 'E' ? TRUE : FALSE;
1308}
1309
1310/**
1311 * blkid_partition_is_logical:
1312 * @par: partition
1313 *
1314 * Note that this function returns TRUE for all partitions in all
1315 * nested partition tables (e.g. BSD labels).
1316 *
1317 * Returns: 1 if the partitions is logical partition or 0 if not.
1318 */
1319int blkid_partition_is_logical(blkid_partition par)
1320{
1321 return partition_get_logical_type(par) == 'L' ? TRUE : FALSE;
1322}
1323
0e8a8065
KZ
1324static void set_string(unsigned char *item, size_t max,
1325 const unsigned char *data, size_t len)
e4799a35 1326{
0e8a8065
KZ
1327 if (len >= max)
1328 len = max - 1;
e4799a35 1329
0e8a8065
KZ
1330 memcpy(item, data, len);
1331 item[len] = '\0';
e4799a35 1332
c2dbd49b 1333 blkid_rtrim_whitespace(item);
0e8a8065
KZ
1334}
1335
1336int blkid_partition_set_name(blkid_partition par,
1337 const unsigned char *name, size_t len)
1338{
1339 if (!par)
1340 return -1;
1341
1342 set_string(par->name, sizeof(par->name), name, len);
e4799a35
KZ
1343 return 0;
1344}
1345
1346int blkid_partition_set_utf8name(blkid_partition par, const unsigned char *name,
1347 size_t len, int enc)
1348{
1349 if (!par)
1350 return -1;
c2dbd49b 1351
e4799a35 1352 blkid_encode_to_utf8(enc, par->name, sizeof(par->name), name, len);
c2dbd49b 1353 blkid_rtrim_whitespace(par->name);
e4799a35
KZ
1354 return 0;
1355}
1356
1357int blkid_partition_set_uuid(blkid_partition par, const unsigned char *uuid)
1358{
1359 if (!par)
1360 return -1;
1361
1362 blkid_unparse_uuid(uuid, par->uuid, sizeof(par->uuid));
1363 return 0;
1364}
1365
d67cc288
KZ
1366int blkid_partition_gen_uuid(blkid_partition par)
1367{
1368 if (!par || !par->tab || !*par->tab->id)
1369 return -1;
1370
feeeaca9 1371 snprintf(par->uuid, sizeof(par->uuid), "%.33s-%02x",
d67cc288
KZ
1372 par->tab->id, par->partno);
1373 return 0;
1374}
1375
e4799a35
KZ
1376/**
1377 * blkid_partition_get_name:
1378 * @par: partition
1379 *
1380 * Returns: partition name string if supported by PT (e.g. Mac) or NULL.
1381 */
1382const char *blkid_partition_get_name(blkid_partition par)
1383{
7f787ced 1384 return *par->name ? (char *) par->name : NULL;
e4799a35
KZ
1385}
1386
1387/**
1388 * blkid_partition_get_uuid:
1389 * @par: partition
1390 *
1391 * Returns: partition UUID string if supported by PT (e.g. GPT) or NULL.
1392 */
1393const char *blkid_partition_get_uuid(blkid_partition par)
1394{
7f787ced 1395 return *par->uuid ? par->uuid : NULL;
e4799a35
KZ
1396}
1397
1398/**
1399 * blkid_partition_get_partno:
1400 * @par: partition
1401 *
9e930041
SR
1402 * Returns: proposed partition number (e.g. 'N' from sda'N') or -1 in case of
1403 * error. Note that the number is generate by library independently on your OS.
e4799a35
KZ
1404 */
1405int blkid_partition_get_partno(blkid_partition par)
1406{
7f787ced 1407 return par->partno;
e4799a35
KZ
1408}
1409
1410/**
1411 * blkid_partition_get_start:
1412 * @par: partition
1413 *
1414 * Be careful if you _not_ probe whole disk:
1415 *
9e930041 1416 * 1) the offset is usually relative to begin of the disk -- but if you probe a
e4799a35
KZ
1417 * fragment of the disk only -- then the offset could be still relative to
1418 * the begin of the disk rather that relative to the fragment.
1419 *
9e930041 1420 * 2) the offset for nested partitions could be relative to parent (e.g. Solaris)
e4799a35
KZ
1421 * _or_ relative to the begin of the whole disk (e.g. bsd).
1422 *
9e930041 1423 * You don't have to care about such details if you probe whole disk. In such
e4799a35
KZ
1424 * a case libblkid always returns the offset relative to the begin of the disk.
1425 *
1426 * Returns: start of the partition (in 512-sectors).
1427 */
1428blkid_loff_t blkid_partition_get_start(blkid_partition par)
1429{
7f787ced 1430 return (blkid_loff_t)par->start;
e4799a35
KZ
1431}
1432
1433/**
1434 * blkid_partition_get_size:
1435 * @par: partition
1436 *
1437 * WARNING: be very careful when you work with MS-DOS extended partitions. The
1438 * library always returns full size of the partition. If you want add
1439 * the partition to the Linux system (BLKPG_ADD_PARTITION ioctl) you
1440 * need to reduce the size of the partition to 1 or 2 blocks. The
9e930041 1441 * rest of the partition has to be inaccessible for mkfs or mkswap
e4799a35
KZ
1442 * programs, we need a small space for boot loaders only.
1443 *
1444 * For some unknown reason this (safe) practice is not to used for
1445 * nested BSD, Solaris, ..., partition tables in Linux kernel.
1446 *
1447 * Returns: size of the partition (in 512-sectors).
1448 */
1449blkid_loff_t blkid_partition_get_size(blkid_partition par)
1450{
7f787ced 1451 return (blkid_loff_t)par->size;
e4799a35
KZ
1452}
1453
1454/**
1455 * blkid_partition_get_type:
1456 * @par: partition
1457 *
0e8a8065 1458 * Returns: partition type.
e4799a35
KZ
1459 */
1460int blkid_partition_get_type(blkid_partition par)
1461{
e3436956 1462 return par->type;
e4799a35 1463}
0e8a8065
KZ
1464
1465/* Sets partition 'type' for PT where the type is defined by string rather
1466 * than by number
1467 */
1468int blkid_partition_set_type_string(blkid_partition par,
1469 const unsigned char *type, size_t len)
1470{
0e8a8065
KZ
1471 set_string((unsigned char *) par->typestr,
1472 sizeof(par->typestr), type, len);
1473 return 0;
1474}
1475
1476/* Sets partition 'type' for PT where the type is defined by UUIDrather
1477 * than by number
1478 */
1479int blkid_partition_set_type_uuid(blkid_partition par, const unsigned char *uuid)
1480{
0e8a8065
KZ
1481 blkid_unparse_uuid(uuid, par->typestr, sizeof(par->typestr));
1482 return 0;
1483}
1484
1485/**
1486 * blkid_partition_get_type_string:
1487 * @par: partition
1488 *
1489 * The type string is supported by a small subset of partition tables (e.g Mac
1490 * and EFI GPT). Note that GPT uses type UUID and this function returns this
1491 * UUID as string.
1492 *
1493 * Returns: partition type string or NULL.
1494 */
1495const char *blkid_partition_get_type_string(blkid_partition par)
1496{
7f787ced 1497 return *par->typestr ? par->typestr : NULL;
0e8a8065
KZ
1498}
1499
75838802
KZ
1500
1501int blkid_partition_set_flags(blkid_partition par, unsigned long long flags)
1502{
75838802
KZ
1503 par->flags = flags;
1504 return 0;
1505}
1506
1507/**
1508 * blkid_partition_get_flags
1509 * @par: partition
1510 *
1511 * Returns: partition flags (or attributes for gpt).
1512 */
1513unsigned long long blkid_partition_get_flags(blkid_partition par)
1514{
e3436956 1515 return par->flags;
75838802
KZ
1516}
1517