~pr0gg3d/ubuntu/oneiric/util-linux/bug-805886

« back to all changes in this revision

Viewing changes to shlibs/blkid/src/probe.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2009-07-16 15:48:23 UTC
  • mfrom: (1.3.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20090716154823-i26fshvs4v8h90qh
Tags: 2.16-1ubuntu1
* Merge from Debian, remaining changes:
  - Since udev is required in Ubuntu, the hwclock.sh init script is
    not called on startup and the hwclockfirst.sh init script is
    removed.
  - Remove /etc/adjtime on upgrade if it was not used.
  - Install custom blkid.conf to use /dev/.blkid.tab since we don't
    expect device names to survive a reboot
  - No lsb_release call in mount.preinst since we'd need Pre-Depends
    (LP: #383697).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * probe.c - reads tags (LABEL, UUID, FS type, ..) from a block device
 
3
 *
 
4
 * Copyright (C) 2008 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
#ifdef HAVE_SYS_STAT_H
 
18
#include <sys/stat.h>
 
19
#endif
 
20
#ifdef HAVE_SYS_MKDEV_H
 
21
#include <sys/mkdev.h>
 
22
#endif
 
23
#ifdef HAVE_ERRNO_H
 
24
#include <errno.h>
 
25
#endif
 
26
#include <stdint.h>
 
27
#include <stdarg.h>
 
28
 
 
29
#ifdef HAVE_LIBUUID
 
30
# ifdef HAVE_UUID_UUID_H
 
31
#  include <uuid/uuid.h>
 
32
# else
 
33
#  include <uuid.h>
 
34
# endif
 
35
#endif
 
36
 
 
37
#include "blkdev.h"
 
38
#include "blkidP.h"
 
39
#include "probers/probers.h"
 
40
 
 
41
static const struct blkid_idinfo *idinfos[] =
 
42
{
 
43
        /* RAIDs */
 
44
        &linuxraid_idinfo,
 
45
        &ddfraid_idinfo,
 
46
        &iswraid_idinfo,
 
47
        &lsiraid_idinfo,
 
48
        &viaraid_idinfo,
 
49
        &silraid_idinfo,
 
50
        &nvraid_idinfo,
 
51
        &pdcraid_idinfo,
 
52
        &highpoint45x_idinfo,
 
53
        &highpoint37x_idinfo,
 
54
        &adraid_idinfo,
 
55
        &jmraid_idinfo,
 
56
        &lvm2_idinfo,
 
57
        &lvm1_idinfo,
 
58
        &snapcow_idinfo,
 
59
        &luks_idinfo,
 
60
 
 
61
        /* Filesystems */
 
62
        &vfat_idinfo,
 
63
        &swsuspend_idinfo,
 
64
        &swap_idinfo,
 
65
        &xfs_idinfo,
 
66
        &ext4dev_idinfo,
 
67
        &ext4_idinfo,
 
68
        &ext3_idinfo,
 
69
        &ext2_idinfo,
 
70
        &jbd_idinfo,
 
71
        &reiser_idinfo,
 
72
        &reiser4_idinfo,
 
73
        &jfs_idinfo,
 
74
        &udf_idinfo,
 
75
        &iso9660_idinfo,
 
76
        &zfs_idinfo,
 
77
        &hfsplus_idinfo,
 
78
        &hfs_idinfo,
 
79
        &ufs_idinfo,
 
80
        &hpfs_idinfo,
 
81
        &sysv_idinfo,
 
82
        &xenix_idinfo,
 
83
        &ntfs_idinfo,
 
84
        &cramfs_idinfo,
 
85
        &romfs_idinfo,
 
86
        &minix_idinfo,
 
87
        &gfs_idinfo,
 
88
        &gfs2_idinfo,
 
89
        &ocfs_idinfo,
 
90
        &ocfs2_idinfo,
 
91
        &oracleasm_idinfo,
 
92
        &vxfs_idinfo,
 
93
        &squashfs_idinfo,
 
94
        &netware_idinfo,
 
95
        &btrfs_idinfo
 
96
};
 
97
 
 
98
#ifndef ARRAY_SIZE
 
99
# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
100
#endif
 
101
 
 
102
/* filter bitmap macros */
 
103
#define blkid_bmp_wordsize              (8 * sizeof(unsigned long))
 
104
#define blkid_bmp_idx_bit(item)         (1UL << ((item) % blkid_bmp_wordsize))
 
105
#define blkid_bmp_idx_byte(item)        ((item) / blkid_bmp_wordsize)
 
106
 
 
107
#define blkid_bmp_set_item(bmp, item)   \
 
108
                ((bmp)[ blkid_bmp_idx_byte(item) ] |= blkid_bmp_idx_bit(item))
 
109
 
 
110
#define blkid_bmp_unset_item(bmp, item) \
 
111
                ((bmp)[ bmp_idx_byte(item) ] &= ~bmp_idx_bit(item))
 
112
 
 
113
#define blkid_bmp_get_item(bmp, item)   \
 
114
                ((bmp)[ blkid_bmp_idx_byte(item) ] & blkid_bmp_idx_bit(item))
 
115
 
 
116
#define blkid_bmp_size(max_items) \
 
117
                (((max_items) + blkid_bmp_wordsize) / blkid_bmp_wordsize)
 
118
 
 
119
#define BLKID_FLTR_ITEMS        ARRAY_SIZE(idinfos)
 
120
#define BLKID_FLTR_SIZE         blkid_bmp_size(BLKID_FLTR_ITEMS)
 
121
 
 
122
 
 
123
static int blkid_probe_set_usage(blkid_probe pr, int usage);
 
124
 
 
125
int blkid_known_fstype(const char *fstype)
 
126
{
 
127
        int i;
 
128
 
 
129
        if (!fstype)
 
130
                return 0;
 
131
 
 
132
        for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
 
133
                const struct blkid_idinfo *id = idinfos[i];
 
134
                if (strcmp(id->name, fstype) == 0)
 
135
                        return 1;
 
136
        }
 
137
        return 0;
 
138
}
 
139
 
 
140
/*
 
141
 * Returns a pointer to the newly allocated probe struct
 
142
 */
 
143
blkid_probe blkid_new_probe(void)
 
144
{
 
145
        blkid_init_debug(0);
 
146
        return calloc(1, sizeof(struct blkid_struct_probe));
 
147
}
 
148
 
 
149
/*
 
150
 * Deallocates probe struct, buffers and all allocated
 
151
 * data that are associated with this probing control struct.
 
152
 */
 
153
void blkid_free_probe(blkid_probe pr)
 
154
{
 
155
        if (!pr)
 
156
                return;
 
157
        free(pr->fltr);
 
158
        free(pr->buf);
 
159
        free(pr->sbbuf);
 
160
        free(pr);
 
161
}
 
162
 
 
163
static void blkid_probe_reset_vals(blkid_probe pr)
 
164
{
 
165
        memset(pr->vals, 0, sizeof(pr->vals));
 
166
        pr->nvals = 0;
 
167
}
 
168
 
 
169
static void blkid_probe_reset_idx(blkid_probe pr)
 
170
{
 
171
        pr->idx = -1;
 
172
}
 
173
 
 
174
void blkid_reset_probe(blkid_probe pr)
 
175
{
 
176
        if (!pr)
 
177
                return;
 
178
        DBG(DEBUG_LOWPROBE, printf("reseting blkid_probe\n"));
 
179
        if (pr->buf)
 
180
                memset(pr->buf, 0, pr->buf_max);
 
181
        pr->buf_off = 0;
 
182
        pr->buf_len = 0;
 
183
        if (pr->sbbuf)
 
184
                memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
 
185
        pr->sbbuf_len = 0;
 
186
        blkid_probe_reset_vals(pr);
 
187
        blkid_probe_reset_idx(pr);
 
188
}
 
189
 
 
190
/*
 
191
 * Note that we have two offsets:
 
192
 *
 
193
 *      1/ general device offset (pr->off), that's useful for example when we
 
194
 *         probe a partition from whole disk image:
 
195
 *                     blkid-low --offset  <partition_position> disk.img
 
196
 *
 
197
 *      2/ buffer offset (the 'off' argument), that useful for offsets in
 
198
 *         superbloks, ...
 
199
 *
 
200
 *      That means never use lseek(fd, 0, SEEK_SET), the zero position is always
 
201
 *      pr->off, so lseek(fd, pr->off, SEEK_SET).
 
202
 *
 
203
 */
 
204
unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 
205
                                blkid_loff_t off, blkid_loff_t len)
 
