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

« back to all changes in this revision

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