~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/partitions/partitions.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

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