206
{
 
207
        ssize_t ret_read = 0;
 
208
 
 
209
        if (off < 0 || len < 0) {
 
210
                DBG(DEBUG_LOWPROBE,
 
211
                        printf("unexpected offset or length of buffer requested\n"));
 
212
                return NULL;
 
213
        }
 
214
        if (off + len <= BLKID_SB_BUFSIZ) {
 
215
                if (!pr->sbbuf) {
 
216
                        pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
 
217
                        if (!pr->sbbuf)
 
218
                                return NULL;
 
219
                }
 
220
                if (!pr->sbbuf_len) {
 
221
                        if (lseek(pr->fd, pr->off, SEEK_SET) < 0)
 
222
                                return NULL;
 
223
                        ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ);
 
224
                        if (ret_read < 0)
 
225
                                ret_read = 0;
 
226
                        pr->sbbuf_len = ret_read;
 
227
                }
 
228
                if (off + len > pr->sbbuf_len)
 
229
                        return NULL;
 
230
                return pr->sbbuf + off;
 
231
        } else {
 
232
                unsigned char *newbuf = NULL;
 
233
 
 
234
                if (len > pr->buf_max) {
 
235
                        newbuf = realloc(pr->buf, len);
 
236
                        if (!newbuf)
 
237
                                return NULL;
 
238
                        pr->buf = newbuf;
 
239
                        pr->buf_max = len;
 
240
                        pr->buf_off = 0;
 
241
                        pr->buf_len = 0;
 
242
                }
 
243
                if (newbuf || off < pr->buf_off ||
 
244
                    off + len > pr->buf_off + pr->buf_len) {
 
245
 
 
246
                        if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
 
247
                                return NULL;
 
248
 
 
249
                        ret_read = read(pr->fd, pr->buf, len);
 
250
                        if (ret_read != (ssize_t) len)
 
251
                                return NULL;
 
252
                        pr->buf_off = off;
 
253
                        pr->buf_len = len;
 
254
                }
 
255
                return off ? pr->buf + (off - pr->buf_off) : pr->buf;
 
256
        }
 
