blob: 25f1828a6514e05d551a95ba2d19063f594a8905 [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>
Ethan Yonkerfefe5912017-09-30 22:22:13 -050018#include <sys/sysmacros.h>
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050019#include <errno.h>
20#include <stdint.h>
21#include <inttypes.h>
22#include <stdarg.h>
23
24#include "partitions.h"
25#include "sysfs.h"
26
27/**
28 * SECTION: partitions
29 * @title: Partitions probing
30 * @short_description: partitions tables detection and parsing
31 *
32 * This chain supports binary and NAME=value interfaces, but complete PT
33 * description is provided by binary interface only. The libblkid prober is
34 * compatible with kernel partition tables parser. The parser does not return
35 * empty (size=0) partitions or special hidden partitions.
36 *
37 * NAME=value interface, supported tags:
38 *
39 * @PTTYPE: partition table type (dos, gpt, etc.).
40 *
bigbiff7b4c7a62015-01-01 19:44:14 -050041 * @PTUUID: partition table id (uuid for gpt, hex for dos).
42
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050043 * @PART_ENTRY_SCHEME: partition table type
44 *
45 * @PART_ENTRY_NAME: partition name (gpt and mac only)
46 *
bigbiff7b4c7a62015-01-01 19:44:14 -050047 * @PART_ENTRY_UUID: partition UUID (gpt, or pseudo IDs for MBR)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -050048 *
49 * @PART_ENTRY_TYPE: partition type, 0xNN (e.g 0x82) or type UUID (gpt only) or type string (mac)
50 *
51 * @PART_ENTRY_FLAGS: partition flags (e.g. boot_ind) or attributes (e.g. gpt attributes)
52 *
53 * @PART_ENTRY_NUMBER: partition number
54 *
55 * @PART_ENTRY_OFFSET: the begin of the partition
56 *
57 * @PART_ENTRY_SIZE: size of the partition
58 *
59 * @PART_ENTRY_DISK: whole-disk maj:min
60 *
61 * Example:
62 *
63 * <informalexample>
64 * <programlisting>
65 * blkid_probe pr;
66 * const char *ptname;
67 *
68 * pr = blkid_new_probe_from_filename(devname);
69 * if (!pr)
70 * err("%s: faild to open device", devname);
71 *
72 * blkid_probe_enable_partitions(pr, TRUE);
73 * blkid_do_fullprobe(pr);
74 *
75 * blkid_probe_lookup_value(pr, "PTTYPE", &ptname, NULL);
76 * printf("%s partition type detected\n", pttype);
77 *
78 * blkid_free_probe(pr);
79 *
80 * // don't forget to check return codes in your code!
81 * </programlisting>
82 * </informalexample>
83 *
84 * Binary interface:
85 *
86 * <informalexample>
87 * <programlisting>
88 * blkid_probe pr;
89 * blkid_partlist ls;
90 * int nparts, i;
91 *
92 * pr = blkid_new_probe_from_filename(devname);
93 * if (!pr)
94 * err("%s: faild to open device", devname);
95 *
96 * ls = blkid_probe_get_partitions(pr);
97 * nparts = blkid_partlist_numof_partitions(ls);
98 *
99 * for (i = 0; i < nparts; i++) {
100 * blkid_partition par = blkid_partlist_get_partition(ls, i);
101 * printf("#%d: %llu %llu 0x%x",
102 * blkid_partition_get_partno(par),
103 * blkid_partition_get_start(par),
104 * blkid_partition_get_size(par),
105 * blkid_partition_get_type(par));
106 * }
107 *
108 * blkid_free_probe(pr);
109 *
110 * // don't forget to check return codes in your code!
111 * </programlisting>
112 * </informalexample>
113 */
114
115/*
116 * Chain driver function
117 */
118static int partitions_probe(blkid_probe pr, struct blkid_chain *chn);
119static void partitions_free_data(blkid_probe pr, void *data);
120
121/*
122 * Partitions chain probing functions
123 */
124static const struct blkid_idinfo *idinfos[] =
125{
126 &aix_pt_idinfo,
127 &sgi_pt_idinfo,
128 &sun_pt_idinfo,
129 &dos_pt_idinfo,
130 &gpt_pt_idinfo,
bigbiff7b4c7a62015-01-01 19:44:14 -0500131 &pmbr_pt_idinfo, /* always after GPT */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500132 &mac_pt_idinfo,
133 &ultrix_pt_idinfo,
134 &bsd_pt_idinfo,
135 &unixware_pt_idinfo,
136 &solaris_x86_pt_idinfo,
137 &minix_pt_idinfo
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 */
bigbiff7b4c7a62015-01-01 19:44:14 -0500167 blkid_loff_t offset; /* begin of the partition table (in bytes) */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500168 int nparts; /* number of partitions */
169 blkid_partition parent; /* parent of nested partition table */
170 char id[37]; /* PT identifier (e.g. UUID for GPT) */
171
172 struct list_head t_tabs; /* all tables */
173};
174
175/* exported as opaque type "blkid_partition" */
176struct blkid_struct_partition {
bigbiff7b4c7a62015-01-01 19:44:14 -0500177 blkid_loff_t start; /* begin of the partition (512-bytes sectors) */
178 blkid_loff_t size; /* size of the partitions (512-bytes sectors) */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500179
180 int type; /* partition type */
181 char typestr[37]; /* partition type string (GPT and Mac) */
182
183 unsigned long long flags; /* partition flags / attributes */
184
185 int partno; /* partition number */
186 char uuid[37]; /* UUID (when supported by PT), e.g GPT */
187 unsigned char name[128]; /* Partition in UTF8 name (when supporte by PT), e.g. Mac */
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
204static int blkid_partitions_probe_partition(blkid_probe pr);
205
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{
217 if (!pr)
218 return -1;
219 pr->chains[BLKID_CHAIN_PARTS].enabled = enable;
220 return 0;
221}
222
223/**
224 * blkid_probe_set_partitions_flags:
225 * @pr: prober
226 * @flags: BLKID_PARTS_* flags
227 *
228 * Sets probing flags to the partitions prober. This function is optional.
229 *
230 * Returns: 0 on success, or -1 in case of error.
231 */
232int blkid_probe_set_partitions_flags(blkid_probe pr, int flags)
233{
234 if (!pr)
235 return -1;
236 pr->chains[BLKID_CHAIN_PARTS].flags = flags;
237 return 0;
238}
239
240/**
241 * blkid_probe_reset_partitions_filter:
242 * @pr: prober
243 *
244 * Resets partitions probing filter
245 *
246 * Returns: 0 on success, or -1 in case of error.
247 */
248int blkid_probe_reset_partitions_filter(blkid_probe pr)
249{
250 return __blkid_probe_reset_filter(pr, BLKID_CHAIN_PARTS);
251}
252
253/**
254 * blkid_probe_invert_partitions_filter:
255 * @pr: prober
256 *
257 * Inverts partitions probing filter
258 *
259 * Returns: 0 on success, or -1 in case of error.
260 */
261int blkid_probe_invert_partitions_filter(blkid_probe pr)
262{
263 return __blkid_probe_invert_filter(pr, BLKID_CHAIN_PARTS);
264}
265
266/**
267 * blkid_probe_filter_partitions_type:
268 * @pr: prober
269 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
270 * @names: NULL terminated array of probing function names (e.g. "vfat").
271 *
272 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names
273 *
274 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
275 *
276 * Returns: 0 on success, or -1 in case of error.
277 */
278int blkid_probe_filter_partitions_type(blkid_probe pr, int flag, char *names[])
279{
280 return __blkid_probe_filter_types(pr, BLKID_CHAIN_PARTS, flag, names);
281}
282
283/**
284 * blkid_probe_get_partitions:
285 * @pr: probe
286 *
287 * This is a binary interface for partitions. See also blkid_partlist_*
288 * functions.
289 *
290 * This function is independent on blkid_do_[safe,full]probe() and
291 * blkid_probe_enable_partitions() calls.
292 *
293 * WARNING: the returned object will be overwritten by the next
294 * blkid_probe_get_partitions() call for the same @pr. If you want to
295 * use more blkid_partlist objects in the same time you have to create
296 * more blkid_probe handlers (see blkid_new_probe()).
297 *
298 * Returns: list of partitions, or NULL in case of error.
299 */
300blkid_partlist blkid_probe_get_partitions(blkid_probe pr)
301{
302 return (blkid_partlist) blkid_probe_get_binary_data(pr,
303 &pr->chains[BLKID_CHAIN_PARTS]);
304}
305
306/* for internal usage only */
307blkid_partlist blkid_probe_get_partlist(blkid_probe pr)
308{
309 return (blkid_partlist) pr->chains[BLKID_CHAIN_PARTS].data;
310}
311
312static void blkid_probe_set_partlist(blkid_probe pr, blkid_partlist ls)
313{
314 pr->chains[BLKID_CHAIN_PARTS].data = ls;
315}
316
317static void ref_parttable(blkid_parttable tab)
318{
319 tab->nparts++;
320}
321
322static void unref_parttable(blkid_parttable tab)
323{
324 tab->nparts--;
325
326 if (tab->nparts <= 0) {
327 list_del(&tab->t_tabs);
328 free(tab);
329 }
330}
331
332/* free all allocated parttables */
333static void free_parttables(blkid_partlist ls)
334{
335 if (!ls || !ls->l_tabs.next)
336 return;
337
338 /* remove unassigned partition tables */
339 while (!list_empty(&ls->l_tabs)) {
340 blkid_parttable tab = list_entry(ls->l_tabs.next,
341 struct blkid_struct_parttable, t_tabs);
342 unref_parttable(tab);
343 }
344}
345
346static void reset_partlist(blkid_partlist ls)
347{
348 if (!ls)
349 return;
350
351 free_parttables(ls);
352
353 if (ls->next_partno) {
354 /* already initialized - reset */
355 int tmp_nparts = ls->nparts_max;
356 blkid_partition tmp_parts = ls->parts;
357
358 memset(ls, 0, sizeof(struct blkid_struct_partlist));
359
360 ls->nparts_max = tmp_nparts;
361 ls->parts = tmp_parts;
362 }
363
364 ls->nparts = 0;
365 ls->next_partno = 1;
366 INIT_LIST_HEAD(&ls->l_tabs);
367
bigbiff7b4c7a62015-01-01 19:44:14 -0500368 DBG(LOWPROBE, ul_debug("partlist reset"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500369}
370
371static blkid_partlist partitions_init_data(struct blkid_chain *chn)
372{
373 blkid_partlist ls;
374
375 if (chn->data)
376 ls = (blkid_partlist) chn->data;
377 else {
378 /* allocate the new list of partitions */
379 ls = calloc(1, sizeof(struct blkid_struct_partlist));
380 if (!ls)
381 return NULL;
382 chn->data = (void *) ls;
383 }
384
385 reset_partlist(ls);
386
bigbiff7b4c7a62015-01-01 19:44:14 -0500387 DBG(LOWPROBE, ul_debug("parts: initialized partitions list (%p, size=%d)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500388 ls, ls->nparts_max));
389 return ls;
390}
391
392static void partitions_free_data(blkid_probe pr __attribute__((__unused__)),
393 void *data)
394{
395 blkid_partlist ls = (blkid_partlist) data;
396
397 if (!ls)
398 return;
399
400 free_parttables(ls);
401
402 /* deallocate partitions and partlist */
403 free(ls->parts);
404 free(ls);
405}
406
407blkid_parttable blkid_partlist_new_parttable(blkid_partlist ls,
408 const char *type, blkid_loff_t offset)
409{
410 blkid_parttable tab;
411
412 tab = calloc(1, sizeof(struct blkid_struct_parttable));
413 if (!tab)
414 return NULL;
415 tab->type = type;
416 tab->offset = offset;
417 tab->parent = ls->next_parent;
418
419 INIT_LIST_HEAD(&tab->t_tabs);
420 list_add_tail(&tab->t_tabs, &ls->l_tabs);
421
bigbiff7b4c7a62015-01-01 19:44:14 -0500422 DBG(LOWPROBE, ul_debug("parts: create a new partition table "
423 "(%p, type=%s, offset=%"PRId64")", tab, type, offset));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500424 return tab;
425}
426
427static blkid_partition new_partition(blkid_partlist ls, blkid_parttable tab)
428{
429 blkid_partition par;
430
431 if (ls->nparts + 1 > ls->nparts_max) {
432 /* Linux kernel has DISK_MAX_PARTS=256, but it's too much for
433 * generic Linux machine -- let start with 32 partititions.
434 */
bigbiff7b4c7a62015-01-01 19:44:14 -0500435 void *tmp = realloc(ls->parts, (ls->nparts_max + 32) *
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500436 sizeof(struct blkid_struct_partition));
bigbiff7b4c7a62015-01-01 19:44:14 -0500437 if (!tmp)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500438 return NULL;
bigbiff7b4c7a62015-01-01 19:44:14 -0500439 ls->parts = tmp;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500440 ls->nparts_max += 32;
441 }
442
443 par = &ls->parts[ls->nparts++];
444 memset(par, 0, sizeof(struct blkid_struct_partition));
445
446 ref_parttable(tab);
447 par->tab = tab;
448 par->partno = blkid_partlist_increment_partno(ls);
449
450 return par;
451}
452
453blkid_partition blkid_partlist_add_partition(blkid_partlist ls,
454 blkid_parttable tab,
455 blkid_loff_t start, blkid_loff_t size)
456{
457 blkid_partition par = new_partition(ls, tab);
458
459 if (!par)
460 return NULL;
461
462 par->start = start;
463 par->size = size;
464
bigbiff7b4c7a62015-01-01 19:44:14 -0500465 DBG(LOWPROBE, ul_debug("parts: add partition (%p start=%"
466 PRId64 ", size=%" PRId64 ", table=%p)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500467 par, par->start, par->size, tab));
468 return par;
469}
470
471/* allows to modify used partitions numbers (for example for logical partitions) */
472int blkid_partlist_set_partno(blkid_partlist ls, int partno)
473{
474 if (!ls)
475 return -1;
476 ls->next_partno = partno;
477 return 0;
478}
479
480int blkid_partlist_increment_partno(blkid_partlist ls)
481{
482 return ls ? ls->next_partno++ : -1;
483}
484
485/* allows to set "parent" for the next nested partition */
486int blkid_partlist_set_parent(blkid_partlist ls, blkid_partition par)
487{
488 if (!ls)
489 return -1;
490 ls->next_parent = par;
491 return 0;
492}
493
494blkid_partition blkid_partlist_get_parent(blkid_partlist ls)
495{
496 if (!ls)
497 return NULL;
498 return ls->next_parent;
499}
500
501int blkid_partitions_need_typeonly(blkid_probe pr)
502{
503 struct blkid_chain *chn = blkid_probe_get_chain(pr);
504
505 return chn && chn->data && chn->binary ? FALSE : TRUE;
506}
507
508/* get private chain flags */
509int blkid_partitions_get_flags(blkid_probe pr)
510{
511 struct blkid_chain *chn = blkid_probe_get_chain(pr);
512
513 return chn ? chn->flags : 0;
514}
515
516/* check if @start and @size are within @par partition */
517int blkid_is_nested_dimension(blkid_partition par,
518 blkid_loff_t start, blkid_loff_t size)
519{
520 blkid_loff_t pstart;
521 blkid_loff_t psize;
522
523 if (!par)
524 return 0;
525
526 pstart = blkid_partition_get_start(par);
527 psize = blkid_partition_get_size(par);
528
529 if (start < pstart || start + size > pstart + psize)
530 return 0;
531
532 return 1;
533}
534
535static int idinfo_probe(blkid_probe pr, const struct blkid_idinfo *id,
536 struct blkid_chain *chn)
537{
538 const struct blkid_idmag *mag = NULL;
539 blkid_loff_t off;
bigbiff7b4c7a62015-01-01 19:44:14 -0500540 int rc = BLKID_PROBE_NONE; /* default is nothing */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500541
542 if (pr->size <= 0 || (id->minsz && id->minsz > pr->size))
543 goto nothing; /* the device is too small */
bigbiff7b4c7a62015-01-01 19:44:14 -0500544 if (pr->flags & BLKID_FL_NOSCAN_DEV)
545 goto nothing;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500546
bigbiff7b4c7a62015-01-01 19:44:14 -0500547 rc = blkid_probe_get_idmag(pr, id, &off, &mag);
548 if (rc != BLKID_PROBE_OK)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500549 goto nothing;
550
551 /* final check by probing function */
552 if (id->probefunc) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500553 DBG(LOWPROBE, ul_debug(
554 "%s: ---> call probefunc()", id->name));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500555 rc = id->probefunc(pr, mag);
bigbiff7b4c7a62015-01-01 19:44:14 -0500556 if (rc < 0) {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500557 /* reset after error */
558 reset_partlist(blkid_probe_get_partlist(pr));
559 if (chn && !chn->binary)
560 blkid_probe_chain_reset_vals(pr, chn);
bigbiff7b4c7a62015-01-01 19:44:14 -0500561 DBG(LOWPROBE, ul_debug("%s probefunc failed, rc %d",
562 id->name, rc));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500563 }
bigbiff7b4c7a62015-01-01 19:44:14 -0500564 if (rc == BLKID_PROBE_OK && mag && chn && !chn->binary)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500565 rc = blkid_probe_set_magic(pr, off, mag->len,
566 (unsigned char *) mag->magic);
567
bigbiff7b4c7a62015-01-01 19:44:14 -0500568 DBG(LOWPROBE, ul_debug("%s: <--- (rc = %d)", id->name, rc));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500569 }
570
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500571 return rc;
bigbiff7b4c7a62015-01-01 19:44:14 -0500572
573nothing:
574 return BLKID_PROBE_NONE;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500575}
576
577/*
578 * The blkid_do_probe() backend.
579 */
580static int partitions_probe(blkid_probe pr, struct blkid_chain *chn)
581{
bigbiff7b4c7a62015-01-01 19:44:14 -0500582 int rc = BLKID_PROBE_NONE;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500583 size_t i;
584
585 if (!pr || chn->idx < -1)
bigbiff7b4c7a62015-01-01 19:44:14 -0500586 return -EINVAL;
587
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500588 blkid_probe_chain_reset_vals(pr, chn);
589
bigbiff7b4c7a62015-01-01 19:44:14 -0500590 if (pr->flags & BLKID_FL_NOSCAN_DEV)
591 return BLKID_PROBE_NONE;
592
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500593 if (chn->binary)
594 partitions_init_data(chn);
595
596 if (!pr->wipe_size && (pr->prob_flags & BLKID_PROBE_FL_IGNORE_PT))
597 goto details_only;
598
bigbiff7b4c7a62015-01-01 19:44:14 -0500599 DBG(LOWPROBE, ul_debug("--> starting probing loop [PARTS idx=%d]",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500600 chn->idx));
601
602 i = chn->idx < 0 ? 0 : chn->idx + 1U;
603
604 for ( ; i < ARRAY_SIZE(idinfos); i++) {
605 const char *name;
606
607 chn->idx = i;
608
609 /* apply filter */
610 if (chn->fltr && blkid_bmp_get_item(chn->fltr, i))
611 continue;
612
613 /* apply checks from idinfo */
bigbiff7b4c7a62015-01-01 19:44:14 -0500614 rc = idinfo_probe(pr, idinfos[i], chn);
615 if (rc < 0)
616 break;
617 if (rc != BLKID_PROBE_OK)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500618 continue;
619
620 name = idinfos[i]->name;
621
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500622 if (!chn->binary)
bigbiff7b4c7a62015-01-01 19:44:14 -0500623 /*
624 * Non-binary interface, set generic variables. Note
625 * that the another variables could be set in prober
626 * functions.
627 */
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500628 blkid_probe_set_value(pr, "PTTYPE",
629 (unsigned char *) name,
630 strlen(name) + 1);
bigbiff7b4c7a62015-01-01 19:44:14 -0500631
632 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [PARTS idx=%d]",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500633 name, chn->idx));
bigbiff7b4c7a62015-01-01 19:44:14 -0500634 rc = BLKID_PROBE_OK;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500635 break;
636 }
637
bigbiff7b4c7a62015-01-01 19:44:14 -0500638 if (rc != BLKID_PROBE_OK) {
639 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [PARTS idx=%d]",
640 rc, chn->idx));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500641 }
642
643details_only:
644 /*
645 * Gather PART_ENTRY_* values if the current device is a partition.
646 */
bigbiff7b4c7a62015-01-01 19:44:14 -0500647 if ((rc == BLKID_PROBE_OK || rc == BLKID_PROBE_NONE) && !chn->binary &&
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500648 (blkid_partitions_get_flags(pr) & BLKID_PARTS_ENTRY_DETAILS)) {
649
bigbiff7b4c7a62015-01-01 19:44:14 -0500650 int xrc = blkid_partitions_probe_partition(pr);
651
652 /* partition entry probing is optional, and "not-found" from
653 * this sub-probing must not to overwrite previous success. */
654 if (xrc < 0)
655 rc = xrc; /* always propagate errors */
656 else if (rc == BLKID_PROBE_NONE)
657 rc = xrc;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500658 }
659
bigbiff7b4c7a62015-01-01 19:44:14 -0500660 DBG(LOWPROBE, ul_debug("partitions probe done [rc=%d]", rc));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500661 return rc;
662}
663
664/* Probe for nested partition table within the parental partition */
665int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent,
666 const struct blkid_idinfo *id)
667{
668 blkid_probe prc;
bigbiff7b4c7a62015-01-01 19:44:14 -0500669 int rc;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500670 blkid_partlist ls;
671 blkid_loff_t sz, off;
672
bigbiff7b4c7a62015-01-01 19:44:14 -0500673 DBG(LOWPROBE, ul_debug(
674 "parts: ----> %s subprobe requested (parent=%p)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500675 id->name, parent));
676
677 if (!pr || !parent || !parent->size)
bigbiff7b4c7a62015-01-01 19:44:14 -0500678 return -EINVAL;
679 if (pr->flags & BLKID_FL_NOSCAN_DEV)
680 return BLKID_PROBE_NONE;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500681
682 /* range defined by parent */
683 sz = ((blkid_loff_t) parent->size) << 9;
684 off = ((blkid_loff_t) parent->start) << 9;
685
686 if (off < pr->off || pr->off + pr->size < off + sz) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500687 DBG(LOWPROBE, ul_debug(
688 "ERROR: parts: <---- '%s' subprobe: overflow detected.",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500689 id->name));
bigbiff7b4c7a62015-01-01 19:44:14 -0500690 return -ENOSPC;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500691 }
692
693 /* create private prober */
694 prc = blkid_clone_probe(pr);
695 if (!prc)
bigbiff7b4c7a62015-01-01 19:44:14 -0500696 return -ENOMEM;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500697
698 blkid_probe_set_dimension(prc, off, sz);
699
700 /* clone is always with reset chain, fix it */
701 prc->cur_chain = blkid_probe_get_chain(pr);
702
703 /*
704 * Set 'parent' to the current list of the partitions and use the list
705 * in cloned prober (so the cloned prober will extend the current list
706 * of partitions rather than create a new).
707 */
708 ls = blkid_probe_get_partlist(pr);
709 blkid_partlist_set_parent(ls, parent);
710
711 blkid_probe_set_partlist(prc, ls);
712
713 rc = idinfo_probe(prc, id, blkid_probe_get_chain(pr));
714
715 blkid_probe_set_partlist(prc, NULL);
716 blkid_partlist_set_parent(ls, NULL);
717
718 blkid_free_probe(prc); /* free cloned prober */
719
bigbiff7b4c7a62015-01-01 19:44:14 -0500720 DBG(LOWPROBE, ul_debug(
721 "parts: <---- %s subprobe done (parent=%p, rc=%d)",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500722 id->name, parent, rc));
723
724 return rc;
725}
726
727static int blkid_partitions_probe_partition(blkid_probe pr)
728{
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500729 blkid_probe disk_pr = NULL;
730 blkid_partlist ls;
731 blkid_partition par;
732 dev_t devno;
733
bigbiff7b4c7a62015-01-01 19:44:14 -0500734 DBG(LOWPROBE, ul_debug("parts: start probing for partition entry"));
735
736 if (pr->flags & BLKID_FL_NOSCAN_DEV)
737 goto nothing;
738
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500739 devno = blkid_probe_get_devno(pr);
740 if (!devno)
741 goto nothing;
742
743 disk_pr = blkid_probe_get_wholedisk_probe(pr);
744 if (!disk_pr)
745 goto nothing;
746
747 /* parse PT */
748 ls = blkid_probe_get_partitions(disk_pr);
749 if (!ls)
750 goto nothing;
751
752 par = blkid_partlist_devno_to_partition(ls, devno);
bigbiff7b4c7a62015-01-01 19:44:14 -0500753 if (!par)
754 goto nothing;
755 else {
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500756 const char *v;
757 blkid_parttable tab = blkid_partition_get_table(par);
758 dev_t disk = blkid_probe_get_devno(disk_pr);
759
760 if (tab) {
761 v = blkid_parttable_get_type(tab);
762 if (v)
763 blkid_probe_set_value(pr, "PART_ENTRY_SCHEME",
764 (unsigned char *) v, strlen(v) + 1);
765 }
766
767 v = blkid_partition_get_name(par);
768 if (v)
769 blkid_probe_set_value(pr, "PART_ENTRY_NAME",
770 (unsigned char *) v, strlen(v) + 1);
771
772 v = blkid_partition_get_uuid(par);
773 if (v)
774 blkid_probe_set_value(pr, "PART_ENTRY_UUID",
775 (unsigned char *) v, strlen(v) + 1);
776
777 /* type */
778 v = blkid_partition_get_type_string(par);
779 if (v)
780 blkid_probe_set_value(pr, "PART_ENTRY_TYPE",
781 (unsigned char *) v, strlen(v) + 1);
782 else
783 blkid_probe_sprintf_value(pr, "PART_ENTRY_TYPE",
784 "0x%x", blkid_partition_get_type(par));
785
786 if (blkid_partition_get_flags(par))
787 blkid_probe_sprintf_value(pr, "PART_ENTRY_FLAGS",
788 "0x%llx", blkid_partition_get_flags(par));
789
790 blkid_probe_sprintf_value(pr, "PART_ENTRY_NUMBER",
791 "%d", blkid_partition_get_partno(par));
792
793 blkid_probe_sprintf_value(pr, "PART_ENTRY_OFFSET", "%jd",
794 blkid_partition_get_start(par));
795 blkid_probe_sprintf_value(pr, "PART_ENTRY_SIZE", "%jd",
796 blkid_partition_get_size(par));
797
798 blkid_probe_sprintf_value(pr, "PART_ENTRY_DISK", "%u:%u",
799 major(disk), minor(disk));
800 }
bigbiff7b4c7a62015-01-01 19:44:14 -0500801
802 DBG(LOWPROBE, ul_debug("parts: end probing for partition entry [success]"));
803 return BLKID_PROBE_OK;
804
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500805nothing:
bigbiff7b4c7a62015-01-01 19:44:14 -0500806 DBG(LOWPROBE, ul_debug("parts: end probing for partition entry [nothing]"));
807 return BLKID_PROBE_NONE;
808
809
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500810}
811
812/*
813 * Returns 1 if the device is whole-disk and the area specified by @offset and
814 * @size is covered by any partition.
815 */
816int blkid_probe_is_covered_by_pt(blkid_probe pr,
817 blkid_loff_t offset, blkid_loff_t size)
818{
bigbiff7b4c7a62015-01-01 19:44:14 -0500819 blkid_probe prc = NULL;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500820 blkid_partlist ls = NULL;
821 blkid_loff_t start, end;
822 int nparts, i, rc = 0;
823
bigbiff7b4c7a62015-01-01 19:44:14 -0500824 DBG(LOWPROBE, ul_debug(
825 "=> checking if off=%jd size=%jd covered by PT",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500826 offset, size));
827
bigbiff7b4c7a62015-01-01 19:44:14 -0500828 if (pr->flags & BLKID_FL_NOSCAN_DEV)
829 goto done;
830
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500831 prc = blkid_clone_probe(pr);
832 if (!prc)
833 goto done;
834
835 ls = blkid_probe_get_partitions(prc);
836 if (!ls)
837 goto done;
838
839 nparts = blkid_partlist_numof_partitions(ls);
840 if (!nparts)
841 goto done;
842
843 end = (offset + size) >> 9;
844 start = offset >> 9;
845
846 /* check if the partition table fits into the device */
847 for (i = 0; i < nparts; i++) {
848 blkid_partition par = &ls->parts[i];
849
850 if (par->start + par->size > (pr->size >> 9)) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500851 DBG(LOWPROBE, ul_debug("partition #%d overflows "
852 "device (off=%" PRId64 " size=%" PRId64 ")",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500853 par->partno, par->start, par->size));
854 goto done;
855 }
856 }
857
858 /* check if the requested area is covered by PT */
859 for (i = 0; i < nparts; i++) {
860 blkid_partition par = &ls->parts[i];
861
862 if (start >= par->start && end <= par->start + par->size) {
863 rc = 1;
864 break;
865 }
866 }
867done:
868 blkid_free_probe(prc);
869
bigbiff7b4c7a62015-01-01 19:44:14 -0500870 DBG(LOWPROBE, ul_debug("<= %s covered by PT", rc ? "IS" : "NOT"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500871 return rc;
872}
873
874/**
875 * blkid_known_pttype:
876 * @pttype: partiton name
877 *
878 * Returns: 1 for known or 0 for unknown partition type.
879 */
880int blkid_known_pttype(const char *pttype)
881{
882 size_t i;
883
884 if (!pttype)
885 return 0;
886
887 for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
888 const struct blkid_idinfo *id = idinfos[i];
889 if (strcmp(id->name, pttype) == 0)
890 return 1;
891 }
892 return 0;
893}
894
895/**
896 * blkid_partlist_numof_partitions:
897 * @ls: partitions list
898 *
899 * Returns: number of partitions in the list or -1 in case of error.
900 */
901int blkid_partlist_numof_partitions(blkid_partlist ls)
902{
903 return ls ? ls->nparts : -1;
904}
905
906/**
907 * blkid_partlist_get_table:
908 * @ls: partitions list
909 *
910 * Returns: top-level partition table or NULL of there is not a partition table
911 * on the device.
912 */
913blkid_parttable blkid_partlist_get_table(blkid_partlist ls)
914{
915 if (!ls || list_empty(&ls->l_tabs))
916 return NULL;
917
918 return list_entry(ls->l_tabs.next,
919 struct blkid_struct_parttable, t_tabs);
920}
921
922
923/**
924 * blkid_partlist_get_partition:
925 * @ls: partitions list
926 * @n: partition number in range 0..N, where 'N' is blkid_partlist_numof_partitions().
927 *
928 * It's possible that the list of partitions is *empty*, but there is a valid
929 * partition table on the disk. This happen when on-disk details about
930 * partitions are unknown or the partition table is empty.
931 *
932 * See also blkid_partlist_get_table().
933 *
934 * Returns: partition object or NULL in case or error.
935 */
936blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n)
937{
938 if (!ls || n < 0 || n >= ls->nparts)
939 return NULL;
940
941 return &ls->parts[n];
942}
943
944/**
bigbiff7b4c7a62015-01-01 19:44:14 -0500945 * blkid_partlist_get_partition_by_partno
946 * @ls: partitions list
947 * @n: the partition number (e.g. 'N' from sda'N')
948 *
949 * This does not assume any order of the input blkid_partlist. And correctly
950 * handles "out of order" partition tables. partition N is located after
951 * partition N+1 on the disk.
952 *
953 * Returns: partition object or NULL in case or error.
954 */
955blkid_partition blkid_partlist_get_partition_by_partno(blkid_partlist ls, int n)
956{
957 int i, nparts;
958 blkid_partition par;
959
960 if (!ls)
961 return NULL;
962
963 nparts = blkid_partlist_numof_partitions(ls);
964 for (i = 0; i < nparts; i++) {
965 par = blkid_partlist_get_partition(ls, i);
966 if (n == blkid_partition_get_partno(par))
967 return par;
968 }
969 return NULL;
970}
971
972
973/**
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500974 * blkid_partlist_devno_to_partition:
975 * @ls: partitions list
976 * @devno: requested partition
977 *
978 * This function tries to get start and size for @devno from sysfs and
979 * returns a partition from @ls which matches with the values from sysfs.
980 *
981 * This function is necessary when you want to make a relation between an entry
982 * in the partition table (@ls) and block devices in your system.
983 *
984 * Returns: partition object or NULL in case or error.
985 */
986blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno)
987{
988 struct sysfs_cxt sysfs;
989 uint64_t start, size;
990 int i, rc, partno = 0;
991
992 if (!ls)
993 return NULL;
994
bigbiff7b4c7a62015-01-01 19:44:14 -0500995 DBG(LOWPROBE, ul_debug("triyng to convert devno 0x%llx to partition",
bigbiff bigbiffe60683a2013-02-22 20:55:50 -0500996 (long long) devno));
997
998 if (sysfs_init(&sysfs, devno, NULL)) {
bigbiff7b4c7a62015-01-01 19:44:14 -0500999 DBG(LOWPROBE, ul_debug("failed t init sysfs context"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001000 return NULL;
1001 }
1002 rc = sysfs_read_u64(&sysfs, "size", &size);
1003 if (!rc) {
1004 rc = sysfs_read_u64(&sysfs, "start", &start);
1005 if (rc) {
1006 /* try to get partition number from DM uuid.
1007 */
1008 char *uuid = sysfs_strdup(&sysfs, "dm/uuid");
1009 char *tmp = uuid;
1010 char *prefix = uuid ? strsep(&tmp, "-") : NULL;
1011
1012 if (prefix && strncasecmp(prefix, "part", 4) == 0) {
1013 char *end = NULL;
1014
1015 partno = strtol(prefix + 4, &end, 10);
1016 if (prefix == end || (end && *end))
1017 partno = 0;
1018 else
1019 rc = 0; /* success */
1020 }
1021 free(uuid);
1022 }
1023 }
1024
1025 sysfs_deinit(&sysfs);
1026
1027 if (rc)
1028 return NULL;
1029
1030 if (partno) {
bigbiff7b4c7a62015-01-01 19:44:14 -05001031 DBG(LOWPROBE, ul_debug("mapped by DM, using partno %d", partno));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001032
1033 /*
1034 * Partition mapped by kpartx does not provide "start" offset
1035 * in /sys, but if we know partno and size of the partition
1036 * that we can probably make the releation bettween the device
1037 * and an entry in partition table.
1038 */
1039 for (i = 0; i < ls->nparts; i++) {
1040 blkid_partition par = &ls->parts[i];
1041
1042 if (partno != blkid_partition_get_partno(par))
1043 continue;
1044
1045 if ((blkid_loff_t) size == blkid_partition_get_size(par) ||
1046 (blkid_partition_is_extended(par) && size <= 1024))
1047 return par;
1048
1049 }
1050 return NULL;
1051 }
1052
bigbiff7b4c7a62015-01-01 19:44:14 -05001053 DBG(LOWPROBE, ul_debug("searching by offset/size"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001054
1055 for (i = 0; i < ls->nparts; i++) {
1056 blkid_partition par = &ls->parts[i];
1057
1058 if (blkid_partition_get_start(par) == (blkid_loff_t) start &&
1059 blkid_partition_get_size(par) == (blkid_loff_t) size)
1060 return par;
1061
1062 /* exception for extended dos partitions */
1063 if (blkid_partition_get_start(par) == (blkid_loff_t) start &&
1064 blkid_partition_is_extended(par) && size <= 1024)
1065 return par;
1066
1067 }
1068
bigbiff7b4c7a62015-01-01 19:44:14 -05001069 DBG(LOWPROBE, ul_debug("not found partition for device"));
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001070 return NULL;
1071}
1072
bigbiff7b4c7a62015-01-01 19:44:14 -05001073
1074int blkid_parttable_set_uuid(blkid_parttable tab, const unsigned char *id)
1075{
1076 if (!tab)
1077 return -1;
1078
1079 blkid_unparse_uuid(id, tab->id, sizeof(tab->id));
1080 return 0;
1081}
1082
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001083int blkid_parttable_set_id(blkid_parttable tab, const unsigned char *id)
1084{
1085 if (!tab)
1086 return -1;
1087
bigbiff7b4c7a62015-01-01 19:44:14 -05001088 strncpy(tab->id, (const char *) id, sizeof(tab->id));
1089 return 0;
1090}
1091
1092/* set PTUUID variable for non-binary API */
1093int blkid_partitions_set_ptuuid(blkid_probe pr, unsigned char *uuid)
1094{
1095 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1096 struct blkid_prval *v;
1097
1098 if (chn->binary || blkid_uuid_is_empty(uuid, 16))
1099 return 0;
1100
1101 v = blkid_probe_assign_value(pr, "PTUUID");
1102
1103 blkid_unparse_uuid(uuid, (char *) v->data, sizeof(v->data));
1104 v->len = 37;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001105
1106 return 0;
1107}
1108
bigbiff7b4c7a62015-01-01 19:44:14 -05001109/* set PTUUID variable for non-binary API for tables where
1110 * the ID is just a string */
1111int blkid_partitions_strcpy_ptuuid(blkid_probe pr, char *str)
1112{
1113 struct blkid_chain *chn = blkid_probe_get_chain(pr);
1114 struct blkid_prval *v;
1115 size_t len;
1116
1117 if (chn->binary || !str || !*str)
1118 return 0;
1119
1120 len = strlen((char *) str);
1121 if (len > BLKID_PROBVAL_BUFSIZ)
1122 len = BLKID_PROBVAL_BUFSIZ;
1123
1124 v = blkid_probe_assign_value(pr, "PTUUID");
1125 if (v) {
1126 if (len == BLKID_PROBVAL_BUFSIZ)
1127 len--; /* make a space for \0 */
1128
1129 memcpy((char *) v->data, str, len);
1130 v->data[len] = '\0';
1131 v->len = len + 1;
1132 return 0;
1133 }
1134 return -1;
1135}
1136
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001137/**
1138 * blkid_parttable_get_id:
1139 * @tab: partition table
1140 *
1141 * The ID is GPT disk UUID or DOS disk ID (in hex format).
1142 *
1143 * Returns: partition table ID (for example GPT disk UUID) or NULL
1144 */
1145const char *blkid_parttable_get_id(blkid_parttable tab)
1146{
bigbiff7b4c7a62015-01-01 19:44:14 -05001147 return tab && *tab->id ? tab->id : NULL;
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001148}
1149
1150
1151int blkid_partition_set_type(blkid_partition par, int type)
1152{
1153 if (!par)
1154 return -1;
1155 par->type = type;
1156 return 0;
1157}
1158
1159/**
1160 * blkid_parttable_get_type:
1161 * @tab: partition table
1162 *
1163 * Returns: partition table type (type name, e.g. "dos", "gpt", ...)
1164 */
1165const char *blkid_parttable_get_type(blkid_parttable tab)
1166{
1167 return tab ? tab->type : NULL;
1168}
1169
1170/**
1171 * blkid_parttable_get_parent:
1172 * @tab: partition table
1173 *
1174 * Returns: parent for nexted partitition tables or NULL.
1175 */
1176blkid_partition blkid_parttable_get_parent(blkid_parttable tab)
1177{
1178 return tab ? tab->parent : NULL;
1179}
1180
1181/**
1182 * blkid_parttable_get_offset:
1183 * @tab: partition table
1184 *
1185 * Note the position is relative to begin of the device as defined by
1186 * blkid_probe_set_device() for primary partition table, and relative
1187 * to parental partition for nested patition tables.
1188 *
1189 * <informalexample>
1190 * <programlisting>
1191 * off_t offset;
1192 * blkid_partition parent = blkid_parttable_get_parent(tab);
1193 *
1194 * offset = blkid_parttable_get_offset(tab);
1195 *
1196 * if (parent)
1197 * / * 'tab' is nested partition table * /
1198 * offset += blkid_partition_get_start(parent);
1199 * </programlisting>
1200 * </informalexample>
1201
1202 * Returns: position (in bytes) of the partition table or -1 in case of error.
1203 *
1204 */
1205blkid_loff_t blkid_parttable_get_offset(blkid_parttable tab)
1206{
1207 return tab ? tab->offset : -1;
1208}
1209
1210/**
1211 * blkid_partition_get_table:
1212 * @par: partition
1213 *
1214 * The "parttable" describes partition table. The table is usually the same for
1215 * all partitions -- except nested partition tables.
1216 *
1217 * For example bsd, solaris, etc. use a nested partition table within
1218 * standard primary dos partition:
1219 *
1220 * <informalexample>
1221 * <programlisting>
1222 *
1223 * -- dos partition table
1224 * 0: sda1 dos primary partition
1225 * 1: sda2 dos primary partition
1226 * -- bsd partition table (with in sda2)
1227 * 2: sda5 bds partition
1228 * 3: sda6 bds partition
1229 *
1230 * </programlisting>
1231 * </informalexample>
1232 *
1233 * The library does not to use a separate partition table object for dos logical
1234 * partitions (partitions within extended partition). It's possible to
1235 * differentiate between logical, extended and primary partitions by
1236 *
1237 * blkid_partition_is_{extended,primary,logical}().
1238 *
1239 * Returns: partition table object or NULL in case of error.
1240 */
1241blkid_parttable blkid_partition_get_table(blkid_partition par)
1242{
1243 return par ? par->tab : NULL;
1244}
1245
1246static int partition_get_logical_type(blkid_partition par)
1247{
1248 blkid_parttable tab;
1249
1250 if (!par)
1251 return -1;
1252
1253 tab = blkid_partition_get_table(par);
1254 if (!tab || !tab->type)
1255 return -1;
1256
1257 if (tab->parent)
1258 return 'L'; /* report nested partitions as logical */
1259
1260 if (!strcmp(tab->type, "dos")) {
1261 if (par->partno > 4)
1262 return 'L'; /* logical */
1263
bigbiff7b4c7a62015-01-01 19:44:14 -05001264 if(par->type == MBR_DOS_EXTENDED_PARTITION ||
1265 par->type == MBR_W95_EXTENDED_PARTITION ||
1266 par->type == MBR_LINUX_EXTENDED_PARTITION)
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001267 return 'E';
1268 }
1269 return 'P';
1270}
1271
1272/**
1273 * blkid_partition_is_primary:
1274 * @par: partition
1275 *
1276 * Note, this function returns FALSE for DOS extended partitions and
1277 * all partitions in nested partition tables.
1278 *
1279 * Returns: 1 if the partitions is primary partition or 0 if not.
1280 */
1281int blkid_partition_is_primary(blkid_partition par)
1282{
1283 return partition_get_logical_type(par) == 'P' ? TRUE : FALSE;
1284}
1285
1286/**
1287 * blkid_partition_is_extended:
1288 * @par: partition
1289 *
1290 * Returns: 1 if the partitions is extended (dos, windows or linux)
1291 * partition or 0 if not.
1292 */
1293int blkid_partition_is_extended(blkid_partition par)
1294{
1295 return partition_get_logical_type(par) == 'E' ? TRUE : FALSE;
1296}
1297
1298/**
1299 * blkid_partition_is_logical:
1300 * @par: partition
1301 *
1302 * Note that this function returns TRUE for all partitions in all
1303 * nested partition tables (e.g. BSD labels).
1304 *
1305 * Returns: 1 if the partitions is logical partition or 0 if not.
1306 */
1307int blkid_partition_is_logical(blkid_partition par)
1308{
1309 return partition_get_logical_type(par) == 'L' ? TRUE : FALSE;
1310}
1311
1312static void set_string(unsigned char *item, size_t max,
1313 const unsigned char *data, size_t len)
1314{
1315 if (len >= max)
1316 len = max - 1;
1317
1318 memcpy(item, data, len);
1319 item[len] = '\0';
1320
1321 blkid_rtrim_whitespace(item);
1322}
1323
1324int blkid_partition_set_name(blkid_partition par,
1325 const unsigned char *name, size_t len)
1326{
1327 if (!par)
1328 return -1;
1329
1330 set_string(par->name, sizeof(par->name), name, len);
1331 return 0;
1332}
1333
1334int blkid_partition_set_utf8name(blkid_partition par, const unsigned char *name,
1335 size_t len, int enc)
1336{
1337 if (!par)
1338 return -1;
1339
1340 blkid_encode_to_utf8(enc, par->name, sizeof(par->name), name, len);
1341 blkid_rtrim_whitespace(par->name);
1342 return 0;
1343}
1344
1345int blkid_partition_set_uuid(blkid_partition par, const unsigned char *uuid)
1346{
1347 if (!par)
1348 return -1;
1349
1350 blkid_unparse_uuid(uuid, par->uuid, sizeof(par->uuid));
1351 return 0;
1352}
1353
bigbiff7b4c7a62015-01-01 19:44:14 -05001354int blkid_partition_gen_uuid(blkid_partition par)
1355{
1356 if (!par || !par->tab || !*par->tab->id)
1357 return -1;
1358
1359 snprintf(par->uuid, sizeof(par->uuid), "%s-%02x",
1360 par->tab->id, par->partno);
1361 return 0;
1362}
1363
bigbiff bigbiffe60683a2013-02-22 20:55:50 -05001364/**
1365 * blkid_partition_get_name:
1366 * @par: partition
1367 *
1368 * Returns: partition name string if supported by PT (e.g. Mac) or NULL.
1369 */
1370const char *blkid_partition_get_name(blkid_partition par)
1371{
1372 return par && *par->name ? (char *) par->name : NULL;
1373}
1374
1375/**
1376 * blkid_partition_get_uuid:
1377 * @par: partition
1378 *
1379 * Returns: partition UUID string if supported by PT (e.g. GPT) or NULL.
1380 */
1381const char *blkid_partition_get_uuid(blkid_partition par)
1382{
1383 return par && *par->uuid ? par->uuid : NULL;
1384}
1385
1386/**
1387 * blkid_partition_get_partno:
1388 * @par: partition
1389 *
1390 * Returns: proposed partitin number (e.g. 'N' from sda'N') or -1 in case of
1391 * error. Note that the number is generate by library independenly on your OS.
1392 */
1393int blkid_partition_get_partno(blkid_partition par)
1394{
1395 return par ? par->partno : -1;
1396}
1397
1398/**
1399 * blkid_partition_get_start:
1400 * @par: partition
1401 *
1402 * Be careful if you _not_ probe whole disk:
1403 *
1404 * 1) the offset is usully relative to begin of the disk -- but if you probe a
1405 * fragment of the disk only -- then the offset could be still relative to
1406 * the begin of the disk rather that relative to the fragment.
1407 *
1408 * 2) the offset for nested partitions could be releative to parent (e.g. Solaris)
1409 * _or_ relative to the begin of the whole disk (e.g. bsd).
1410 *
1411 * You don't have to care about such details if you proble whole disk. In such
1412 * a case libblkid always returns the offset relative to the begin of the disk.
1413 *
1414 * Returns: start of the partition (in 512-sectors).
1415 */
1416blkid_loff_t blkid_partition_get_start(blkid_partition par)
1417{
1418 return par ? par->start : -1;
1419}
1420
1421/**
1422 * blkid_partition_get_size:
1423 * @par: partition
1424 *
1425 * WARNING: be very careful when you work with MS-DOS extended partitions. The
1426 * library always returns full size of the partition. If you want add
1427 * the partition to the Linux system (BLKPG_ADD_PARTITION ioctl) you
1428 * need to reduce the size of the partition to 1 or 2 blocks. The
1429 * rest of the partition has to be unaccessible for mkfs or mkswap
1430 * programs, we need a small space for boot loaders only.
1431 *
1432 * For some unknown reason this (safe) practice is not to used for
1433 * nested BSD, Solaris, ..., partition tables in Linux kernel.
1434 *
1435 * Returns: size of the partition (in 512-sectors).
1436 */
1437blkid_loff_t blkid_partition_get_size(blkid_partition par)
1438{
1439 return par ? par->size : -1;
1440}
1441
1442/**
1443 * blkid_partition_get_type:
1444 * @par: partition
1445 *
1446 * Returns: partition type.
1447 */
1448int blkid_partition_get_type(blkid_partition par)
1449{
1450 return par->type;
1451}
1452
1453/* Sets partition 'type' for PT where the type is defined by string rather
1454 * than by number
1455 */
1456int blkid_partition_set_type_string(blkid_partition par,
1457 const unsigned char *type, size_t len)
1458{
1459 if (!par)
1460 return -1;
1461
1462 set_string((unsigned char *) par->typestr,
1463 sizeof(par->typestr), type, len);
1464 return 0;
1465}
1466
1467/* Sets partition 'type' for PT where the type is defined by UUIDrather
1468 * than by number
1469 */
1470int blkid_partition_set_type_uuid(blkid_partition par, const unsigned char *uuid)
1471{
1472 if (!par)
1473 return -1;
1474
1475 blkid_unparse_uuid(uuid, par->typestr, sizeof(par->typestr));
1476 return 0;
1477}
1478
1479/**
1480 * blkid_partition_get_type_string:
1481 * @par: partition
1482 *
1483 * The type string is supported by a small subset of partition tables (e.g Mac
1484 * and EFI GPT). Note that GPT uses type UUID and this function returns this
1485 * UUID as string.
1486 *
1487 * Returns: partition type string or NULL.
1488 */
1489const char *blkid_partition_get_type_string(blkid_partition par)
1490{
1491 return par && *par->typestr ? par->typestr : NULL;
1492}
1493
1494
1495int blkid_partition_set_flags(blkid_partition par, unsigned long long flags)
1496{
1497 if (!par)
1498 return -1;
1499 par->flags = flags;
1500 return 0;
1501}
1502
1503/**
1504 * blkid_partition_get_flags
1505 * @par: partition
1506 *
1507 * Returns: partition flags (or attributes for gpt).
1508 */
1509unsigned long long blkid_partition_get_flags(blkid_partition par)
1510{
1511 return par->flags;
1512}
1513