blob: 4853f97e29fc58b1664d8a41c9f7f424abd1cd89 [file] [log] [blame]
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001/*
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>
20#include <inttypes.h>
21#include <stdarg.h>
22
23#include "partitions.h"
24#include "sysfs.h"
25
26/**
27 * SECTION: partitions
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
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.
35 *
36 * NAME=value interface, supported tags:
37 *
38 * @PTTYPE: partition table type (dos, gpt, etc.).
39 *
bigbiff7b4c7a62015-01-01 19:44:14 -050040 * @PTUUID: partition table id (uuid for gpt, hex for dos).
41
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050042 * @PART_ENTRY_SCHEME: partition table type
43 *
44 * @PART_ENTRY_NAME: partition name (gpt and mac only)
45 *
bigbiff7b4c7a62015-01-01 19:44:14 -050046 * @PART_ENTRY_UUID: partition UUID (gpt, or pseudo IDs for MBR)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050047 *
48 * @PART_ENTRY_TYPE: partition type, 0xNN (e.g 0x82) or type UUID (gpt only) or type string (mac)
49 *
50 * @PART_ENTRY_FLAGS: partition flags (e.g. boot_ind) or attributes (e.g. gpt attributes)
51 *
52 * @PART_ENTRY_NUMBER: partition number
53 *
54 * @PART_ENTRY_OFFSET: the begin of the partition
55 *
56 * @PART_ENTRY_SIZE: size of the partition
57 *
58 * @PART_ENTRY_DISK: whole-disk maj:min
59 *
60 * Example:
61 *
62 * <informalexample>
63 * <programlisting>
64 * blkid_probe pr;
65 * const char *ptname;
66 *
67 * pr = blkid_new_probe_from_filename(devname);
68 * if (!pr)
69 * err("%s: faild to open device", devname);
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);
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;
90 *
91 * pr = blkid_new_probe_from_filename(devname);
92 * if (!pr)
93 * err("%s: faild to open device", devname);
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);
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{
125 &aix_pt_idinfo,
126 &sgi_pt_idinfo,
127 &sun_pt_idinfo,
128 &dos_pt_idinfo,
129 &gpt_pt_idinfo,
bigbiff7b4c7a62015-01-01 19:44:14 -0500130 &pmbr_pt_idinfo, /* always after GPT */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500131 &mac_pt_idinfo,
132 &ultrix_pt_idinfo,
133 &bsd_pt_idinfo,
134 &unixware_pt_idinfo,
135 &solaris_x86_pt_idinfo,
136 &minix_pt_idinfo
137};
138
139/*
140 * Driver definition
141 */
142const struct blkid_chaindrv partitions_drv = {
143 .id = BLKID_CHAIN_PARTS,
144 .name = "partitions",
145 .dflt_enabled = FALSE,
146 .idinfos = idinfos,
147 .nidinfos = ARRAY_SIZE(idinfos),
148 .has_fltr = TRUE,
149 .probe = partitions_probe,
150 .safeprobe = partitions_probe,
151 .free_data = partitions_free_data
152};
153
154
155/*
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.
159 *
160 * [Just for the record, I hate typedef for pointers --kzak]
161 */
162
163/* exported as opaque type "blkid_parttable" */
164struct blkid_struct_parttable {
165 const char *type; /* partition table type */
bigbiff7b4c7a62015-01-01 19:44:14 -0500166 blkid_loff_t offset; /* begin of the partition table (in bytes) */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500167 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) */
170
171 struct list_head t_tabs; /* all tables */
172};
173
174/* exported as opaque type "blkid_partition" */
175struct blkid_struct_partition {
bigbiff7b4c7a62015-01-01 19:44:14 -0500176 blkid_loff_t start; /* begin of the partition (512-bytes sectors) */
177 blkid_loff_t size; /* size of the partitions (512-bytes sectors) */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500178
179 int type; /* partition type */
180 char typestr[37]; /* partition type string (GPT and Mac) */
181
182 unsigned long long flags; /* partition flags / attributes */
183
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 */
187
188 blkid_parttable tab; /* partition table */
189};
190
191/* exported as opaque type "blkid_partlist" */
192struct blkid_struct_partlist {
193 int next_partno; /* next partition number */
194 blkid_partition next_parent; /* next parent if parsing nested PT */
195
196 int nparts; /* number of partitions */
197 int nparts_max; /* max.number of partitions */
198 blkid_partition parts; /* array of partitions */
199
200 struct list_head l_tabs; /* list of partition tables */
201};
202
203static int blkid_partitions_probe_partition(blkid_probe pr);
204
205/**
206 * blkid_probe_enable_partitions:
207 * @pr: probe
208 * @enable: TRUE/FALSE
209 *
210 * Enables/disables the partitions probing for non-binary interface.
211 *
212 * Returns: 0 on success, or -1 in case of error.
213 */
214int blkid_probe_enable_partitions(blkid_probe pr, int enable)
215{
216 if (!pr)
217 return -1;
218 pr->chains[BLKID_CHAIN_PARTS].enabled = enable;
219 return 0;
220}
221
222/**
223 * blkid_probe_set_partitions_flags:
224 * @pr: prober
225 * @flags: BLKID_PARTS_* flags
226 *
227 * Sets probing flags to the partitions prober. This function is optional.
228 *
229 * Returns: 0 on success, or -1 in case of error.
230 */
231int blkid_probe_set_partitions_flags(blkid_probe pr, int flags)
232{
233 if (!pr)
234 return -1;
235 pr->chains[BLKID_CHAIN_PARTS].flags = flags;
236 return 0;
237}
238
239/**
240 * blkid_probe_reset_partitions_filter:
241 * @pr: prober
242 *
243 * Resets partitions probing filter
244 *
245 * Returns: 0 on success, or -1 in case of error.
246 */
247int blkid_probe_reset_partitions_filter(blkid_probe pr)
248{
249 return __blkid_probe_reset_filter(pr, BLKID_CHAIN_PARTS);
250}
251
252/**
253 * blkid_probe_invert_partitions_filter:
254 * @pr: prober
255 *
256 * Inverts partitions probing filter
257 *
258 * Returns: 0 on success, or -1 in case of error.
259 */
260int blkid_probe_invert_partitions_filter(blkid_probe pr)
261{
262 return __blkid_probe_invert_filter(pr, BLKID_CHAIN_PARTS);
263}
264
265/**
266 * blkid_probe_filter_partitions_type:
267 * @pr: prober
268 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
269 * @names: NULL terminated array of probing function names (e.g. "vfat").
270 *
271 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names
272 *
273 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
274 *
275 * Returns: 0 on success, or -1 in case of error.
276 */
277int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *names[])
278{
279 return __blkid_probe_filter_types(pr, BLKID_CHAIN_PARTS, flag, names);
280}
281
282/**
283 * blkid_probe_get_partitions:
284 * @pr: probe
285 *
286 * This is a binary interface for partitions. See also blkid_partlist_*
287 * functions.
288 *
289 * This function is independent on blkid_do_[safe,full]probe() and
290 * blkid_probe_enable_partitions() calls.
291 *
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()).
296 *
297 * Returns: list of partitions, or NULL in case of error.
298 */
299blkid_partlist blkid_probe_get_partitions(blkid_probe pr)
300{
301 return (blkid_partlist) blkid_probe_get_binary_data(pr,
302 &pr->chains[BLKID_CHAIN_PARTS]);
303}
304
305/* for internal usage only */
306blkid_partlist blkid_probe_get_partlist(blkid_probe pr)
307{
308 return (blkid_partlist) pr->chains[BLKID_CHAIN_PARTS].data;
309}
310
311static void blkid_probe_set_partlist(blkid_probe pr, blkid_partlist ls)
312{
313 pr->chains[BLKID_CHAIN_PARTS].data = ls;
314}
315
316static void ref_parttable(blkid_parttable tab)
317{
318 tab->nparts++;
319}
320
321static void unref_parttable(blkid_parttable tab)
322{
323 tab->nparts--;
324
325 if (tab->nparts <= 0) {
326 list_del(&tab->t_tabs);
327 free(tab);
328 }
329}
330
331/* free all allocated parttables */
332static void free_parttables(blkid_partlist ls)
333{
334 if (!ls || !ls->l_tabs.next)
335 return;
336
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);
342 }
343}
344
345static void reset_partlist(blkid_partlist ls)
346{
347 if (!ls)
348 return;
349
350 free_parttables(ls);
351
352 if (ls->next_partno) {
353 /* already initialized - reset */
354 int tmp_nparts = ls->nparts_max;
355 blkid_partition tmp_parts = ls->parts;
356
357 memset(ls, 0, sizeof(struct blkid_struct_partlist));
358
359 ls->nparts_max = tmp_nparts;
360 ls->parts = tmp_parts;
361 }
362
363 ls->nparts = 0;
364 ls->next_partno = 1;
365 INIT_LIST_HEAD(&ls->l_tabs);
366
bigbiff7b4c7a62015-01-01 19:44:14 -0500367 DBG(LOWPROBE, ul_debug("partlist reset"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500368}
369
370static blkid_partlist partitions_init_data(struct blkid_chain *chn)
371{
372 blkid_partlist ls;
373
374 if (chn->data)
375 ls = (blkid_partlist) chn->data;
376 else {
377 /* allocate the new list of partitions */
378 ls = calloc(1, sizeof(struct blkid_struct_partlist));
379 if (!ls)
380 return NULL;
381 chn->data = (void *) ls;
382 }
383
384 reset_partlist(ls);
385
bigbiff7b4c7a62015-01-01 19:44:14 -0500386 DBG(LOWPROBE, ul_debug("parts: initialized partitions list (%p, size=%d)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500387 ls, ls->nparts_max));
388 return ls;
389}
390
391static void partitions_free_data(blkid_probe pr __attribute__((__unused__)),
392 void *data)
393{
394 blkid_partlist ls = (blkid_partlist) data;
395
396 if (!ls)
397 return;
398
399 free_parttables(ls);
400
401 /* deallocate partitions and partlist */
402 free(ls->parts);
403 free(ls);
404}
405
406blkid_parttable blkid_partlist_new_parttable(blkid_partlist ls,
407 const char *type, blkid_loff_t offset)
408{
409 blkid_parttable tab;
410
411 tab = calloc(1, sizeof(struct blkid_struct_parttable));
412 if (!tab)
413 return NULL;
414 tab->type = type;
415 tab->offset = offset;
416 tab->parent = ls->next_parent;
417
418 INIT_LIST_HEAD(&tab->t_tabs);
419 list_add_tail(&tab->t_tabs, &ls->l_tabs);
420
bigbiff7b4c7a62015-01-01 19:44:14 -0500421 DBG(LOWPROBE, ul_debug("parts: create a new partition table "
422 "(%p, type=%s, offset=%"PRId64")", tab, type, offset));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500423 return tab;
424}
425
426static blkid_partition new_partition(blkid_partlist ls, blkid_parttable tab)
427{
428 blkid_partition par;
429
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.
433 */
bigbiff7b4c7a62015-01-01 19:44:14 -0500434 void *tmp = realloc(ls->parts, (ls->nparts_max + 32) *
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500435 sizeof(struct blkid_struct_partition));
bigbiff7b4c7a62015-01-01 19:44:14 -0500436 if (!tmp)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500437 return NULL;
bigbiff7b4c7a62015-01-01 19:44:14 -0500438 ls->parts = tmp;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500439 ls->nparts_max += 32;
440 }
441
442 par = &ls->parts[ls->nparts++];
443 memset(par, 0, sizeof(struct blkid_struct_partition));
444
445 ref_parttable(tab);
446 par->tab = tab;
447 par->partno = blkid_partlist_increment_partno(ls);
448
449 return par;
450}
451
452blkid_partition blkid_partlist_add_partition(blkid_partlist ls,
453 blkid_parttable tab,
454 blkid_loff_t start, blkid_loff_t size)
455{
456 blkid_partition par = new_partition(ls, tab);
457
458 if (!par)
459 return NULL;
460
461 par->start = start;
462 par->size = size;
463
bigbiff7b4c7a62015-01-01 19:44:14 -0500464 DBG(LOWPROBE, ul_debug("parts: add partition (%p start=%"
465 PRId64 ", size=%" PRId64 ", table=%p)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500466 par, par->start, par->size, tab));
467 return par;
468}
469
470/* allows to modify used partitions numbers (for example for logical partitions) */
471int blkid_partlist_set_partno(blkid_partlist ls, int partno)
472{
473 if (!ls)
474 return -1;
475 ls->next_partno = partno;
476 return 0;
477}
478
479int blkid_partlist_increment_partno(blkid_partlist ls)
480{
481 return ls ? ls->next_partno++ : -1;
482}
483
484/* allows to set "parent" for the next nested partition */
485int blkid_partlist_set_parent(blkid_partlist ls, blkid_partition par)
486{
487 if (!ls)
488 return -1;
489 ls->next_parent = par;
490 return 0;
491}
492
493blkid_partition blkid_partlist_get_parent(blkid_partlist ls)
494{
495 if (!ls)
496 return NULL;
497 return ls->next_parent;
498}
499
500int blkid_partitions_need_typeonly(blkid_probe pr)
501{
502 struct blkid_chain *chn = blkid_probe_get_chain(pr);
503
504 return chn && chn->data && chn->binary ? FALSE : TRUE;
505}
506
507/* get private chain flags */
508int blkid_partitions_get_flags(blkid_probe pr)
509{
510 struct blkid_chain *chn = blkid_probe_get_chain(pr);
511
512 return chn ? chn->flags : 0;
513}
514
515/* check if @start and @size are within @par partition */
516int blkid_is_nested_dimension(blkid_partition par,
517 blkid_loff_t start, blkid_loff_t size)
518{
519 blkid_loff_t pstart;
520 blkid_loff_t psize;
521
522 if (!par)
523 return 0;
524
525 pstart = blkid_partition_get_start(par);
526 psize = blkid_partition_get_size(par);
527
528 if (start < pstart || start + size > pstart + psize)
529 return 0;
530
531 return 1;
532}
533
534static int idinfo_probe(blkid_probe pr, const struct blkid_idinfo *id,
535 struct blkid_chain *chn)
536{
537 const struct blkid_idmag *mag = NULL;
538 blkid_loff_t off;
bigbiff7b4c7a62015-01-01 19:44:14 -0500539 int rc = BLKID_PROBE_NONE; /* default is nothing */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500540
541 if (pr->size <= 0 || (id->minsz && id->minsz > pr->size))
542 goto nothing; /* the device is too small */
bigbiff7b4c7a62015-01-01 19:44:14 -0500543 if (pr->flags & BLKID_FL_NOSCAN_DEV)
544 goto nothing;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500545
bigbiff7b4c7a62015-01-01 19:44:14 -0500546 rc = blkid_probe_get_idmag(pr, id, &off, &mag);
547 if (rc != BLKID_PROBE_OK)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500548 goto nothing;
549
550 /* final check by probing function */
551 if (id->probefunc) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500552 DBG(LOWPROBE, ul_debug(
553 "%s: ---> call probefunc()", id->name));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500554 rc = id->probefunc(pr, mag);
bigbiff7b4c7a62015-01-01 19:44:14 -0500555 if (rc < 0) {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500556 /* reset after error */
557 reset_partlist(blkid_probe_get_partlist(pr));
558 if (chn && !chn->binary)
559 blkid_probe_chain_reset_vals(pr, chn);
bigbiff7b4c7a62015-01-01 19:44:14 -0500560 DBG(LOWPROBE, ul_debug("%s probefunc failed, rc %d",
561 id->name, rc));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500562 }
bigbiff7b4c7a62015-01-01 19:44:14 -0500563 if (rc == BLKID_PROBE_OK && mag && chn && !chn->binary)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500564 rc = blkid_probe_set_magic(pr, off, mag->len,
565 (unsigned char *) mag->magic);
566
bigbiff7b4c7a62015-01-01 19:44:14 -0500567 DBG(LOWPROBE, ul_debug("%s: <--- (rc = %d)", id->name, rc));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500568 }
569
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500570 return rc;
bigbiff7b4c7a62015-01-01 19:44:14 -0500571
572nothing:
573 return BLKID_PROBE_NONE;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500574}
575
576/*
577 * The blkid_do_probe() backend.
578 */
579static int partitions_probe(blkid_probe pr, struct blkid_chain *chn)
580{
bigbiff7b4c7a62015-01-01 19:44:14 -0500581 int rc = BLKID_PROBE_NONE;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500582 size_t i;
583
584 if (!pr || chn->idx < -1)
bigbiff7b4c7a62015-01-01 19:44:14 -0500585 return -EINVAL;
586
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500587 blkid_probe_chain_reset_vals(pr, chn);
588
bigbiff7b4c7a62015-01-01 19:44:14 -0500589 if (pr->flags & BLKID_FL_NOSCAN_DEV)
590 return BLKID_PROBE_NONE;
591
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500592 if (chn->binary)
593 partitions_init_data(chn);
594
595 if (!pr->wipe_size && (pr->prob_flags & BLKID_PROBE_FL_IGNORE_PT))
596 goto details_only;
597
bigbiff7b4c7a62015-01-01 19:44:14 -0500598 DBG(LOWPROBE, ul_debug("--> starting probing loop [PARTS idx=%d]",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500599 chn->idx));
600
601 i = chn->idx < 0 ? 0 : chn->idx + 1U;
602
603 for ( ; i < ARRAY_SIZE(idinfos); i++) {
604 const char *name;
605
606 chn->idx = i;
607
608 /* apply filter */
609 if (chn->fltr && blkid_bmp_get_item(chn->fltr, i))
610 continue;
611
612 /* apply checks from idinfo */
bigbiff7b4c7a62015-01-01 19:44:14 -0500613 rc = idinfo_probe(pr, idinfos[i], chn);
614 if (rc < 0)
615 break;
616 if (rc != BLKID_PROBE_OK)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500617 continue;
618
619 name = idinfos[i]->name;
620
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500621 if (!chn->binary)
bigbiff7b4c7a62015-01-01 19:44:14 -0500622 /*
623 * Non-binary interface, set generic variables. Note
624 * that the another variables could be set in prober
625 * functions.
626 */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500627 blkid_probe_set_value(pr, "PTTYPE",
628 (unsigned char *) name,
629 strlen(name) + 1);
bigbiff7b4c7a62015-01-01 19:44:14 -0500630
631 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [PARTS idx=%d]",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500632 name, chn->idx));
bigbiff7b4c7a62015-01-01 19:44:14 -0500633 rc = BLKID_PROBE_OK;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500634 break;
635 }
636
bigbiff7b4c7a62015-01-01 19:44:14 -0500637 if (rc != BLKID_PROBE_OK) {
638 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [PARTS idx=%d]",
639 rc, chn->idx));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500640 }
641
642details_only:
643 /*
644 * Gather PART_ENTRY_* values if the current device is a partition.
645 */
bigbiff7b4c7a62015-01-01 19:44:14 -0500646 if ((rc == BLKID_PROBE_OK || rc == BLKID_PROBE_NONE) && !chn->binary &&
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500647 (blkid_partitions_get_flags(pr) & BLKID_PARTS_ENTRY_DETAILS)) {
648
bigbiff7b4c7a62015-01-01 19:44:14 -0500649 int xrc = blkid_partitions_probe_partition(pr);
650
651 /* partition entry probing is optional, and "not-found" from
652 * this sub-probing must not to overwrite previous success. */
653 if (xrc < 0)
654 rc = xrc; /* always propagate errors */
655 else if (rc == BLKID_PROBE_NONE)
656 rc = xrc;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500657 }
658
bigbiff7b4c7a62015-01-01 19:44:14 -0500659 DBG(LOWPROBE, ul_debug("partitions probe done [rc=%d]", rc));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500660 return rc;
661}
662
663/* Probe for nested partition table within the parental partition */
664int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent,
665 const struct blkid_idinfo *id)
666{
667 blkid_probe prc;
bigbiff7b4c7a62015-01-01 19:44:14 -0500668 int rc;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500669 blkid_partlist ls;
670 blkid_loff_t sz, off;
671
bigbiff7b4c7a62015-01-01 19:44:14 -0500672 DBG(LOWPROBE, ul_debug(
673 "parts: ----> %s subprobe requested (parent=%p)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500674 id->name, parent));
675
676 if (!pr || !parent || !parent->size)
bigbiff7b4c7a62015-01-01 19:44:14 -0500677 return -EINVAL;
678 if (pr->flags & BLKID_FL_NOSCAN_DEV)
679 return BLKID_PROBE_NONE;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500680
681 /* range defined by parent */
682 sz = ((blkid_loff_t) parent->size) << 9;
683 off = ((blkid_loff_t) parent->start) << 9;
684
685 if (off < pr->off || pr->off + pr->size < off + sz) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500686 DBG(LOWPROBE, ul_debug(
687 "ERROR: parts: <---- '%s' subprobe: overflow detected.",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500688 id->name));
bigbiff7b4c7a62015-01-01 19:44:14 -0500689 return -ENOSPC;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500690 }
691
692 /* create private prober */
693 prc = blkid_clone_probe(pr);
694 if (!prc)
bigbiff7b4c7a62015-01-01 19:44:14 -0500695 return -ENOMEM;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500696
697 blkid_probe_set_dimension(prc, off, sz);
698
699 /* clone is always with reset chain, fix it */
700 prc->cur_chain = blkid_probe_get_chain(pr);
701
702 /*
703 * Set 'parent' to the current list of the partitions and use the list
704 * in cloned prober (so the cloned prober will extend the current list
705 * of partitions rather than create a new).
706 */
707 ls = blkid_probe_get_partlist(pr);
708 blkid_partlist_set_parent(ls, parent);
709
710 blkid_probe_set_partlist(prc, ls);
711
712 rc = idinfo_probe(prc, id, blkid_probe_get_chain(pr));
713
714 blkid_probe_set_partlist(prc, NULL);
715 blkid_partlist_set_parent(ls, NULL);
716
717 blkid_free_probe(prc); /* free cloned prober */
718
bigbiff7b4c7a62015-01-01 19:44:14 -0500719 DBG(LOWPROBE, ul_debug(
720 "parts: <---- %s subprobe done (parent=%p, rc=%d)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500721 id->name, parent, rc));
722
723 return rc;
724}
725
726static int blkid_partitions_probe_partition(blkid_probe pr)
727{
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500728 blkid_probe disk_pr = NULL;
729 blkid_partlist ls;
730 blkid_partition par;
731 dev_t devno;
732
bigbiff7b4c7a62015-01-01 19:44:14 -0500733 DBG(LOWPROBE, ul_debug("parts: start probing for partition entry"));
734
735 if (pr->flags & BLKID_FL_NOSCAN_DEV)
736 goto nothing;
737
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500738 devno = blkid_probe_get_devno(pr);
739 if (!devno)
740 goto nothing;
741
742 disk_pr = blkid_probe_get_wholedisk_probe(pr);
743 if (!disk_pr)
744 goto nothing;
745
746 /* parse PT */
747 ls = blkid_probe_get_partitions(disk_pr);
748 if (!ls)
749 goto nothing;
750
751 par = blkid_partlist_devno_to_partition(ls, devno);
bigbiff7b4c7a62015-01-01 19:44:14 -0500752 if (!par)
753 goto nothing;
754 else {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500755 const char *v;
756 blkid_parttable tab = blkid_partition_get_table(par);
757 dev_t disk = blkid_probe_get_devno(disk_pr);
758
759 if (tab) {
760 v = blkid_parttable_get_type(tab);
761 if (v)
762 blkid_probe_set_value(pr, "PART_ENTRY_SCHEME",
763 (unsigned char *) v, strlen(v) + 1);
764 }
765
766 v = blkid_partition_get_name(par);
767 if (v)
768 blkid_probe_set_value(pr, "PART_ENTRY_NAME",
769 (unsigned char *) v, strlen(v) + 1);
770
771 v = blkid_partition_get_uuid(par);
772 if (v)
773 blkid_probe_set_value(pr, "PART_ENTRY_UUID",
774 (unsigned char *) v, strlen(v) + 1);
775
776 /* type */
777 v = blkid_partition_get_type_string(par);
778 if (v)
779 blkid_probe_set_value(pr, "PART_ENTRY_TYPE",
780 (unsigned char *) v, strlen(v) + 1);
781 else
782 blkid_probe_sprintf_value(pr, "PART_ENTRY_TYPE",
783 "0x%x", blkid_partition_get_type(par));
784
785 if (blkid_partition_get_flags(par))
786 blkid_probe_sprintf_value(pr, "PART_ENTRY_FLAGS",
787 "0x%llx", blkid_partition_get_flags(par));
788
789 blkid_probe_sprintf_value(pr, "PART_ENTRY_NUMBER",
790 "%d", blkid_partition_get_partno(par));
791
792 blkid_probe_sprintf_value(pr, "PART_ENTRY_OFFSET", "%jd",
793 blkid_partition_get_start(par));
794 blkid_probe_sprintf_value(pr, "PART_ENTRY_SIZE", "%jd",
795 blkid_partition_get_size(par));
796
797 blkid_probe_sprintf_value(pr, "PART_ENTRY_DISK", "%u:%u",
798 major(disk), minor(disk));
799 }
bigbiff7b4c7a62015-01-01 19:44:14 -0500800
801 DBG(LOWPROBE, ul_debug("parts: end probing for partition entry [success]"));
802 return BLKID_PROBE_OK;
803
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500804nothing:
bigbiff7b4c7a62015-01-01 19:44:14 -0500805 DBG(LOWPROBE, ul_debug("parts: end probing for partition entry [nothing]"));
806 return BLKID_PROBE_NONE;
807
808
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500809}
810
811/*
812 * Returns 1 if the device is whole-disk and the area specified by @offset and
813 * @size is covered by any partition.
814 */
815int blkid_probe_is_covered_by_pt(blkid_probe pr,
816 blkid_loff_t offset, blkid_loff_t size)
817{
bigbiff7b4c7a62015-01-01 19:44:14 -0500818 blkid_probe prc = NULL;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500819 blkid_partlist ls = NULL;
820 blkid_loff_t start, end;
821 int nparts, i, rc = 0;
822
bigbiff7b4c7a62015-01-01 19:44:14 -0500823 DBG(LOWPROBE, ul_debug(
824 "=> checking if off=%jd size=%jd covered by PT",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500825 offset, size));
826
bigbiff7b4c7a62015-01-01 19:44:14 -0500827 if (pr->flags & BLKID_FL_NOSCAN_DEV)
828 goto done;
829
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500830 prc = blkid_clone_probe(pr);
831 if (!prc)
832 goto done;
833
834 ls = blkid_probe_get_partitions(prc);
835 if (!ls)
836 goto done;
837
838 nparts = blkid_partlist_numof_partitions(ls);
839 if (!nparts)
840 goto done;
841
842 end = (offset + size) >> 9;
843 start = offset >> 9;
844
845 /* check if the partition table fits into the device */
846 for (i = 0; i < nparts; i++) {
847 blkid_partition par = &ls->parts[i];
848
849 if (par->start + par->size > (pr->size >> 9)) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500850 DBG(LOWPROBE, ul_debug("partition #%d overflows "
851 "device (off=%" PRId64 " size=%" PRId64 ")",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500852 par->partno, par->start, par->size));
853 goto done;
854 }
855 }
856
857 /* check if the requested area is covered by PT */
858 for (i = 0; i < nparts; i++) {
859 blkid_partition par = &ls->parts[i];
860
861 if (start >= par->start && end <= par->start + par->size) {
862 rc = 1;
863 break;
864 }
865 }
866done:
867 blkid_free_probe(prc);
868
bigbiff7b4c7a62015-01-01 19:44:14 -0500869 DBG(LOWPROBE, ul_debug("<= %s covered by PT", rc ? "IS" : "NOT"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500870 return rc;
871}
872
873/**
874 * blkid_known_pttype:
875 * @pttype: partiton name
876 *
877 * Returns: 1 for known or 0 for unknown partition type.
878 */
879int blkid_known_pttype(const char *pttype)
880{
881 size_t i;
882
883 if (!pttype)
884 return 0;
885
886 for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
887 const struct blkid_idinfo *id = idinfos[i];
888 if (strcmp(id->name, pttype) == 0)
889 return 1;
890 }
891 return 0;
892}
893
894/**
895 * blkid_partlist_numof_partitions:
896 * @ls: partitions list
897 *
898 * Returns: number of partitions in the list or -1 in case of error.
899 */
900int blkid_partlist_numof_partitions(blkid_partlist ls)
901{
902 return ls ? ls->nparts : -1;
903}
904
905/**
906 * blkid_partlist_get_table:
907 * @ls: partitions list
908 *
909 * Returns: top-level partition table or NULL of there is not a partition table
910 * on the device.
911 */
912blkid_parttable blkid_partlist_get_table(blkid_partlist ls)
913{
914 if (!ls || list_empty(&ls->l_tabs))
915 return NULL;
916
917 return list_entry(ls->l_tabs.next,
918 struct blkid_struct_parttable, t_tabs);
919}
920
921
922/**
923 * blkid_partlist_get_partition:
924 * @ls: partitions list
925 * @n: partition number in range 0..N, where 'N' is blkid_partlist_numof_partitions().
926 *
927 * It's possible that the list of partitions is *empty*, but there is a valid
928 * partition table on the disk. This happen when on-disk details about
929 * partitions are unknown or the partition table is empty.
930 *
931 * See also blkid_partlist_get_table().
932 *
933 * Returns: partition object or NULL in case or error.
934 */
935blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n)
936{
937 if (!ls || n < 0 || n >= ls->nparts)
938 return NULL;
939
940 return &ls->parts[n];
941}
942
943/**
bigbiff7b4c7a62015-01-01 19:44:14 -0500944 * blkid_partlist_get_partition_by_partno
945 * @ls: partitions list
946 * @n: the partition number (e.g. 'N' from sda'N')
947 *
948 * This does not assume any order of the input blkid_partlist. And correctly
949 * handles "out of order" partition tables. partition N is located after
950 * partition N+1 on the disk.
951 *
952 * Returns: partition object or NULL in case or error.
953 */
954blkid_partition blkid_partlist_get_partition_by_partno(blkid_partlist ls, int n)
955{
956 int i, nparts;
957 blkid_partition par;
958
959 if (!ls)
960 return NULL;
961
962 nparts = blkid_partlist_numof_partitions(ls);
963 for (i = 0; i < nparts; i++) {
964 par = blkid_partlist_get_partition(ls, i);
965 if (n == blkid_partition_get_partno(par))
966 return par;
967 }
968 return NULL;
969}
970
971
972/**
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500973 * blkid_partlist_devno_to_partition:
974 * @ls: partitions list
975 * @devno: requested partition
976 *
977 * This function tries to get start and size for @devno from sysfs and
978 * returns a partition from @ls which matches with the values from sysfs.
979 *
980 * This function is necessary when you want to make a relation between an entry
981 * in the partition table (@ls) and block devices in your system.
982 *
983 * Returns: partition object or NULL in case or error.
984 */
985blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno)
986{
987 struct sysfs_cxt sysfs;
988 uint64_t start, size;
989 int i, rc, partno = 0;
990
991 if (!ls)
992 return NULL;
993
bigbiff7b4c7a62015-01-01 19:44:14 -0500994 DBG(LOWPROBE, ul_debug("triyng to convert devno 0x%llx to partition",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500995 (long long) devno));
996
997 if (sysfs_init(&sysfs, devno, NULL)) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500998 DBG(LOWPROBE, ul_debug("failed t init sysfs context"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500999 return NULL;
1000 }
1001 rc = sysfs_read_u64(&sysfs, "size", &size);
1002 if (!rc) {
1003 rc = sysfs_read_u64(&sysfs, "start", &start);
1004 if (rc) {
1005 /* try to get partition number from DM uuid.
1006 */
1007 char *uuid = sysfs_strdup(&sysfs, "dm/uuid");
1008 char *tmp = uuid;
1009 char *prefix = uuid ? strsep(&tmp, "-") : NULL;
1010
1011 if (prefix && strncasecmp(prefix, "part", 4) == 0) {
1012 char *end = NULL;
1013
1014 partno = strtol(prefix + 4, &end, 10);
1015 if (prefix == end || (end && *end))
1016 partno = 0;
1017 else
1018 rc = 0; /* success */
1019 }
1020 free(uuid);
1021 }
1022 }
1023
1024 sysfs_deinit(&sysfs);
1025
1026 if (rc)
1027 return NULL;
1028
1029 if (partno) {
bigbiff7b4c7a62015-01-01 19:44:14 -05001030 DBG(LOWPROBE, ul_debug("mapped by DM, using partno %d", partno));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001031
1032 /*
1033 * Partition mapped by kpartx does not provide "start" offset
1034 * in /sys, but if we know partno and size of the partition
1035 * that we can probably make the releation bettween the device
1036 * and an entry in partition table.
1037 */
1038 for (i = 0; i < ls->nparts; i++) {
1039 blkid_partition par = &ls->parts[i];
1040
1041 if (partno != blkid_partition_get_partno(par))
1042 continue;
1043
1044 if ((blkid_loff_t) size == blkid_partition_get_size(par) ||
1045 (blkid_partition_is_extended(par) && size <= 1024))
1046 return par;
1047
1048 }
1049 return NULL;
1050 }
1051
bigbiff7b4c7a62015-01-01 19:44:14 -05001052 DBG(LOWPROBE, ul_debug("searching by offset/size"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001053
1054 for (i = 0; i < ls->nparts; i++) {
1055 blkid_partition par = &ls->parts[i];
1056
1057 if (blkid_partition_get_start(par) == (blkid_loff_t) start &&
1058 blkid_partition_get_size(par) == (blkid_loff_t) size)
1059 return par;
1060
1061 /* exception for extended dos partitions */
1062 if (blkid_partition_get_start(par) == (blkid_loff_t) start &&
1063 blkid_partition_is_extended(par) && size <= 1024)
1064 return par;
1065
1066 }
1067
bigbiff7b4c7a62015-01-01 19:44:14 -05001068 DBG(LOWPROBE, ul_debug("not found partition for device"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001069 return NULL;
1070}
1071
bigbiff7b4c7a62015-01-01 19:44:14 -05001072
1073int blkid_parttable_set_uuid(blkid_parttable tab, const unsigned char *id)
1074{
1075 if (!tab)
1076 return -1;
1077
1078 blkid_unparse_uuid(id, tab->id, sizeof(tab->id));
1079 return 0;
1080}
1081
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001082int blkid_parttable_set_id(blkid_parttable tab, const unsigned char *id)
1083{
1084 if (!tab)
1085 return -1;
1086
bigbiff7b4c7a62015-01-01 19:44:14 -05001087 strncpy(tab->id, (const char *) id, sizeof(tab->id));
1088 return 0;
1089}
1090
1091/* set PTUUID variable for non-binary API */
1092int blkid_partitions_set_ptuuid(blkid_probe pr, unsigned char *uuid)
1093{
1094 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1095 struct blkid_prval *v;
1096
1097 if (chn->binary || blkid_uuid_is_empty(uuid, 16))
1098 return 0;
1099
1100 v = blkid_probe_assign_value(pr, "PTUUID");
1101
1102 blkid_unparse_uuid(uuid, (char *) v->data, sizeof(v->data));
1103 v->len = 37;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001104
1105 return 0;
1106}
1107
bigbiff7b4c7a62015-01-01 19:44:14 -05001108/* set PTUUID variable for non-binary API for tables where
1109 * the ID is just a string */
1110int blkid_partitions_strcpy_ptuuid(blkid_probe pr, char *str)
1111{
1112 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1113 struct blkid_prval *v;
1114 size_t len;
1115
1116 if (chn->binary || !str || !*str)
1117 return 0;
1118
1119 len = strlen((char *) str);
1120 if (len > BLKID_PROBVAL_BUFSIZ)
1121 len = BLKID_PROBVAL_BUFSIZ;
1122
1123 v = blkid_probe_assign_value(pr, "PTUUID");
1124 if (v) {
1125 if (len == BLKID_PROBVAL_BUFSIZ)
1126 len--; /* make a space for \0 */
1127
1128 memcpy((char *) v->data, str, len);
1129 v->data[len] = '\0';
1130 v->len = len + 1;
1131 return 0;
1132 }
1133 return -1;
1134}
1135
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001136/**
1137 * blkid_parttable_get_id:
1138 * @tab: partition table
1139 *
1140 * The ID is GPT disk UUID or DOS disk ID (in hex format).
1141 *
1142 * Returns: partition table ID (for example GPT disk UUID) or NULL
1143 */
1144const char *blkid_parttable_get_id(blkid_parttable tab)
1145{
bigbiff7b4c7a62015-01-01 19:44:14 -05001146 return tab && *tab->id ? tab->id : NULL;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001147}
1148
1149
1150int blkid_partition_set_type(blkid_partition par, int type)
1151{
1152 if (!par)
1153 return -1;
1154 par->type = type;
1155 return 0;
1156}
1157
1158/**
1159 * blkid_parttable_get_type:
1160 * @tab: partition table
1161 *
1162 * Returns: partition table type (type name, e.g. "dos", "gpt", ...)
1163 */
1164const char *blkid_parttable_get_type(blkid_parttable tab)
1165{
1166 return tab ? tab->type : NULL;
1167}
1168
1169/**
1170 * blkid_parttable_get_parent:
1171 * @tab: partition table
1172 *
1173 * Returns: parent for nexted partitition tables or NULL.
1174 */
1175blkid_partition blkid_parttable_get_parent(blkid_parttable tab)
1176{
1177 return tab ? tab->parent : NULL;
1178}
1179
1180/**
1181 * blkid_parttable_get_offset:
1182 * @tab: partition table
1183 *
1184 * Note the position is relative to begin of the device as defined by
1185 * blkid_probe_set_device() for primary partition table, and relative
1186 * to parental partition for nested patition tables.
1187 *
1188 * <informalexample>
1189 * <programlisting>
1190 * off_t offset;
1191 * blkid_partition parent = blkid_parttable_get_parent(tab);
1192 *
1193 * offset = blkid_parttable_get_offset(tab);
1194 *
1195 * if (parent)
1196 * / * 'tab' is nested partition table * /
1197 * offset += blkid_partition_get_start(parent);
1198 * </programlisting>
1199 * </informalexample>
1200
1201 * Returns: position (in bytes) of the partition table or -1 in case of error.
1202 *
1203 */
1204blkid_loff_t blkid_parttable_get_offset(blkid_parttable tab)
1205{
1206 return tab ? tab->offset : -1;
1207}
1208
1209/**
1210 * blkid_partition_get_table:
1211 * @par: partition
1212 *
1213 * The "parttable" describes partition table. The table is usually the same for
1214 * all partitions -- except nested partition tables.
1215 *
1216 * For example bsd, solaris, etc. use a nested partition table within
1217 * standard primary dos partition:
1218 *
1219 * <informalexample>
1220 * <programlisting>
1221 *
1222 * -- dos partition table
1223 * 0: sda1 dos primary partition
1224 * 1: sda2 dos primary partition
1225 * -- bsd partition table (with in sda2)
1226 * 2: sda5 bds partition
1227 * 3: sda6 bds partition
1228 *
1229 * </programlisting>
1230 * </informalexample>
1231 *
1232 * The library does not to use a separate partition table object for dos logical
1233 * partitions (partitions within extended partition). It's possible to
1234 * differentiate between logical, extended and primary partitions by
1235 *
1236 * blkid_partition_is_{extended,primary,logical}().
1237 *
1238 * Returns: partition table object or NULL in case of error.
1239 */
1240blkid_parttable blkid_partition_get_table(blkid_partition par)
1241{
1242 return par ? par->tab : NULL;
1243}
1244
1245static int partition_get_logical_type(blkid_partition par)
1246{
1247 blkid_parttable tab;
1248
1249 if (!par)
1250 return -1;
1251
1252 tab = blkid_partition_get_table(par);
1253 if (!tab || !tab->type)
1254 return -1;
1255
1256 if (tab->parent)
1257 return 'L'; /* report nested partitions as logical */
1258
1259 if (!strcmp(tab->type, "dos")) {
1260 if (par->partno > 4)
1261 return 'L'; /* logical */
1262
bigbiff7b4c7a62015-01-01 19:44:14 -05001263 if(par->type == MBR_DOS_EXTENDED_PARTITION ||
1264 par->type == MBR_W95_EXTENDED_PARTITION ||
1265 par->type == MBR_LINUX_EXTENDED_PARTITION)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001266 return 'E';
1267 }
1268 return 'P';
1269}
1270
1271/**
1272 * blkid_partition_is_primary:
1273 * @par: partition
1274 *
1275 * Note, this function returns FALSE for DOS extended partitions and
1276 * all partitions in nested partition tables.
1277 *
1278 * Returns: 1 if the partitions is primary partition or 0 if not.
1279 */
1280int blkid_partition_is_primary(blkid_partition par)
1281{
1282 return partition_get_logical_type(par) == 'P' ? TRUE : FALSE;
1283}
1284
1285/**
1286 * blkid_partition_is_extended:
1287 * @par: partition
1288 *
1289 * Returns: 1 if the partitions is extended (dos, windows or linux)
1290 * partition or 0 if not.
1291 */
1292int blkid_partition_is_extended(blkid_partition par)
1293{
1294 return partition_get_logical_type(par) == 'E' ? TRUE : FALSE;
1295}
1296
1297/**
1298 * blkid_partition_is_logical:
1299 * @par: partition
1300 *
1301 * Note that this function returns TRUE for all partitions in all
1302 * nested partition tables (e.g. BSD labels).
1303 *
1304 * Returns: 1 if the partitions is logical partition or 0 if not.
1305 */
1306int blkid_partition_is_logical(blkid_partition par)
1307{
1308 return partition_get_logical_type(par) == 'L' ? TRUE : FALSE;
1309}
1310
1311static void set_string(unsigned char *item, size_t max,
1312 const unsigned char *data, size_t len)
1313{
1314 if (len >= max)
1315 len = max - 1;
1316
1317 memcpy(item, data, len);
1318 item[len] = '\0';
1319
1320 blkid_rtrim_whitespace(item);
1321}
1322
1323int blkid_partition_set_name(blkid_partition par,
1324 const unsigned char *name, size_t len)
1325{
1326 if (!par)
1327 return -1;
1328
1329 set_string(par->name, sizeof(par->name), name, len);
1330 return 0;
1331}
1332
1333int blkid_partition_set_utf8name(blkid_partition par, const unsigned char *name,
1334 size_t len, int enc)
1335{
1336 if (!par)
1337 return -1;
1338
1339 blkid_encode_to_utf8(enc, par->name, sizeof(par->name), name, len);
1340 blkid_rtrim_whitespace(par->name);
1341 return 0;
1342}
1343
1344int blkid_partition_set_uuid(blkid_partition par, const unsigned char *uuid)
1345{
1346 if (!par)
1347 return -1;
1348
1349 blkid_unparse_uuid(uuid, par->uuid, sizeof(par->uuid));
1350 return 0;
1351}
1352
bigbiff7b4c7a62015-01-01 19:44:14 -05001353int blkid_partition_gen_uuid(blkid_partition par)
1354{
1355 if (!par || !par->tab || !*par->tab->id)
1356 return -1;
1357
1358 snprintf(par->uuid, sizeof(par->uuid), "%s-%02x",
1359 par->tab->id, par->partno);
1360 return 0;
1361}
1362
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001363/**
1364 * blkid_partition_get_name:
1365 * @par: partition
1366 *
1367 * Returns: partition name string if supported by PT (e.g. Mac) or NULL.
1368 */
1369const char *blkid_partition_get_name(blkid_partition par)
1370{
1371 return par && *par->name ? (char *) par->name : NULL;
1372}
1373
1374/**
1375 * blkid_partition_get_uuid:
1376 * @par: partition
1377 *
1378 * Returns: partition UUID string if supported by PT (e.g. GPT) or NULL.
1379 */
1380const char *blkid_partition_get_uuid(blkid_partition par)
1381{
1382 return par && *par->uuid ? par->uuid : NULL;
1383}
1384
1385/**
1386 * blkid_partition_get_partno:
1387 * @par: partition
1388 *
1389 * Returns: proposed partitin number (e.g. 'N' from sda'N') or -1 in case of
1390 * error. Note that the number is generate by library independenly on your OS.
1391 */
1392int blkid_partition_get_partno(blkid_partition par)
1393{
1394 return par ? par->partno : -1;
1395}
1396
1397/**
1398 * blkid_partition_get_start:
1399 * @par: partition
1400 *
1401 * Be careful if you _not_ probe whole disk:
1402 *
1403 * 1) the offset is usully relative to begin of the disk -- but if you probe a
1404 * fragment of the disk only -- then the offset could be still relative to
1405 * the begin of the disk rather that relative to the fragment.
1406 *
1407 * 2) the offset for nested partitions could be releative to parent (e.g. Solaris)
1408 * _or_ relative to the begin of the whole disk (e.g. bsd).
1409 *
1410 * You don't have to care about such details if you proble whole disk. In such
1411 * a case libblkid always returns the offset relative to the begin of the disk.
1412 *
1413 * Returns: start of the partition (in 512-sectors).
1414 */
1415blkid_loff_t blkid_partition_get_start(blkid_partition par)
1416{
1417 return par ? par->start : -1;
1418}
1419
1420/**
1421 * blkid_partition_get_size:
1422 * @par: partition
1423 *
1424 * WARNING: be very careful when you work with MS-DOS extended partitions. The
1425 * library always returns full size of the partition. If you want add
1426 * the partition to the Linux system (BLKPG_ADD_PARTITION ioctl) you
1427 * need to reduce the size of the partition to 1 or 2 blocks. The
1428 * rest of the partition has to be unaccessible for mkfs or mkswap
1429 * programs, we need a small space for boot loaders only.
1430 *
1431 * For some unknown reason this (safe) practice is not to used for
1432 * nested BSD, Solaris, ..., partition tables in Linux kernel.
1433 *
1434 * Returns: size of the partition (in 512-sectors).
1435 */
1436blkid_loff_t blkid_partition_get_size(blkid_partition par)
1437{
1438 return par ? par->size : -1;
1439}
1440
1441/**
1442 * blkid_partition_get_type:
1443 * @par: partition
1444 *
1445 * Returns: partition type.
1446 */
1447int blkid_partition_get_type(blkid_partition par)
1448{
1449 return par->type;
1450}
1451
1452/* Sets partition 'type' for PT where the type is defined by string rather
1453 * than by number
1454 */
1455int blkid_partition_set_type_string(blkid_partition par,
1456 const unsigned char *type, size_t len)
1457{
1458 if (!par)
1459 return -1;
1460
1461 set_string((unsigned char *) par->typestr,
1462 sizeof(par->typestr), type, len);
1463 return 0;
1464}
1465
1466/* Sets partition 'type' for PT where the type is defined by UUIDrather
1467 * than by number
1468 */
1469int blkid_partition_set_type_uuid(blkid_partition par, const unsigned char *uuid)
1470{
1471 if (!par)
1472 return -1;
1473
1474 blkid_unparse_uuid(uuid, par->typestr, sizeof(par->typestr));
1475 return 0;
1476}
1477
1478/**
1479 * blkid_partition_get_type_string:
1480 * @par: partition
1481 *
1482 * The type string is supported by a small subset of partition tables (e.g Mac
1483 * and EFI GPT). Note that GPT uses type UUID and this function returns this
1484 * UUID as string.
1485 *
1486 * Returns: partition type string or NULL.
1487 */
1488const char *blkid_partition_get_type_string(blkid_partition par)
1489{
1490 return par && *par->typestr ? par->typestr : NULL;
1491}
1492
1493
1494int blkid_partition_set_flags(blkid_partition par, unsigned long long flags)
1495{
1496 if (!par)
1497 return -1;
1498 par->flags = flags;
1499 return 0;
1500}
1501
1502/**
1503 * blkid_partition_get_flags
1504 * @par: partition
1505 *
1506 * Returns: partition flags (or attributes for gpt).
1507 */
1508unsigned long long blkid_partition_get_flags(blkid_partition par)
1509{
1510 return par->flags;
1511}
1512