257
}
 
258
 
 
259
/*
 
260
 * Assignes the device to probe control struct, resets internal buffers and
 
261
 * reads 512 bytes from device to the buffers.
 
262
 *
 
263
 * Returns -1 in case of failure, or 0 on success.
 
264
 */
 
265
int blkid_probe_set_device(blkid_probe pr, int fd,
 
266
                blkid_loff_t off, blkid_loff_t size)
 
267
{
 
268
        if (!pr)
 
269
                return -1;
 
270
 
 
271
        blkid_reset_probe(pr);
 
272
 
 
273
        pr->fd = fd;
 
274
        pr->off = off;
 
275
        pr->size = 0;
 
276
 
 
277
        if (size)
 
278
                pr->size = size;
 
279
        else {
 
280
                struct stat sb;
 
281
 
 
282
                if (fstat(fd, &sb))
 
283
                        return -1;
 
284
 
 
285
                if (S_ISBLK(sb.st_mode))
 
286
                        blkdev_get_size(fd, (unsigned long long *) &pr->size);
 
287
                else
 
288
                        pr->size = sb.st_size;
 
289
        }
 
290
        if (!pr->size)
 
291
                return -1;
 
292
 
 
293
        /* read SB to test if the device is readable */
 
294
        if (!blkid_probe_get_buffer(pr, 0, 0x200)) {
 
295
                DBG(DEBUG_LOWPROBE,
 
296
                        printf("failed to prepare a device for low-probing\n"));
 
297
                return -1;
 
298
        }
 
299
 
 
300
        DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n",
 
301
                                pr->off, pr->size));
 
302
        return 0;
 
303
}
 
304
 
 
305
int blkid_probe_set_request(blkid_probe pr, int flags)
 
306
{
 
307
        if (!pr)
 
308
                return -1;
 
309
        pr->probreq = flags;
 
310
        return 0;
 
311
}
 
312
 
 
313
int blkid_probe_reset_filter(blkid_probe pr)
 
314
{
 
315
        if (!pr)
 
316
                return -1;
 
317
        if (pr->fltr)
 
318
                memset(pr->fltr, 0, BLKID_FLTR_SIZE * sizeof(unsigned long));
 
319
        blkid_probe_reset_idx(pr);
 
320
        return 0;
 
321
}
 
322
 
 
323
/*
 
324
 * flag:
 
325
 *
 
326
 *  BLKID_FLTR_NOTIN  - probe all filesystems which are NOT IN names[]
 
327
 *
 
328
 *  BLKID_FLTR_ONLYIN - probe filesystem which are IN names[]
 
329
 */
 
330
int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[])
 
