2 * partitions - partition tables parsing
4 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
16 #include <sys/types.h>
23 #include "partitions.h"
28 * @title: Partitions probing
29 * @short_description: partitions tables detection and parsing
31 * This chain supports binary and NAME=value interfaces, but complete PT
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.
36 * NAME=value interface, supported tags:
38 * @PTTYPE: partition table type (dos, gpt, etc.).
40 * @PTUUID: partition table id (uuid for gpt, hex for dos).
42 * @PART_ENTRY_SCHEME: partition table type
44 * @PART_ENTRY_NAME: partition name (gpt and mac only)
46 * @PART_ENTRY_UUID: partition UUID (gpt, or pseudo IDs for MBR)
48 * @PART_ENTRY_TYPE: partition type, 0xNN (e.g 0x82) or type UUID (gpt only) or type string (mac)
50 * @PART_ENTRY_FLAGS: partition flags (e.g. boot_ind) or attributes (e.g. gpt attributes)
52 * @PART_ENTRY_NUMBER: partition number
54 * @PART_ENTRY_OFFSET: the begin of the partition
56 * @PART_ENTRY_SIZE: size of the partition
58 * @PART_ENTRY_DISK: whole-disk maj:min
67 * pr = blkid_new_probe_from_filename(devname);
69 * err("%s: faild to open device", devname);
71 * blkid_probe_enable_partitions(pr, TRUE);
72 * blkid_do_fullprobe(pr);
74 * blkid_probe_lookup_value(pr, "PTTYPE", &ptname, NULL);
75 * printf("%s partition type detected\n", pttype);
77 * blkid_free_probe(pr);
79 * // don't forget to check return codes in your code!
91 * pr = blkid_new_probe_from_filename(devname);
93 * err("%s: faild to open device", devname);
95 * ls = blkid_probe_get_partitions(pr);
96 * nparts = blkid_partlist_numof_partitions(ls);
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));
107 * blkid_free_probe(pr);
109 * // don't forget to check return codes in your code!
115 * Chain driver function
117 static int partitions_probe(blkid_probe pr
, struct blkid_chain
*chn
);
118 static void partitions_free_data(blkid_probe pr
, void *data
);
121 * Partitions chain probing functions
123 static const struct blkid_idinfo
*idinfos
[] =
130 &pmbr_pt_idinfo
, /* always after GPT */
135 &solaris_x86_pt_idinfo
,
142 const struct blkid_chaindrv partitions_drv
= {
143 .id
= BLKID_CHAIN_PARTS
,
144 .name
= "partitions",
145 .dflt_enabled
= FALSE
,
147 .nidinfos
= ARRAY_SIZE(idinfos
),
149 .probe
= partitions_probe
,
150 .safeprobe
= partitions_probe
,
151 .free_data
= partitions_free_data
156 * For compatibility with the rest of libblkid API (with the old high-level
157 * API) we use completely opaque typedefs for all structs. Don't forget that
158 * the final blkid_* types are pointers! See blkid.h.
160 * [Just for the record, I hate typedef for pointers --kzak]
163 /* exported as opaque type "blkid_parttable" */
164 struct blkid_struct_parttable
{
165 const char *type
; /* partition table type */
166 uint64_t offset
; /* begin of the partition table (in bytes) */
167 int nparts
; /* number of partitions */
168 blkid_partition parent
; /* parent of nested partition table */
169 char id
[37]; /* PT identifier (e.g. UUID for GPT) */
171 struct list_head t_tabs
; /* all tables */
174 /* exported as opaque type "blkid_partition" */
175 struct blkid_struct_partition
{
176 uint64_t start
; /* begin of the partition (512-bytes sectors) */
177 uint64_t size
; /* size of the partitions (512-bytes sectors) */
179 int type
; /* partition type */
180 char typestr
[37]; /* partition type string (GPT and Mac) */
182 unsigned long long flags
; /* partition flags / attributes */
184 int partno
; /* partition number */
185 char uuid
[37]; /* UUID (when supported by PT), e.g GPT */
186 unsigned char name
[128]; /* Partition in UTF8 name (when supporte by PT), e.g. Mac */
188 blkid_parttable tab
; /* partition table */
191 /* exported as opaque type "blkid_partlist" */
192 struct blkid_struct_partlist
{
193 int next_partno
; /* next partition number */
194 blkid_partition next_parent
; /* next parent if parsing nested PT */
196 int nparts
; /* number of partitions */
197 int nparts_max
; /* max.number of partitions */
198 blkid_partition parts
; /* array of partitions */
200 struct list_head l_tabs
; /* list of partition tables */
203 static int blkid_partitions_probe_partition(blkid_probe pr
);
206 * blkid_probe_enable_partitions:
208 * @enable: TRUE/FALSE
210 * Enables/disables the partitions probing for non-binary interface.
212 * Returns: 0 on success, or -1 in case of error.
214 int blkid_probe_enable_partitions(blkid_probe pr
, int enable
)
218 pr
->chains
[BLKID_CHAIN_PARTS
].enabled
= enable
;
223 * blkid_probe_set_partitions_flags:
225 * @flags: BLKID_PARTS_* flags
227 * Sets probing flags to the partitions prober. This function is optional.
229 * Returns: 0 on success, or -1 in case of error.
231 int blkid_probe_set_partitions_flags(blkid_probe pr
, int flags
)
235 pr
->chains
[BLKID_CHAIN_PARTS
].flags
= flags
;
240 * blkid_probe_reset_partitions_filter:
243 * Resets partitions probing filter
245 * Returns: 0 on success, or -1 in case of error.
247 int blkid_probe_reset_partitions_filter(blkid_probe pr
)
249 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_PARTS
);
253 * blkid_probe_invert_partitions_filter:
256 * Inverts partitions probing filter
258 * Returns: 0 on success, or -1 in case of error.
260 int blkid_probe_invert_partitions_filter(blkid_probe pr
)
262 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_PARTS
);
266 * blkid_probe_filter_partitions_type:
268 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
269 * @names: NULL terminated array of probing function names (e.g. "vfat").
271 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names
273 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
275 * Returns: 0 on success, or -1 in case of error.
277 int blkid_probe_filter_partitions_type(blkid_probe pr
, int flag
, char *names
[])
279 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_PARTS
, flag
, names
);
283 * blkid_probe_get_partitions:
286 * This is a binary interface for partitions. See also blkid_partlist_*
289 * This function is independent on blkid_do_[safe,full]probe() and
290 * blkid_probe_enable_partitions() calls.
292 * WARNING: the returned object will be overwritten by the next
293 * blkid_probe_get_partitions() call for the same @pr. If you want to
294 * use more blkid_partlist objects in the same time you have to create
295 * more blkid_probe handlers (see blkid_new_probe()).
297 * Returns: list of partitions, or NULL in case of error.
299 blkid_partlist
blkid_probe_get_partitions(blkid_probe pr
)
301 return (blkid_partlist
) blkid_probe_get_binary_data(pr
,
302 &pr
->chains
[BLKID_CHAIN_PARTS
]);
305 /* for internal usage only */
306 blkid_partlist
blkid_probe_get_partlist(blkid_probe pr
)
308 return (blkid_partlist
) pr
->chains
[BLKID_CHAIN_PARTS
].data
;
311 static void blkid_probe_set_partlist(blkid_probe pr
, blkid_partlist ls
)
313 pr
->chains
[BLKID_CHAIN_PARTS
].data
= ls
;
316 static void ref_parttable(blkid_parttable tab
)
321 static void unref_parttable(blkid_parttable tab
)
325 if (tab
->nparts
<= 0) {
326 list_del(&tab
->t_tabs
);
331 /* free all allocated parttables */
332 static void free_parttables(blkid_partlist ls
)
334 if (!ls
|| !ls
->l_tabs
.next
)
337 /* remove unassigned partition tables */
338 while (!list_empty(&ls
->l_tabs
)) {
339 blkid_parttable tab
= list_entry(ls
->l_tabs
.next
,
340 struct blkid_struct_parttable
, t_tabs
);
341 unref_parttable(tab
);
345 static void reset_partlist(blkid_partlist ls
)
352 if (ls
->next_partno
) {
353 /* already initialized - reset */
354 int tmp_nparts
= ls
->nparts_max
;
355 blkid_partition tmp_parts
= ls
->parts
;
357 memset(ls
, 0, sizeof(struct blkid_struct_partlist
));
359 ls
->nparts_max
= tmp_nparts
;
360 ls
->parts
= tmp_parts
;
365 INIT_LIST_HEAD(&ls
->l_tabs
);
367 DBG(LOWPROBE
, ul_debug("partlist reset"));
370 static blkid_partlist
partitions_init_data(struct blkid_chain
*chn
)
375 ls
= (blkid_partlist
) chn
->data
;
377 /* allocate the new list of partitions */
378 ls
= calloc(1, sizeof(struct blkid_struct_partlist
));
381 chn
->data
= (void *) ls
;
386 DBG(LOWPROBE
, ul_debug("parts: initialized partitions list (%p, size=%d)",
387 ls
, ls
->nparts_max
));
391 static void partitions_free_data(blkid_probe pr
__attribute__((__unused__
)),
394 blkid_partlist ls
= (blkid_partlist
) data
;
401 /* deallocate partitions and partlist */
406 blkid_parttable
blkid_partlist_new_parttable(blkid_partlist ls
,
407 const char *type
, uint64_t offset
)
411 tab
= calloc(1, sizeof(struct blkid_struct_parttable
));
415 tab
->offset
= offset
;
416 tab
->parent
= ls
->next_parent
;
418 INIT_LIST_HEAD(&tab
->t_tabs
);
419 list_add_tail(&tab
->t_tabs
, &ls
->l_tabs
);
421 DBG(LOWPROBE
, ul_debug("parts: create a new partition table "
422 "(%p, type=%s, offset=%"PRId64
")", tab
, type
, offset
));
426 static blkid_partition
new_partition(blkid_partlist ls
, blkid_parttable tab
)
430 if (ls
->nparts
+ 1 > ls
->nparts_max
) {
431 /* Linux kernel has DISK_MAX_PARTS=256, but it's too much for
432 * generic Linux machine -- let start with 32 partititions.
434 void *tmp
= realloc(ls
->parts
, (ls
->nparts_max
+ 32) *
435 sizeof(struct blkid_struct_partition
));
439 ls
->nparts_max
+= 32;
442 par
= &ls
->parts
[ls
->nparts
++];
443 memset(par
, 0, sizeof(struct blkid_struct_partition
));
447 par
->partno
= blkid_partlist_increment_partno(ls
);
452 blkid_partition
blkid_partlist_add_partition(blkid_partlist ls
,
453 blkid_parttable tab
, uint64_t start
, uint64_t size
)
455 blkid_partition par
= new_partition(ls
, tab
);
463 DBG(LOWPROBE
, ul_debug("parts: add partition (%p start=%"
464 PRIu64
", size=%" PRIu64
", table=%p)",
465 par
, par
->start
, par
->size
, tab
));
469 /* allows to modify used partitions numbers (for example for logical partitions) */
470 int blkid_partlist_set_partno(blkid_partlist ls
, int partno
)
474 ls
->next_partno
= partno
;
478 int blkid_partlist_increment_partno(blkid_partlist ls
)
480 return ls
? ls
->next_partno
++ : -1;
483 /* allows to set "parent" for the next nested partition */
484 int blkid_partlist_set_parent(blkid_partlist ls
, blkid_partition par
)
488 ls
->next_parent
= par
;
492 blkid_partition
blkid_partlist_get_parent(blkid_partlist ls
)
496 return ls
->next_parent
;
499 int blkid_partitions_need_typeonly(blkid_probe pr
)
501 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
503 return chn
&& chn
->data
&& chn
->binary
? FALSE
: TRUE
;
506 /* get private chain flags */
507 int blkid_partitions_get_flags(blkid_probe pr
)
509 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
511 return chn
? chn
->flags
: 0;
514 /* check if @start and @size are within @par partition */
515 int blkid_is_nested_dimension(blkid_partition par
,
516 uint64_t start
, uint64_t size
)
524 pstart
= blkid_partition_get_start(par
);
525 psize
= blkid_partition_get_size(par
);
527 if (start
< pstart
|| start
+ size
> pstart
+ psize
)
533 static int idinfo_probe(blkid_probe pr
, const struct blkid_idinfo
*id
,
534 struct blkid_chain
*chn
)
536 const struct blkid_idmag
*mag
= NULL
;
538 int rc
= BLKID_PROBE_NONE
; /* default is nothing */
540 if (pr
->size
<= 0 || (id
->minsz
&& id
->minsz
> pr
->size
))
541 goto nothing
; /* the device is too small */
542 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
545 rc
= blkid_probe_get_idmag(pr
, id
, &off
, &mag
);
546 if (rc
!= BLKID_PROBE_OK
)
549 /* final check by probing function */
551 DBG(LOWPROBE
, ul_debug(
552 "%s: ---> call probefunc()", id
->name
));
553 rc
= id
->probefunc(pr
, mag
);
555 /* reset after error */
556 reset_partlist(blkid_probe_get_partlist(pr
));
557 if (chn
&& !chn
->binary
)
558 blkid_probe_chain_reset_values(pr
, chn
);
559 DBG(LOWPROBE
, ul_debug("%s probefunc failed, rc %d",
562 if (rc
== BLKID_PROBE_OK
&& mag
&& chn
&& !chn
->binary
)
563 rc
= blkid_probe_set_magic(pr
, off
, mag
->len
,
564 (unsigned char *) mag
->magic
);
566 DBG(LOWPROBE
, ul_debug("%s: <--- (rc = %d)", id
->name
, rc
));
572 return BLKID_PROBE_NONE
;
576 * The blkid_do_probe() backend.
578 static int partitions_probe(blkid_probe pr
, struct blkid_chain
*chn
)
580 int rc
= BLKID_PROBE_NONE
;
583 if (!pr
|| chn
->idx
< -1)
586 blkid_probe_chain_reset_values(pr
, chn
);
588 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
589 return BLKID_PROBE_NONE
;
592 partitions_init_data(chn
);
594 if (!pr
->wipe_size
&& (pr
->prob_flags
& BLKID_PROBE_FL_IGNORE_PT
))
597 DBG(LOWPROBE
, ul_debug("--> starting probing loop [PARTS idx=%d]",
600 i
= chn
->idx
< 0 ? 0 : chn
->idx
+ 1U;
602 for ( ; i
< ARRAY_SIZE(idinfos
); i
++) {
608 if (chn
->fltr
&& blkid_bmp_get_item(chn
->fltr
, i
))
611 /* apply checks from idinfo */
612 rc
= idinfo_probe(pr
, idinfos
[i
], chn
);
615 if (rc
!= BLKID_PROBE_OK
)
618 name
= idinfos
[i
]->name
;
622 * Non-binary interface, set generic variables. Note
623 * that the another variables could be set in prober
626 blkid_probe_set_value(pr
, "PTTYPE",
627 (unsigned char *) name
,
630 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (type=%s) [PARTS idx=%d]",
636 if (rc
!= BLKID_PROBE_OK
) {
637 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (failed=%d) [PARTS idx=%d]",
643 * Gather PART_ENTRY_* values if the current device is a partition.
645 if ((rc
== BLKID_PROBE_OK
|| rc
== BLKID_PROBE_NONE
) && !chn
->binary
&&
646 (blkid_partitions_get_flags(pr
) & BLKID_PARTS_ENTRY_DETAILS
)) {
648 int xrc
= blkid_partitions_probe_partition(pr
);
650 /* partition entry probing is optional, and "not-found" from
651 * this sub-probing must not to overwrite previous success. */
653 rc
= xrc
; /* always propagate errors */
654 else if (rc
== BLKID_PROBE_NONE
)
658 DBG(LOWPROBE
, ul_debug("partitions probe done [rc=%d]", rc
));
662 /* Probe for nested partition table within the parental partition */
663 int blkid_partitions_do_subprobe(blkid_probe pr
, blkid_partition parent
,
664 const struct blkid_idinfo
*id
)
671 DBG(LOWPROBE
, ul_debug(
672 "parts: ----> %s subprobe requested (parent=%p)",
675 if (!pr
|| !parent
|| !parent
->size
)
677 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
678 return BLKID_PROBE_NONE
;
680 /* range defined by parent */
681 sz
= parent
->size
<< 9;
682 off
= parent
->start
<< 9;
684 if (off
< pr
->off
|| pr
->off
+ pr
->size
< off
+ sz
) {
685 DBG(LOWPROBE
, ul_debug(
686 "ERROR: parts: <---- '%s' subprobe: overflow detected.",
691 /* create private prober */
692 prc
= blkid_clone_probe(pr
);
696 blkid_probe_set_dimension(prc
, off
, sz
);
698 /* clone is always with reset chain, fix it */
699 prc
->cur_chain
= blkid_probe_get_chain(pr
);
702 * Set 'parent' to the current list of the partitions and use the list
703 * in cloned prober (so the cloned prober will extend the current list
704 * of partitions rather than create a new).
706 ls
= blkid_probe_get_partlist(pr
);
707 blkid_partlist_set_parent(ls
, parent
);
709 blkid_probe_set_partlist(prc
, ls
);
711 rc
= idinfo_probe(prc
, id
, blkid_probe_get_chain(pr
));
713 blkid_probe_set_partlist(prc
, NULL
);
714 blkid_partlist_set_parent(ls
, NULL
);
716 blkid_free_probe(prc
); /* free cloned prober */
718 DBG(LOWPROBE
, ul_debug(
719 "parts: <---- %s subprobe done (parent=%p, rc=%d)",
720 id
->name
, parent
, rc
));
725 static int blkid_partitions_probe_partition(blkid_probe pr
)
727 blkid_probe disk_pr
= NULL
;
732 DBG(LOWPROBE
, ul_debug("parts: start probing for partition entry"));
734 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
737 devno
= blkid_probe_get_devno(pr
);
741 disk_pr
= blkid_probe_get_wholedisk_probe(pr
);
746 ls
= blkid_probe_get_partitions(disk_pr
);
750 par
= blkid_partlist_devno_to_partition(ls
, devno
);
755 blkid_parttable tab
= blkid_partition_get_table(par
);
756 dev_t disk
= blkid_probe_get_devno(disk_pr
);
759 v
= blkid_parttable_get_type(tab
);
761 blkid_probe_set_value(pr
, "PART_ENTRY_SCHEME",
762 (unsigned char *) v
, strlen(v
) + 1);
765 v
= blkid_partition_get_name(par
);
767 blkid_probe_set_value(pr
, "PART_ENTRY_NAME",
768 (unsigned char *) v
, strlen(v
) + 1);
770 v
= blkid_partition_get_uuid(par
);
772 blkid_probe_set_value(pr
, "PART_ENTRY_UUID",
773 (unsigned char *) v
, strlen(v
) + 1);
776 v
= blkid_partition_get_type_string(par
);
778 blkid_probe_set_value(pr
, "PART_ENTRY_TYPE",
779 (unsigned char *) v
, strlen(v
) + 1);
781 blkid_probe_sprintf_value(pr
, "PART_ENTRY_TYPE",
782 "0x%x", blkid_partition_get_type(par
));
784 if (blkid_partition_get_flags(par
))
785 blkid_probe_sprintf_value(pr
, "PART_ENTRY_FLAGS",
786 "0x%llx", blkid_partition_get_flags(par
));
788 blkid_probe_sprintf_value(pr
, "PART_ENTRY_NUMBER",
789 "%d", blkid_partition_get_partno(par
));
791 blkid_probe_sprintf_value(pr
, "PART_ENTRY_OFFSET", "%jd",
792 blkid_partition_get_start(par
));
793 blkid_probe_sprintf_value(pr
, "PART_ENTRY_SIZE", "%jd",
794 blkid_partition_get_size(par
));
796 blkid_probe_sprintf_value(pr
, "PART_ENTRY_DISK", "%u:%u",
797 major(disk
), minor(disk
));
800 DBG(LOWPROBE
, ul_debug("parts: end probing for partition entry [success]"));
801 return BLKID_PROBE_OK
;
804 DBG(LOWPROBE
, ul_debug("parts: end probing for partition entry [nothing]"));
805 return BLKID_PROBE_NONE
;
811 * Returns 1 if the device is whole-disk and the area specified by @offset and
812 * @size is covered by any partition.
814 int blkid_probe_is_covered_by_pt(blkid_probe pr
,
815 uint64_t offset
, uint64_t size
)
817 blkid_probe prc
= NULL
;
818 blkid_partlist ls
= NULL
;
820 int nparts
, i
, rc
= 0;
822 DBG(LOWPROBE
, ul_debug(
823 "=> checking if off=%jd size=%jd covered by PT",
826 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
829 prc
= blkid_clone_probe(pr
);
833 ls
= blkid_probe_get_partitions(prc
);
837 nparts
= blkid_partlist_numof_partitions(ls
);
841 end
= (offset
+ size
) >> 9;
844 /* check if the partition table fits into the device */
845 for (i
= 0; i
< nparts
; i
++) {
846 blkid_partition par
= &ls
->parts
[i
];
848 if (par
->start
+ par
->size
> (pr
->size
>> 9)) {
849 DBG(LOWPROBE
, ul_debug("partition #%d overflows "
850 "device (off=%" PRId64
" size=%" PRId64
")",
851 par
->partno
, par
->start
, par
->size
));
856 /* check if the requested area is covered by PT */
857 for (i
= 0; i
< nparts
; i
++) {
858 blkid_partition par
= &ls
->parts
[i
];
860 if (start
>= par
->start
&& end
<= par
->start
+ par
->size
) {
866 blkid_free_probe(prc
);
868 DBG(LOWPROBE
, ul_debug("<= %s covered by PT", rc
? "IS" : "NOT"));
873 * blkid_known_pttype:
874 * @pttype: partiton name
876 * Returns: 1 for known or 0 for unknown partition type.
878 int blkid_known_pttype(const char *pttype
)
885 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
886 const struct blkid_idinfo
*id
= idinfos
[i
];
887 if (strcmp(id
->name
, pttype
) == 0)
894 * blkid_partlist_numof_partitions:
895 * @ls: partitions list
897 * Returns: number of partitions in the list or -1 in case of error.
899 int blkid_partlist_numof_partitions(blkid_partlist ls
)
901 return ls
? ls
->nparts
: -1;
905 * blkid_partlist_get_table:
906 * @ls: partitions list
908 * Returns: top-level partition table or NULL of there is not a partition table
911 blkid_parttable
blkid_partlist_get_table(blkid_partlist ls
)
913 if (!ls
|| list_empty(&ls
->l_tabs
))
916 return list_entry(ls
->l_tabs
.next
,
917 struct blkid_struct_parttable
, t_tabs
);
922 * blkid_partlist_get_partition:
923 * @ls: partitions list
924 * @n: partition number in range 0..N, where 'N' is blkid_partlist_numof_partitions().
926 * It's possible that the list of partitions is *empty*, but there is a valid
927 * partition table on the disk. This happen when on-disk details about
928 * partitions are unknown or the partition table is empty.
930 * See also blkid_partlist_get_table().
932 * Returns: partition object or NULL in case or error.
934 blkid_partition
blkid_partlist_get_partition(blkid_partlist ls
, int n
)
936 if (!ls
|| n
< 0 || n
>= ls
->nparts
)
939 return &ls
->parts
[n
];
943 * blkid_partlist_get_partition_by_partno
944 * @ls: partitions list
945 * @n: the partition number (e.g. 'N' from sda'N')
947 * This does not assume any order of the input blkid_partlist. And correctly
948 * handles "out of order" partition tables. partition N is located after
949 * partition N+1 on the disk.
951 * Returns: partition object or NULL in case or error.
953 blkid_partition
blkid_partlist_get_partition_by_partno(blkid_partlist ls
, int n
)
961 nparts
= blkid_partlist_numof_partitions(ls
);
962 for (i
= 0; i
< nparts
; i
++) {
963 par
= blkid_partlist_get_partition(ls
, i
);
964 if (n
== blkid_partition_get_partno(par
))
972 * blkid_partlist_devno_to_partition:
973 * @ls: partitions list
974 * @devno: requested partition
976 * This function tries to get start and size for @devno from sysfs and
977 * returns a partition from @ls which matches with the values from sysfs.
979 * This function is necessary when you want to make a relation between an entry
980 * in the partition table (@ls) and block devices in your system.
982 * Returns: partition object or NULL in case or error.
984 blkid_partition
blkid_partlist_devno_to_partition(blkid_partlist ls
, dev_t devno
)
986 struct sysfs_cxt sysfs
;
987 uint64_t start
, size
;
988 int i
, rc
, partno
= 0;
993 DBG(LOWPROBE
, ul_debug("triyng to convert devno 0x%llx to partition",
996 if (sysfs_init(&sysfs
, devno
, NULL
)) {
997 DBG(LOWPROBE
, ul_debug("failed t init sysfs context"));
1000 rc
= sysfs_read_u64(&sysfs
, "size", &size
);
1002 rc
= sysfs_read_u64(&sysfs
, "start", &start
);
1004 /* try to get partition number from DM uuid.
1006 char *uuid
= sysfs_strdup(&sysfs
, "dm/uuid");
1008 char *prefix
= uuid
? strsep(&tmp
, "-") : NULL
;
1010 if (prefix
&& strncasecmp(prefix
, "part", 4) == 0) {
1013 partno
= strtol(prefix
+ 4, &end
, 10);
1014 if (prefix
== end
|| (end
&& *end
))
1017 rc
= 0; /* success */
1023 sysfs_deinit(&sysfs
);
1029 DBG(LOWPROBE
, ul_debug("mapped by DM, using partno %d", partno
));
1032 * Partition mapped by kpartx does not provide "start" offset
1033 * in /sys, but if we know partno and size of the partition
1034 * that we can probably make the releation bettween the device
1035 * and an entry in partition table.
1037 for (i
= 0; i
< ls
->nparts
; i
++) {
1038 blkid_partition par
= &ls
->parts
[i
];
1040 if (partno
!= blkid_partition_get_partno(par
))
1043 if (size
== blkid_partition_get_size(par
) ||
1044 (blkid_partition_is_extended(par
) && size
<= 1024ULL))
1051 DBG(LOWPROBE
, ul_debug("searching by offset/size"));
1053 for (i
= 0; i
< ls
->nparts
; i
++) {
1054 blkid_partition par
= &ls
->parts
[i
];
1056 if (blkid_partition_get_start(par
) == start
&&
1057 blkid_partition_get_size(par
) == size
)
1060 /* exception for extended dos partitions */
1061 if (blkid_partition_get_start(par
) == start
&&
1062 blkid_partition_is_extended(par
) && size
<= 1024ULL)
1067 DBG(LOWPROBE
, ul_debug("not found partition for device"));
1072 int blkid_parttable_set_uuid(blkid_parttable tab
, const unsigned char *id
)
1077 blkid_unparse_uuid(id
, tab
->id
, sizeof(tab
->id
));
1081 int blkid_parttable_set_id(blkid_parttable tab
, const unsigned char *id
)
1086 strncpy(tab
->id
, (const char *) id
, sizeof(tab
->id
));
1090 /* set PTUUID variable for non-binary API */
1091 int blkid_partitions_set_ptuuid(blkid_probe pr
, unsigned char *uuid
)
1093 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
1094 struct blkid_prval
*v
;
1096 if (chn
->binary
|| blkid_uuid_is_empty(uuid
, 16))
1099 v
= blkid_probe_assign_value(pr
, "PTUUID");
1104 v
->data
= calloc(1, v
->len
);
1106 blkid_unparse_uuid(uuid
, (char *) v
->data
, v
->len
);
1110 blkid_probe_free_value(v
);
1114 /* set PTUUID variable for non-binary API for tables where
1115 * the ID is just a string */
1116 int blkid_partitions_strcpy_ptuuid(blkid_probe pr
, char *str
)
1118 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
1120 if (chn
->binary
|| !str
|| !*str
)
1123 if (!blkid_probe_set_value(pr
, "PTUUID", (unsigned char *) str
, strlen(str
) + 1))
1130 * blkid_parttable_get_id:
1131 * @tab: partition table
1133 * The ID is GPT disk UUID or DOS disk ID (in hex format).
1135 * Returns: partition table ID (for example GPT disk UUID) or NULL
1137 const char *blkid_parttable_get_id(blkid_parttable tab
)
1139 return tab
&& *tab
->id
? tab
->id
: NULL
;
1143 int blkid_partition_set_type(blkid_partition par
, int type
)
1152 * blkid_parttable_get_type:
1153 * @tab: partition table
1155 * Returns: partition table type (type name, e.g. "dos", "gpt", ...)
1157 const char *blkid_parttable_get_type(blkid_parttable tab
)
1159 return tab
? tab
->type
: NULL
;
1163 * blkid_parttable_get_parent:
1164 * @tab: partition table
1166 * Returns: parent for nexted partitition tables or NULL.
1168 blkid_partition
blkid_parttable_get_parent(blkid_parttable tab
)
1170 return tab
? tab
->parent
: NULL
;
1174 * blkid_parttable_get_offset:
1175 * @tab: partition table
1177 * Note the position is relative to begin of the device as defined by
1178 * blkid_probe_set_device() for primary partition table, and relative
1179 * to parental partition for nested patition tables.
1184 * blkid_partition parent = blkid_parttable_get_parent(tab);
1186 * offset = blkid_parttable_get_offset(tab);
1189 * / * 'tab' is nested partition table * /
1190 * offset += blkid_partition_get_start(parent);
1192 * </informalexample>
1194 * Returns: position (in bytes) of the partition table or -1 in case of error.
1197 blkid_loff_t
blkid_parttable_get_offset(blkid_parttable tab
)
1199 return tab
? tab
->offset
: -1;
1203 * blkid_partition_get_table:
1206 * The "parttable" describes partition table. The table is usually the same for
1207 * all partitions -- except nested partition tables.
1209 * For example bsd, solaris, etc. use a nested partition table within
1210 * standard primary dos partition:
1215 * -- dos partition table
1216 * 0: sda1 dos primary partition
1217 * 1: sda2 dos primary partition
1218 * -- bsd partition table (with in sda2)
1219 * 2: sda5 bds partition
1220 * 3: sda6 bds partition
1223 * </informalexample>
1225 * The library does not to use a separate partition table object for dos logical
1226 * partitions (partitions within extended partition). It's possible to
1227 * differentiate between logical, extended and primary partitions by
1229 * blkid_partition_is_{extended,primary,logical}().
1231 * Returns: partition table object or NULL in case of error.
1233 blkid_parttable
blkid_partition_get_table(blkid_partition par
)
1235 return par
? par
->tab
: NULL
;
1238 static int partition_get_logical_type(blkid_partition par
)
1240 blkid_parttable tab
;
1245 tab
= blkid_partition_get_table(par
);
1246 if (!tab
|| !tab
->type
)
1250 return 'L'; /* report nested partitions as logical */
1252 if (!strcmp(tab
->type
, "dos")) {
1253 if (par
->partno
> 4)
1254 return 'L'; /* logical */
1256 if(par
->type
== MBR_DOS_EXTENDED_PARTITION
||
1257 par
->type
== MBR_W95_EXTENDED_PARTITION
||
1258 par
->type
== MBR_LINUX_EXTENDED_PARTITION
)
1265 * blkid_partition_is_primary:
1268 * Note, this function returns FALSE for DOS extended partitions and
1269 * all partitions in nested partition tables.
1271 * Returns: 1 if the partitions is primary partition or 0 if not.
1273 int blkid_partition_is_primary(blkid_partition par
)
1275 return partition_get_logical_type(par
) == 'P' ? TRUE
: FALSE
;
1279 * blkid_partition_is_extended:
1282 * Returns: 1 if the partitions is extended (dos, windows or linux)
1283 * partition or 0 if not.
1285 int blkid_partition_is_extended(blkid_partition par
)
1287 return partition_get_logical_type(par
) == 'E' ? TRUE
: FALSE
;
1291 * blkid_partition_is_logical:
1294 * Note that this function returns TRUE for all partitions in all
1295 * nested partition tables (e.g. BSD labels).
1297 * Returns: 1 if the partitions is logical partition or 0 if not.
1299 int blkid_partition_is_logical(blkid_partition par
)
1301 return partition_get_logical_type(par
) == 'L' ? TRUE
: FALSE
;
1304 static void set_string(unsigned char *item
, size_t max
,
1305 const unsigned char *data
, size_t len
)
1310 memcpy(item
, data
, len
);
1313 blkid_rtrim_whitespace(item
);
1316 int blkid_partition_set_name(blkid_partition par
,
1317 const unsigned char *name
, size_t len
)
1322 set_string(par
->name
, sizeof(par
->name
), name
, len
);
1326 int blkid_partition_set_utf8name(blkid_partition par
, const unsigned char *name
,
1327 size_t len
, int enc
)
1332 blkid_encode_to_utf8(enc
, par
->name
, sizeof(par
->name
), name
, len
);
1333 blkid_rtrim_whitespace(par
->name
);
1337 int blkid_partition_set_uuid(blkid_partition par
, const unsigned char *uuid
)
1342 blkid_unparse_uuid(uuid
, par
->uuid
, sizeof(par
->uuid
));
1346 int blkid_partition_gen_uuid(blkid_partition par
)
1348 if (!par
|| !par
->tab
|| !*par
->tab
->id
)
1351 snprintf(par
->uuid
, sizeof(par
->uuid
), "%s-%02x",
1352 par
->tab
->id
, par
->partno
);
1357 * blkid_partition_get_name:
1360 * Returns: partition name string if supported by PT (e.g. Mac) or NULL.
1362 const char *blkid_partition_get_name(blkid_partition par
)
1364 return par
&& *par
->name
? (char *) par
->name
: NULL
;
1368 * blkid_partition_get_uuid:
1371 * Returns: partition UUID string if supported by PT (e.g. GPT) or NULL.
1373 const char *blkid_partition_get_uuid(blkid_partition par
)
1375 return par
&& *par
->uuid
? par
->uuid
: NULL
;
1379 * blkid_partition_get_partno:
1382 * Returns: proposed partitin number (e.g. 'N' from sda'N') or -1 in case of
1383 * error. Note that the number is generate by library independenly on your OS.
1385 int blkid_partition_get_partno(blkid_partition par
)
1387 return par
? par
->partno
: -1;
1391 * blkid_partition_get_start:
1394 * Be careful if you _not_ probe whole disk:
1396 * 1) the offset is usully relative to begin of the disk -- but if you probe a
1397 * fragment of the disk only -- then the offset could be still relative to
1398 * the begin of the disk rather that relative to the fragment.
1400 * 2) the offset for nested partitions could be releative to parent (e.g. Solaris)
1401 * _or_ relative to the begin of the whole disk (e.g. bsd).
1403 * You don't have to care about such details if you proble whole disk. In such
1404 * a case libblkid always returns the offset relative to the begin of the disk.
1406 * Returns: start of the partition (in 512-sectors).
1408 blkid_loff_t
blkid_partition_get_start(blkid_partition par
)
1410 return par
? par
->start
: -1;
1414 * blkid_partition_get_size:
1417 * WARNING: be very careful when you work with MS-DOS extended partitions. The
1418 * library always returns full size of the partition. If you want add
1419 * the partition to the Linux system (BLKPG_ADD_PARTITION ioctl) you
1420 * need to reduce the size of the partition to 1 or 2 blocks. The
1421 * rest of the partition has to be unaccessible for mkfs or mkswap
1422 * programs, we need a small space for boot loaders only.
1424 * For some unknown reason this (safe) practice is not to used for
1425 * nested BSD, Solaris, ..., partition tables in Linux kernel.
1427 * Returns: size of the partition (in 512-sectors).
1429 blkid_loff_t
blkid_partition_get_size(blkid_partition par
)
1431 return par
? par
->size
: -1;
1435 * blkid_partition_get_type:
1438 * Returns: partition type.
1440 int blkid_partition_get_type(blkid_partition par
)
1445 /* Sets partition 'type' for PT where the type is defined by string rather
1448 int blkid_partition_set_type_string(blkid_partition par
,
1449 const unsigned char *type
, size_t len
)
1454 set_string((unsigned char *) par
->typestr
,
1455 sizeof(par
->typestr
), type
, len
);
1459 /* Sets partition 'type' for PT where the type is defined by UUIDrather
1462 int blkid_partition_set_type_uuid(blkid_partition par
, const unsigned char *uuid
)
1467 blkid_unparse_uuid(uuid
, par
->typestr
, sizeof(par
->typestr
));
1472 * blkid_partition_get_type_string:
1475 * The type string is supported by a small subset of partition tables (e.g Mac
1476 * and EFI GPT). Note that GPT uses type UUID and this function returns this
1479 * Returns: partition type string or NULL.
1481 const char *blkid_partition_get_type_string(blkid_partition par
)
1483 return par
&& *par
->typestr
? par
->typestr
: NULL
;
1487 int blkid_partition_set_flags(blkid_partition par
, unsigned long long flags
)
1496 * blkid_partition_get_flags
1499 * Returns: partition flags (or attributes for gpt).
1501 unsigned long long blkid_partition_get_flags(blkid_partition par
)