331
{
 
332
        int i;
 
333
 
 
334
        if (!pr || !names)
 
335
                return -1;
 
336
        if (!pr->fltr) {
 
337
                pr->fltr = calloc(BLKID_FLTR_SIZE, sizeof(unsigned long));
 
338
                blkid_probe_reset_idx(pr);
 
339
        } else
 
340
                blkid_probe_reset_filter(pr);
 
341
 
 
342
        if (!pr->fltr)
 
343
                return -1;
 
344
 
 
345
        for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
 
346
                int has = 0;
 
347
                const struct blkid_idinfo *id = idinfos[i];
 
348
                char **n;
 
349
 
 
350
                for (n = names; *n; n++) {
 
351
                        if (!strcmp(id->name, *n)) {
 
352
                                has = 1;
 
353
                                break;
 
354
                        }
 
355
                }
 
356
                /* The default is enable all filesystems,
 
357
                 * set relevant bitmap bit means disable the filesystem.
 
358
                 */
 
359
                if (flag & BLKID_FLTR_ONLYIN) {
 
360
                       if (!has)
 
361
                                blkid_bmp_set_item(pr->fltr, i);
 
362
                } else if (flag & BLKID_FLTR_NOTIN) {
 
363
                        if (has)
 
364
                                blkid_bmp_set_item(pr->fltr, i);
 
365
                }
 
366
        }
 
367
        DBG(DEBUG_LOWPROBE, printf("a new probing type-filter initialized\n"));
 
368
        return 0;
 
369
}
 
370
 
 
371
/*
 
372
 * flag:
 
373
 *
 
374
 *  BLKID_FLTR_NOTIN  - probe all filesystems which are NOT IN "usage"
 
375
 *
 
376
 *  BLKID_FLTR_ONLYIN - probe filesystem which are IN "usage"
 
377
 *
 
378
 * where the "usage" is a set of filesystem according the usage flag (crypto,
 
379
 * raid, filesystem, ...)
 
380
 */
 
381
int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage)
 
382
{
 
383
        int i;
 
384
 
 
385
        if (!pr || !usage)
 
386
                return -1;
 
387
        if (!pr->fltr) {
 
388
                pr->fltr = calloc(BLKID_FLTR_SIZE, sizeof(unsigned long));
 
389
                blkid_probe_reset_idx(pr);
 
390
        } else
 
391
                blkid_probe_reset_filter(pr);
 
392
 
 
393
        if (!pr->fltr)
 
394
                return -1;
 
395
 
 
396
        for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
 
397
                const struct blkid_idinfo *id = idinfos[i];
 
398
 
 
399
                if (id->usage & usage) {
 
400
                        if (flag & BLKID_FLTR_NOTIN)
 
401
                                blkid_bmp_set_item(pr->fltr, i);
 
402
                } else if (flag & BLKID_FLTR_ONLYIN)
 
403
                        blkid_bmp_set_item(pr->fltr, i);
 
404
        }
 
405
        DBG(DEBUG_LOWPROBE, printf("a new probing usage-filter initialized\n"));
 
406
        return 0;
 
407
}
 
408
 
 
409
 
 
410
int blkid_probe_invert_filter(blkid_probe pr)
 
411
{
 
412
        int i;
 
413
 
 
414
        if (!pr || !pr->fltr)
 
415
                return -1;
 
416
        for (i = 0; i < BLKID_FLTR_SIZE; i++)
 
417
                pr->fltr[i] = ~pr->fltr[i];
 
418
 
 
419
        blkid_probe_reset_idx(pr);
 
420
        DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
 
421
        return 0;
 
422
}
 
423
 
 
424
/*
 
425
 * The blkid_do_probe() calls the probe functions. This routine could be used
 
426
 * in a loop when you need to probe for all possible filesystems/raids.
 
427
 *
 
428
 * 1/ basic case -- use the first result:
 
429
 *
 
430
 *      if (blkid_do_probe(pr) == 0) {
 
431
 *              int nvals = blkid_probe_numof_values(pr);
 
432
 *              for (n = 0; n < nvals; n++) {
 
433
 *                      if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
 
434
 *                              printf("%s = %s\n", name, data);
 
435
 *              }
 
436
 *      }
 
437
 *
 
438
 * 2/ advanced case -- probe for all signatures (don't forget that some
 
439
 *                     filesystems can co-exist on one volume (e.g. CD-ROM).
 
440
 *
 
441
 *      while (blkid_do_probe(pr) == 0) {
 
442
 *              int nvals = blkid_probe_numof_values(pr);
 
443
 *              ...
 
444
 *      }
 
445
 *
 
446
 *    The internal probing index (pointer to the last probing function) is
 
447
 *    always reseted when you touch probing filter or set a new device. It
 
448
 *    means you cannot use:
 
449
 *
 
450
 *      blkid_probe_invert_filter()
 
451
 *      blkid_probe_filter_usage()
 
452
 *      blkid_probe_filter_types()
 
453
 *      blkid_probe_reset_filter()
 
454
 *      blkid_probe_set_device()
 
455
 *
 
456
 *    in the loop (e.g while()) when you iterate on all signatures.
 
457
 */
 
458
int blkid_do_probe(blkid_probe pr)
 
459
{
 
460
        int i = 0;
 
461
 
 
462
        if (!pr || pr->idx < -1)
 
463
                return -1;
 
464
 
 
465
        blkid_probe_reset_vals(pr);
 
466
 
 
467
        DBG(DEBUG_LOWPROBE,
 
468
                printf("--> starting probing loop [idx=%d]\n",
 
469
                pr->idx));
 
470
 
 
471
        i = pr->idx + 1;
 
472
 
 
473
        for ( ; i < ARRAY_SIZE(idinfos); i++) {
 
474
                const struct blkid_idinfo *id;
 
475
                const struct blkid_idmag *mag;
 
476
                int hasmag = 0;
 
477
 
 
478
                pr->idx = i;
 
479
 
 
480
                if (pr->fltr && blkid_bmp_get_item(pr->fltr, i))
 
481
                        continue;
 
482
 
 
483
                id = idinfos[i];
 
484
                mag = id->magics ? &id->magics[0] : NULL;
 
485
 
 
486
                /* try to detect by magic string */
 
487
                while(mag && mag->magic) {
 
488
                        int idx;
 
489
                        unsigned char *buf;
 
490
 
 
491
                        idx = mag->kboff + (mag->sboff >> 10);
 
492
                        buf = blkid_probe_get_buffer(pr, idx << 10, 1024);
 
493
 
 
494
                        if (buf && !memcmp(mag->magic,
 
495
                                        buf + (mag->sboff & 0x3ff), mag->len)) {
 
496
                                DBG(DEBUG_LOWPROBE, printf(
 
497
                                        "%s: magic sboff=%u, kboff=%ld\n",
 
498
                                        id->name, mag->sboff, mag->kboff));
 
499
                                hasmag = 1;
 
500
                                break;
 
501
                        }
 
502
                        mag++;
 
503
                }
 
504
 
 
505
                if (hasmag == 0 && id->magics && id->magics[0].magic)
 
506
                        /* magic string(s) defined, but not found */
 
507
                        continue;
 
508
 
 
509
                /* final check by probing function */
 
510
                if (id->probefunc) {
 
511
                        DBG(DEBUG_LOWPROBE, printf(
 
512
                                "%s: call probefunc()\n", id->name));
 
513
                        if (id->probefunc(pr, mag) != 0)
 
514
                                continue;
 
515
                }
 
516
 
 
517
                /* all cheks passed */
 
518
                if (pr->probreq & BLKID_PROBREQ_TYPE)
 
519
                        blkid_probe_set_value(pr, "TYPE",
 
520
                                (unsigned char *) id->name,
 
521
                                strlen(id->name) + 1);
 
522
                if (pr->probreq & BLKID_PROBREQ_USAGE)
 
523
                        blkid_probe_set_usage(pr, id->usage);
 
524
 
 
525
                DBG(DEBUG_LOWPROBE,
 
526
                        printf("<-- leaving probing loop (type=%s) [idx=%d]\n",
 
527
                        id->name, pr->idx));
 
528
                return 0;
 
529
        }
 
530
        DBG(DEBUG_LOWPROBE,
 
531
                printf("<-- leaving probing loop (failed) [idx=%d]\n",
 
532
                pr->idx));
 
533
        return 1;
 
534
}
 
535
 
 
536
/*
 
537
 * This is the same function as blkid_do_probe(), but returns only one result
 
538
 * (cannot be used in while()) and checks for ambivalen results (more
 
539
 * filesystems on the device) -- in such case returns -2.
 
540
 *
 
541
 * The function does not check for filesystems when a RAID signature is
 
542
 * detected.  The function also does not check for collision between RAIDs. The
 
543
 * first detected RAID is returned.
 
544
 */
 
545
int blkid_do_safeprobe(blkid_probe pr)
 
546
{
 
547
        struct blkid_struct_probe first;
 
548
        int count = 0;
 
549
        int intol = 0;
 
550
        int rc;
 
551
 
 
552
        while ((rc = blkid_do_probe(pr)) == 0) {
 
553
                if (!count) {
 
554
                        /* store the fist result */
 
555
                        memcpy(first.vals, pr->vals, sizeof(first.vals));
 
556
                        first.nvals = pr->nvals;
 
557
                        first.idx = pr->idx;
 
558
                }
 
559
                count++;
 
560
 
 
561
                if (idinfos[pr->idx]->usage & BLKID_USAGE_RAID)
 
562
                        break;
 
563
                if (!(idinfos[pr->idx]->flags & BLKID_IDINFO_TOLERANT))
 
564
                        intol++;
 
565
        }
 
566
        if (rc < 0)
 
567
                return rc;              /* error */
 
568
        if (count > 1 && intol) {
 
569
                DBG(DEBUG_LOWPROBE,
 
570
                        printf("ERROR: ambivalent result detected (%d filesystems)!\n",
 
571
                        count));
 
572
                return -2;              /* error, ambivalent result (more FS) */
 
573
        }
 
574
        if (!count)
 
575
                return 1;               /* nothing detected */
 
576
 
 
577
        /* restore the first result */
 
578
        memcpy(pr->vals, first.vals, sizeof(first.vals));
 
579
        pr->nvals = first.nvals;
 
580
        pr->idx = first.idx;
 
581
 
 
582
        return 0;
 
583
}
 
584
 
 
585
int blkid_probe_numof_values(blkid_probe pr)
 
586
{
 
587
        if (!pr)
 
588
                return -1;
 
589
        return pr->nvals;
 
590
}
 
591
 
 
592
 
 
593
static struct blkid_prval *blkid_probe_assign_value(
 
594
                        blkid_probe pr, const char *name)
 
595
{
 
596
        struct blkid_prval *v;
 
597
 
 
598
        if (!name)
 
599
                return NULL;
 
600
        if (pr->nvals >= BLKID_PROBVAL_NVALS)
 
601
                return NULL;
 
602
 
 
603
        v = &pr->vals[pr->nvals];
 
604
        v->name = name;
 
605
        pr->nvals++;
 
606
 
 
607
        DBG(DEBUG_LOWPROBE, printf("assigning %s\n", name));
 
608
        return v;
 
609
}
 
610
 
 
611
int blkid_probe_set_value(blkid_probe pr, const char *name,
 
612
                unsigned char *data, size_t len)
 
613
{
 
614
        struct blkid_prval *v;
 
615
 
 
616
        if (len > BLKID_PROBVAL_BUFSIZ)
 
617
                len = BLKID_PROBVAL_BUFSIZ;
 
618
 
 
619
        v = blkid_probe_assign_value(pr, name);
 
620
        if (!v)
 
621
                return -1;
 
622
 
 
623
        memcpy(v->data, data, len);
 
624
        v->len = len;
 
625
        return 0;
 
626
}
 
627
 
 
628
int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
 
629
                const char *fmt, va_list ap)
 
630
{
 
631
        struct blkid_prval *v;
 
632
        size_t len;
 
633
 
 
634
        v = blkid_probe_assign_value(pr, name);
 
635
        if (!v)
 
636
                return -1;
 
637
 
 
638
        len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
 
639
 
 
640
        if (len <= 0) {
 
641
                pr->nvals--; /* reset the latest assigned value */
 
642
                return -1;
 
643
        }
 
644
        v->len = len + 1;
 
645
        return 0;
 
646
}
 
647
 
 
648
int blkid_probe_set_version(blkid_probe pr, const char *version)
 
649
{
 
650
        if (pr->probreq & BLKID_PROBREQ_VERSION)
 
651
                return blkid_probe_set_value(pr, "VERSION",
 
652
                           (unsigned char *) version, strlen(version) + 1);
 
653
        return 0;
 
654
}
 
655
 
 
656
int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
 
657
{
 
658
        int rc = 0;
 
659
 
 
660
        if (pr->probreq & BLKID_PROBREQ_VERSION) {
 
661
                va_list ap;
 
662
 
 
663
                va_start(ap, fmt);
 
664
                rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap);
 
665
                va_end(ap);
 
666
        }
 
667
        return rc;
 
668
}
 
669
 
 
670
static int blkid_probe_set_usage(blkid_probe pr, int usage)
 
671
{
 
672
        char *u = NULL;
 
673
 
 
674
        if (usage & BLKID_USAGE_FILESYSTEM)
 
675
                u = "filesystem";
 
676
        else if (usage & BLKID_USAGE_RAID)
 
677
                u = "raid";
 
678
        else if (usage & BLKID_USAGE_CRYPTO)
 
679
                u = "crypto";
 
680
        else if (usage & BLKID_USAGE_OTHER)
 
681
                u = "other";
 
682
        else
 
683
                u = "unknown";
 
684
 
 
685
        return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1);
 
686
}
 
687
 
 
688
int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
 
689
{
 
690
        struct blkid_prval *v;
 
691
        int i;
 
692
 
 
693
        if (len > BLKID_PROBVAL_BUFSIZ)
 
694
                len = BLKID_PROBVAL_BUFSIZ;
 
695
 
 
696
        if ((pr->probreq & BLKID_PROBREQ_LABELRAW) &&
 
697
            blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
 
698
                return -1;
 
699
        if (!(pr->probreq & BLKID_PROBREQ_LABEL))
 
700
                return 0;
 
701
        v = blkid_probe_assign_value(pr, "LABEL");
 
702
        if (!v)
 
703
                return -1;
 
704
 
 
705
        memcpy(v->data, label, len);
 
706
        v->data[len] = '\0';
 
707
 
 
708
        /* remove trailing whitespace */
 
709
        i = strnlen((char *) v->data, len);
 
710
        while (i--) {
 
711
                if (!isspace(v->data[i]))
 
712
                        break;
 
713
        }
 
714
        v->data[++i] = '\0';
 
715
        v->len = i + 1;
 
716
        return 0;
 
717
}
 
718
 
 
719
static size_t encode_to_utf8(int enc, unsigned char *dest, size_t len,
 
720
                        unsigned char *src, size_t count)
 
721
{
 
722
        size_t i, j;
 
723
        uint16_t c;
 
724
 
 
725
        for (j = i = 0; i + 2 <= count; i += 2) {
 
726
                if (enc == BLKID_ENC_UTF16LE)
 
727
                        c = (src[i+1] << 8) | src[i];
 
728
                else /* BLKID_ENC_UTF16BE */
 
729
                        c = (src[i] << 8) | src[i+1];
 
730
                if (c == 0) {
 
731
                        dest[j] = '\0';
 
732
                        break;
 
733
                } else if (c < 0x80) {
 
734
                        if (j+1 >= len)
 
735
                                break;
 
736
                        dest[j++] = (uint8_t) c;
 
737
                } else if (c < 0x800) {
 
738
                        if (j+2 >= len)
 
739
                                break;
 
740
                        dest[j++] = (uint8_t) (0xc0 | (c >> 6));
 
741
                        dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
 
742
                } else {
 
743
                        if (j+3 >= len)
 
744
                                break;
 
745
                        dest[j++] = (uint8_t) (0xe0 | (c >> 12));
 
746
                        dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
 
747
                        dest[j++] = (uint8_t) (0x80 | (c & 0x3f));
 
748
                }
 
749
        }
 
750
        dest[j] = '\0';
 
751
        return j;
 
752
}
 
753
 
 
754
int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
 
755
                                size_t len, int enc)
 
756
{
 
757
        struct blkid_prval *v;
 
758
 
 
759
        if ((pr->probreq & BLKID_PROBREQ_LABELRAW) &&
 
760
            blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
 
761
                return -1;
 
762
        if (!(pr->probreq & BLKID_PROBREQ_LABEL))
 
763
                return 0;
 
764
        v = blkid_probe_assign_value(pr, "LABEL");
 
765
        if (!v)
 
766
                return -1;
 
767
 
 
768
        v->len = encode_to_utf8(enc, v->data, sizeof(v->data), label, len);
 
769
        return 0;
 
770
}
 
771
 
 
772
/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
 
773
static int uuid_is_empty(const unsigned char *buf, size_t len)
 
774
{
 
775
        int i;
 
776
 
 
777
        for (i = 0; i < len; i++)
 
778
                if (buf[i])
 
779
                        return 0;
 
780
        return 1;
 
781
}
 
782
 
 
783
int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
 
784
                                size_t len, const char *fmt, ...)
 
785
{
 
786
        int rc = -1;
 
787
        va_list ap;
 
788
 
 
789
        if (len > BLKID_PROBVAL_BUFSIZ)
 
790
                len = BLKID_PROBVAL_BUFSIZ;
 
791
 
 
792
        if (uuid_is_empty(uuid, len))
 
793
                return 0;
 
794
 
 
795
        if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) &&
 
796
            blkid_probe_set_value(pr, "UUID_RAW", uuid, len) < 0)
 
797
                return -1;
 
798
        if (!(pr->probreq & BLKID_PROBREQ_UUID))
 
799
                return 0;
 
800
 
 
801
        va_start(ap, fmt);
 
802
        rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap);
 
803
        va_end(ap);
 
804
 
 
805
        /* convert to lower case (..be paranoid) */
 
806
        if (!rc) {
 
807
                int i;
 
808
                struct blkid_prval *v = &pr->vals[pr->nvals];
 
809
 
 
810
                for (i = 0; i < v->len; i++)
 
811
                        if (v->data[i] >= 'A' && v->data[i] <= 'F')
 
812
                                v->data[i] = (v->data[i] - 'A') + 'a';
 
813
        }
 
814
        return rc;
 
815
}
 
816
 
 
817
/* function to set UUIDs that are in suberblocks stored as strings */
 
818
int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len)
 
819
{
 
820
        struct blkid_prval *v;
 
821
 
 
822
        if (str == NULL || *str == '\0')
 
823
                return -1;
 
824
        if (!len)
 
825
                len = strlen((char *) str);
 
826
        if (len > BLKID_PROBVAL_BUFSIZ)
 
827
                len = BLKID_PROBVAL_BUFSIZ;
 
828
 
 
829
        if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) &&
 
830
            blkid_probe_set_value(pr, "UUID_RAW", str, len) < 0)
 
831
                return -1;
 
832
        if (!(pr->probreq & BLKID_PROBREQ_UUID))
 
833
                return 0;
 
834
 
 
835
        v = blkid_probe_assign_value(pr, "UUID");
 
836
        if (v) {
 
837
                memcpy((char *) v->data, str, len);
 
838
                *(v->data + len) = '\0';
 
839
                v->len = len;
 
840
                return 0;
 
841
        }
 
842
        return -1;
 
843
}
 
844
 
 
845
/* default _set_uuid function to set DCE UUIDs */
 
846
int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name)
 
847
{
 
848
        struct blkid_prval *v;
 
849
 
 
850
        if (uuid_is_empty(uuid, 16))
 
851
                return 0;
 
852
 
 
853
        if (!name) {
 
854
                if ((pr->probreq & BLKID_PROBREQ_UUIDRAW) &&
 
855
                    blkid_probe_set_value(pr, "UUID_RAW", uuid, 16) < 0)
 
856
                        return -1;
 
857
                if (!(pr->probreq & BLKID_PROBREQ_UUID))
 
858
                        return 0;
 
859
 
 
860
                v = blkid_probe_assign_value(pr, "UUID");
 
861
        } else
 
862
                v = blkid_probe_assign_value(pr, name);
 
863
 
 
864
#ifdef HAVE_LIBUUID
 
865
        {
 
866
                uuid_unparse(uuid, (char *) v->data);
 
867
                v->len = 37;
 
868
        }
 
869
#else
 
870
        v->len = snprintf(v->data, sizeof(v->data),
 
871
                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
 
872
                uuid[0], uuid[1], uuid[2], uuid[3],
 
873
                uuid[4], uuid[5],
 
874
                uuid[6], uuid[7],
 
875
                uuid[8], uuid[9],
 
876
                uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
 
877
        v->len++;
 
878
#endif
 
879
        return 0;
 
880
}
 
881
 
 
882
int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid)
 
883
{
 
884
        return blkid_probe_set_uuid_as(pr, uuid, NULL);
 
885
}
 
886
 
 
887
int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
 
888
                        const char **data, size_t *len)
 
889
{
 
890
        struct blkid_prval *v;
 
891
 
 
892
        if (pr == NULL || num < 0 || num >= pr->nvals)
 
893
                return -1;
 
894
 
 
895
        v = &pr->vals[num];
 
896
        if (name)
 
897
                *name = v->name;
 
898
        if (data)
 
899
                *data = (char *) v->data;
 
900
        if (len)
 
901
                *len = v->len;
 
902
 
 
903
        DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
 
904
        return 0;
 
905
}
 
906
 
 
907
int blkid_probe_lookup_value(blkid_probe pr, const char *name,
 
908
                        const char **data, size_t *len)
 
909
{
 
910
        int i;
 
911
 
 
912
        if (pr == NULL || pr->nvals == 0 || name == NULL)
 
913
                return -1;
 
914
 
 
915
        for (i = 0; i < pr->nvals; i++) {
 
916
                struct blkid_prval *v = &pr->vals[i];
 
917
 
 
918
                if (v->name && strcmp(name, v->name) == 0) {
 
919
                        if (data)
 
920
                                *data = (char *) v->data;
 
921
                        if (len)
 
922
                                *len = v->len;
 
923
                        DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
 
924
                        return 0;
 
925
                }
 
926
        }
 
927
        return -1;
 
928
}
 
929
 
 
930
int blkid_probe_has_value(blkid_probe pr, const char *name)
 
931
{
 
932
        if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
 
933
                return 1;
 
934
        return 0;
 
935
}
 
936