]> git.ipfire.org Git - thirdparty/util-linux.git/blame - shlibs/blkid/src/probe.c
libblkid: remove superblock functions from probe.c
[thirdparty/util-linux.git] / shlibs / blkid / src / probe.c
CommitLineData
a0948ffe 1/*
51410fc6 2 * probe.c - reads tags (LABEL, UUID, FS type, ..) from a block device
a0948ffe 3 *
51410fc6 4 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
a0948ffe 5 *
a0948ffe
KZ
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
a0948ffe
KZ
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
a0948ffe
KZ
23#ifdef HAVE_ERRNO_H
24#include <errno.h>
25#endif
51410fc6 26#include <stdint.h>
8c0dc071
KZ
27#include <stdarg.h>
28
51410fc6 29#ifdef HAVE_LIBUUID
8c0dc071
KZ
30# ifdef HAVE_UUID_UUID_H
31# include <uuid/uuid.h>
e5127179
KZ
32# else
33# include <uuid.h>
8c0dc071 34# endif
51410fc6 35#endif
a0948ffe 36
dc61d909 37#include "blkdev.h"
51410fc6 38#include "blkidP.h"
219227c2
KZ
39
40#include "superblocks/superblocks.h"
a0948ffe 41
51410fc6 42static const struct blkid_idinfo *idinfos[] =
a0948ffe 43{
3402fff1
KZ
44 /* RAIDs */
45 &linuxraid_idinfo,
f8504a4e 46 &ddfraid_idinfo,
56ad7426 47 &iswraid_idinfo,
dc61d909 48 &lsiraid_idinfo,
3402fff1
KZ
49 &viaraid_idinfo,
50 &silraid_idinfo,
e86961ba 51 &nvraid_idinfo,
b9938904 52 &pdcraid_idinfo,
5784db20
KZ
53 &highpoint45x_idinfo,
54 &highpoint37x_idinfo,
3402fff1
KZ
55 &adraid_idinfo,
56 &jmraid_idinfo,
57 &lvm2_idinfo,
f19f9872 58 &lvm1_idinfo,
c8d20dc1 59 &snapcow_idinfo,
06da6d00 60 &luks_idinfo,
3402fff1
KZ
61
62 /* Filesystems */
63 &vfat_idinfo,
64 &swsuspend_idinfo,
65 &swap_idinfo,
66 &xfs_idinfo,
8e7e30e4
KZ
67 &ext4dev_idinfo,
68 &ext4_idinfo,
69 &ext3_idinfo,
70 &ext2_idinfo,
3402fff1
KZ
71 &jbd_idinfo,
72 &reiser_idinfo,
73 &reiser4_idinfo,
80f26373 74 &jfs_idinfo,
3402fff1
KZ
75 &udf_idinfo,
76 &iso9660_idinfo,
1f4da8d2 77 &zfs_idinfo,
3402fff1
KZ
78 &hfsplus_idinfo,
79 &hfs_idinfo,
83b935ae 80 &ufs_idinfo,
e134f470 81 &hpfs_idinfo,
d1e9e1e4
KZ
82 &sysv_idinfo,
83 &xenix_idinfo,
3402fff1
KZ
84 &ntfs_idinfo,
85 &cramfs_idinfo,
86 &romfs_idinfo,
681ff570 87 &minix_idinfo,
81f81873
KZ
88 &gfs_idinfo,
89 &gfs2_idinfo,
7fd65bed
KZ
90 &ocfs_idinfo,
91 &ocfs2_idinfo,
92 &oracleasm_idinfo,
c29368b4 93 &vxfs_idinfo,
fc954eb5 94 &squashfs_idinfo,
990b429a
KZ
95 &netware_idinfo,
96 &btrfs_idinfo
51410fc6 97};
a0948ffe 98
51410fc6
KZ
99#ifndef ARRAY_SIZE
100# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
101#endif
a0948ffe 102
51410fc6 103#define BLKID_FLTR_ITEMS ARRAY_SIZE(idinfos)
f23e0557 104#define BLKID_FLTR_SIZE blkid_bmp_nwords(BLKID_FLTR_ITEMS)
a0948ffe 105
51410fc6 106static int blkid_probe_set_usage(blkid_probe pr, int usage);
a0948ffe 107
a0948ffe 108/*
51410fc6 109 * Returns a pointer to the newly allocated probe struct
a0948ffe 110 */
51410fc6 111blkid_probe blkid_new_probe(void)
a0948ffe 112{
7a458332 113 blkid_init_debug(0);
51410fc6 114 return calloc(1, sizeof(struct blkid_struct_probe));
a0948ffe
KZ
115}
116
117/*
51410fc6
KZ
118 * Deallocates probe struct, buffers and all allocated
119 * data that are associated with this probing control struct.
a0948ffe 120 */
51410fc6 121void blkid_free_probe(blkid_probe pr)
a0948ffe 122{
51410fc6
KZ
123 if (!pr)
124 return;
125 free(pr->fltr);
126 free(pr->buf);
127 free(pr->sbbuf);
128 free(pr);
a0948ffe
KZ
129}
130
9bdf6885
KZ
131/*
132 * Removes chain values from probing result.
133 */
134void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
135{
136 int nvals = pr->nvals;
137 int i, x;
138
139 for (x = 0, i = 0; i < pr->nvals; i++) {
140 struct blkid_prval *v = &pr->vals[i];
141
142 if (v->chain != chn && x == i) {
143 x++;
144 continue;
145 }
146 if (v->chain == chn) {
147 --nvals;
148 continue;
149 }
150 memcpy(&pr->vals[x++], v, sizeof(struct blkid_prval));
151 }
152 pr->nvals = nvals;
153}
154
155/*
156 * Copies chain values from probing result to @vals, the max size of @vals is
157 * @nvals and returns real number of values.
158 */
159int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
160 struct blkid_prval *vals, int nvals)
161{
162 int i, x;
163
164 for (x = 0, i = 0; i < pr->nvals && x < nvals; i++) {
165 struct blkid_prval *v = &pr->vals[i];
166
167 if (v->chain != chn)
168 continue;
169 memcpy(&vals[x++], v, sizeof(struct blkid_prval));
170 }
171 return x;
172}
173
174/*
175 * Appends values from @vals to the probing result
176 */
177void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals)
178{
179 int i = 0;
180
181 while (i < nvals && pr->nvals < BLKID_NVALS) {
182 memcpy(&pr->vals[pr->nvals++], &vals[i++],
183 sizeof(struct blkid_prval));
184 }
185}
186
51410fc6 187static void blkid_probe_reset_vals(blkid_probe pr)
a0948ffe 188{
51410fc6
KZ
189 memset(pr->vals, 0, sizeof(pr->vals));
190 pr->nvals = 0;
a0948ffe
KZ
191}
192
1c1726a7
KZ
193struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
194{
195 return pr->cur_chain;
196}
197
4ce48a97
KZ
198static void blkid_probe_reset_idx(blkid_probe pr)
199{
200 pr->idx = -1;
201}
202
51410fc6 203void blkid_reset_probe(blkid_probe pr)
a0948ffe 204{
51410fc6
KZ
205 if (!pr)
206 return;
6644688a 207 DBG(DEBUG_LOWPROBE, printf("reseting blkid_probe\n"));
51410fc6
KZ
208 if (pr->buf)
209 memset(pr->buf, 0, pr->buf_max);
210 pr->buf_off = 0;
211 pr->buf_len = 0;
212 if (pr->sbbuf)
213 memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
214 pr->sbbuf_len = 0;
215 blkid_probe_reset_vals(pr);
4ce48a97 216 blkid_probe_reset_idx(pr);
a0948ffe
KZ
217}
218
46a734fd
KZ
219/***
220static int blkid_probe_dump_filter(blkid_probe pr, int chain)
221{
222 struct blkid_chain *chn;
223 int i;
224
225 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
226 return -1;
227
228 chn = &pr->chains[chain];
229
230 if (!chn->fltr)
231 return -1;
232
233 for (i = 0; i < chn->driver->nidinfos; i++) {
234 const struct blkid_idinfo *id = chn->driver->idinfos[i];
235
236 DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
237 i,
238 id->name,
239 blkid_bmp_get_item(chn->fltr, i)
240 ? "disabled" : "enabled <--"));
241
242 }
243 return 0;
244}
245***/
246
247/*
248 * Returns properly initialized chain filter
249 */
250unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
251{
252 struct blkid_chain *chn;
253
254 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
255 return NULL;
256
257 chn = &pr->chains[chain];
258
259 /* always when you touch the chain filter all indexes are reseted and
260 * probing starts from scratch
261 */
262 chn->idx = -1;
263 pr->cur_chain = NULL;
264
265 if (!chn->driver->has_fltr || (!chn->fltr && !create))
266 return NULL;
267
268 if (!chn->fltr)
269 chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
270 else
271 memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
272
273 /* blkid_probe_dump_filter(pr, chain); */
274 return chn->fltr;
275}
276
277/*
278 * Generic private functions for filter setting
279 */
280int __blkid_probe_invert_filter(blkid_probe pr, int chain)
281{
282 int i;
283 struct blkid_chain *chn;
284 unsigned long *fltr;
285
286 fltr = blkid_probe_get_filter(pr, chain, FALSE);
287 if (!fltr)
288 return -1;
289
290 chn = &pr->chains[chain];
291
292 for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
293 fltr[i] = ~fltr[i];
294
295 DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
296 /* blkid_probe_dump_filter(pr, chain); */
297 return 0;
298}
299
300int __blkid_probe_reset_filter(blkid_probe pr, int chain)
301{
302 return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
303}
304
305int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
306{
307 unsigned long *fltr;
308 struct blkid_chain *chn;
309 int i;
310
311 fltr = blkid_probe_get_filter(pr, chain, TRUE);
312 if (!fltr)
313 return -1;
314
315 chn = &pr->chains[chain];
316
317 for (i = 0; i < chn->driver->nidinfos; i++) {
318 int has = 0;
319 const struct blkid_idinfo *id = chn->driver->idinfos[i];
320 char **n;
321
322 for (n = names; *n; n++) {
323 if (!strcmp(id->name, *n)) {
324 has = 1;
325 break;
326 }
327 }
328 if (flag & BLKID_FLTR_ONLYIN) {
329 if (!has)
330 blkid_bmp_set_item(fltr, i);
331 } else if (flag & BLKID_FLTR_NOTIN) {
332 if (has)
333 blkid_bmp_set_item(fltr, i);
334 }
335 }
336
337 DBG(DEBUG_LOWPROBE,
338 printf("%s: a new probing type-filter initialized\n",
339 chn->driver->name));
340 /* blkid_probe_dump_filter(pr, chain); */
341 return 0;
342}
343
51410fc6
KZ
344/*
345 * Note that we have two offsets:
346 *
347 * 1/ general device offset (pr->off), that's useful for example when we
348 * probe a partition from whole disk image:
349 * blkid-low --offset <partition_position> disk.img
350 *
351 * 2/ buffer offset (the 'off' argument), that useful for offsets in
352 * superbloks, ...
353 *
354 * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
355 * pr->off, so lseek(fd, pr->off, SEEK_SET).
356 *
357 */
358unsigned char *blkid_probe_get_buffer(blkid_probe pr,
359 blkid_loff_t off, blkid_loff_t len)
a0948ffe 360{
51410fc6 361 ssize_t ret_read = 0;
a0948ffe 362
4884729a
KZ
363 if (off < 0 || len < 0) {
364 DBG(DEBUG_LOWPROBE,
365 printf("unexpected offset or length of buffer requested\n"));
366 return NULL;
367 }
51410fc6
KZ
368 if (off + len <= BLKID_SB_BUFSIZ) {
369 if (!pr->sbbuf) {
370 pr->sbbuf = malloc(BLKID_SB_BUFSIZ);
371 if (!pr->sbbuf)
372 return NULL;
373 }
374 if (!pr->sbbuf_len) {
375 if (lseek(pr->fd, pr->off, SEEK_SET) < 0)
376 return NULL;
377 ret_read = read(pr->fd, pr->sbbuf, BLKID_SB_BUFSIZ);
378 if (ret_read < 0)
379 ret_read = 0;
380 pr->sbbuf_len = ret_read;
381 }
382 if (off + len > pr->sbbuf_len)
383 return NULL;
384 return pr->sbbuf + off;
385 } else {
386 unsigned char *newbuf = NULL;
387
388 if (len > pr->buf_max) {
389 newbuf = realloc(pr->buf, len);
390 if (!newbuf)
391 return NULL;
392 pr->buf = newbuf;
393 pr->buf_max = len;
394 pr->buf_off = 0;
395 pr->buf_len = 0;
396 }
397 if (newbuf || off < pr->buf_off ||
398 off + len > pr->buf_off + pr->buf_len) {
399
400 if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
401 return NULL;
402
403 ret_read = read(pr->fd, pr->buf, len);
404 if (ret_read != (ssize_t) len)
405 return NULL;
406 pr->buf_off = off;
407 pr->buf_len = len;
408 }
409 return off ? pr->buf + (off - pr->buf_off) : pr->buf;
410 }
a0948ffe
KZ
411}
412
51410fc6
KZ
413/*
414 * Assignes the device to probe control struct, resets internal buffers and
415 * reads 512 bytes from device to the buffers.
416 *
417 * Returns -1 in case of failure, or 0 on success.
418 */
419int blkid_probe_set_device(blkid_probe pr, int fd,
420 blkid_loff_t off, blkid_loff_t size)
a0948ffe 421{
51410fc6
KZ
422 if (!pr)
423 return -1;
a0948ffe 424
51410fc6 425 blkid_reset_probe(pr);
a0948ffe 426
51410fc6
KZ
427 pr->fd = fd;
428 pr->off = off;
bb6c6673 429 pr->size = 0;
dc61d909 430
bb6c6673 431 if (size)
dc61d909 432 pr->size = size;
bb6c6673
KZ
433 else {
434 struct stat sb;
435
436 if (fstat(fd, &sb))
437 return -1;
438
439 if (S_ISBLK(sb.st_mode))
440 blkdev_get_size(fd, (unsigned long long *) &pr->size);
441 else
442 pr->size = sb.st_size;
443 }
444 if (!pr->size)
445 return -1;
a0948ffe 446
51410fc6 447 /* read SB to test if the device is readable */
6644688a
KZ
448 if (!blkid_probe_get_buffer(pr, 0, 0x200)) {
449 DBG(DEBUG_LOWPROBE,
450 printf("failed to prepare a device for low-probing\n"));
51410fc6 451 return -1;
6644688a 452 }
a0948ffe 453
bb6c6673
KZ
454 DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%zd, size=%zd\n",
455 pr->off, pr->size));
a0948ffe
KZ
456 return 0;
457}
458
a0fc685c
KZ
459/*
460 * The blkid_do_probe() calls the probe functions. This routine could be used
461 * in a loop when you need to probe for all possible filesystems/raids.
462 *
463 * 1/ basic case -- use the first result:
464 *
465 * if (blkid_do_probe(pr) == 0) {
466 * int nvals = blkid_probe_numof_values(pr);
467 * for (n = 0; n < nvals; n++) {
468 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
469 * printf("%s = %s\n", name, data);
470 * }
471 * }
472 *
473 * 2/ advanced case -- probe for all signatures (don't forget that some
474 * filesystems can co-exist on one volume (e.g. CD-ROM).
475 *
476 * while (blkid_do_probe(pr) == 0) {
477 * int nvals = blkid_probe_numof_values(pr);
478 * ...
479 * }
480 *
481 * The internal probing index (pointer to the last probing function) is
482 * always reseted when you touch probing filter or set a new device. It
483 * means you cannot use:
484 *
485 * blkid_probe_invert_filter()
486 * blkid_probe_filter_usage()
487 * blkid_probe_filter_types()
488 * blkid_probe_reset_filter()
489 * blkid_probe_set_device()
490 *
491 * in the loop (e.g while()) when you iterate on all signatures.
492 */
51410fc6 493int blkid_do_probe(blkid_probe pr)
a0948ffe 494{
a0fc685c 495 int i = 0;
a0948ffe 496
4bf7d601 497 if (!pr || pr->idx < -1)
51410fc6 498 return -1;
a0948ffe 499
51410fc6 500 blkid_probe_reset_vals(pr);
a0948ffe 501
4bf7d601
KZ
502 DBG(DEBUG_LOWPROBE,
503 printf("--> starting probing loop [idx=%d]\n",
504 pr->idx));
a0fc685c 505
4bf7d601 506 i = pr->idx + 1;
6644688a 507
a2f01a1c 508 for ( ; i < ARRAY_SIZE(idinfos); i++) {
51410fc6
KZ
509 const struct blkid_idinfo *id;
510 const struct blkid_idmag *mag;
2d4f7576 511 int hasmag = 0;
a0948ffe 512
a0fc685c
KZ
513 pr->idx = i;
514
51410fc6
KZ
515 if (pr->fltr && blkid_bmp_get_item(pr->fltr, i))
516 continue;
a0948ffe 517
51410fc6
KZ
518 id = idinfos[i];
519 mag = id->magics ? &id->magics[0] : NULL;
a0948ffe 520
51410fc6
KZ
521 /* try to detect by magic string */
522 while(mag && mag->magic) {
523 int idx;
524 unsigned char *buf;
a0948ffe 525
51410fc6
KZ
526 idx = mag->kboff + (mag->sboff >> 10);
527 buf = blkid_probe_get_buffer(pr, idx << 10, 1024);
a0948ffe 528
51410fc6 529 if (buf && !memcmp(mag->magic,
6644688a
KZ
530 buf + (mag->sboff & 0x3ff), mag->len)) {
531 DBG(DEBUG_LOWPROBE, printf(
92163c45
KZ
532 "%s: magic sboff=%u, kboff=%ld\n",
533 id->name, mag->sboff, mag->kboff));
2d4f7576 534 hasmag = 1;
51410fc6 535 break;
6644688a 536 }
51410fc6
KZ
537 mag++;
538 }
a0948ffe 539
2d4f7576 540 if (hasmag == 0 && id->magics && id->magics[0].magic)
51410fc6
KZ
541 /* magic string(s) defined, but not found */
542 continue;
a0948ffe 543
51410fc6 544 /* final check by probing function */
6644688a
KZ
545 if (id->probefunc) {
546 DBG(DEBUG_LOWPROBE, printf(
92163c45 547 "%s: call probefunc()\n", id->name));
6644688a
KZ
548 if (id->probefunc(pr, mag) != 0)
549 continue;
550 }
a0948ffe 551
51410fc6
KZ
552 /* all cheks passed */
553 if (pr->probreq & BLKID_PROBREQ_TYPE)
554 blkid_probe_set_value(pr, "TYPE",
555 (unsigned char *) id->name,
556 strlen(id->name) + 1);
51410fc6
KZ
557 if (pr->probreq & BLKID_PROBREQ_USAGE)
558 blkid_probe_set_usage(pr, id->usage);
a0948ffe 559
5b6215b5 560 DBG(DEBUG_LOWPROBE,
4bf7d601
KZ
561 printf("<-- leaving probing loop (type=%s) [idx=%d]\n",
562 id->name, pr->idx));
51410fc6
KZ
563 return 0;
564 }
4bf7d601
KZ
565 DBG(DEBUG_LOWPROBE,
566 printf("<-- leaving probing loop (failed) [idx=%d]\n",
567 pr->idx));
51410fc6 568 return 1;
a0948ffe
KZ
569}
570
a2f01a1c
KZ
571/*
572 * This is the same function as blkid_do_probe(), but returns only one result
573 * (cannot be used in while()) and checks for ambivalen results (more
574 * filesystems on the device) -- in such case returns -2.
7103157c
KZ
575 *
576 * The function does not check for filesystems when a RAID signature is
577 * detected. The function also does not check for collision between RAIDs. The
578 * first detected RAID is returned.
a2f01a1c
KZ
579 */
580int blkid_do_safeprobe(blkid_probe pr)
581{
582 struct blkid_struct_probe first;
583 int count = 0;
584 int intol = 0;
585 int rc;
586
587 while ((rc = blkid_do_probe(pr)) == 0) {
588 if (!count) {
589 /* store the fist result */
590 memcpy(first.vals, pr->vals, sizeof(first.vals));
591 first.nvals = pr->nvals;
592 first.idx = pr->idx;
593 }
7103157c
KZ
594 count++;
595
596 if (idinfos[pr->idx]->usage & BLKID_USAGE_RAID)
597 break;
a2f01a1c
KZ
598 if (!(idinfos[pr->idx]->flags & BLKID_IDINFO_TOLERANT))
599 intol++;
a2f01a1c
KZ
600 }
601 if (rc < 0)
602 return rc; /* error */
92163c45
KZ
603 if (count > 1 && intol) {
604 DBG(DEBUG_LOWPROBE,
605 printf("ERROR: ambivalent result detected (%d filesystems)!\n",
606 count));
a2f01a1c 607 return -2; /* error, ambivalent result (more FS) */
92163c45 608 }
a2f01a1c
KZ
609 if (!count)
610 return 1; /* nothing detected */
611
612 /* restore the first result */
613 memcpy(pr->vals, first.vals, sizeof(first.vals));
614 pr->nvals = first.nvals;
615 pr->idx = first.idx;
616
617 return 0;
618}
619
51410fc6 620int blkid_probe_numof_values(blkid_probe pr)
a0948ffe 621{
51410fc6
KZ
622 if (!pr)
623 return -1;
624 return pr->nvals;
a0948ffe
KZ
625}
626
9bdf6885 627struct blkid_prval *blkid_probe_assign_value(
51410fc6 628 blkid_probe pr, const char *name)
a0948ffe 629{
51410fc6 630 struct blkid_prval *v;
a0948ffe 631
51410fc6
KZ
632 if (!name)
633 return NULL;
924fe747 634 if (pr->nvals >= BLKID_NVALS)
51410fc6 635 return NULL;
a0948ffe 636
51410fc6
KZ
637 v = &pr->vals[pr->nvals];
638 v->name = name;
9bdf6885 639 v->chain = pr->cur_chain;
51410fc6 640 pr->nvals++;
6644688a 641
9bdf6885
KZ
642 DBG(DEBUG_LOWPROBE,
643 printf("assigning %s [%s]\n", name, v->chain->driver->name));
51410fc6 644 return v;
a0948ffe
KZ
645}
646
51410fc6
KZ
647int blkid_probe_set_value(blkid_probe pr, const char *name,
648 unsigned char *data, size_t len)
a0948ffe 649{
51410fc6 650 struct blkid_prval *v;
a0948ffe 651
51410fc6
KZ
652 if (len > BLKID_PROBVAL_BUFSIZ)
653 len = BLKID_PROBVAL_BUFSIZ;
a0948ffe 654
51410fc6
KZ
655 v = blkid_probe_assign_value(pr, name);
656 if (!v)
657 return -1;
a0948ffe 658
51410fc6
KZ
659 memcpy(v->data, data, len);
660 v->len = len;
a0948ffe
KZ
661 return 0;
662}
663
51410fc6
KZ
664int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
665 const char *fmt, va_list ap)
a0948ffe 666{
51410fc6
KZ
667 struct blkid_prval *v;
668 size_t len;
a0948ffe 669
51410fc6
KZ
670 v = blkid_probe_assign_value(pr, name);
671 if (!v)
672 return -1;
a0948ffe 673
51410fc6 674 len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
a0948ffe 675
51410fc6
KZ
676 if (len <= 0) {
677 pr->nvals--; /* reset the latest assigned value */
678 return -1;
a0948ffe 679 }
51410fc6 680 v->len = len + 1;
a0948ffe
KZ
681 return 0;
682}
683
51410fc6 684static int blkid_probe_set_usage(blkid_probe pr, int usage)
a0948ffe 685{
51410fc6 686 char *u = NULL;
a0948ffe 687
51410fc6
KZ
688 if (usage & BLKID_USAGE_FILESYSTEM)
689 u = "filesystem";
690 else if (usage & BLKID_USAGE_RAID)
691 u = "raid";
692 else if (usage & BLKID_USAGE_CRYPTO)
693 u = "crypto";
694 else if (usage & BLKID_USAGE_OTHER)
695 u = "other";
696 else
697 u = "unknown";
a0948ffe 698
51410fc6 699 return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1);
a0948ffe
KZ
700}
701
51410fc6 702int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
6d042d0d 703 const char **data, size_t *len)
a0948ffe 704{
51410fc6 705 struct blkid_prval *v;
a0948ffe 706
51410fc6
KZ
707 if (pr == NULL || num < 0 || num >= pr->nvals)
708 return -1;
a0948ffe 709
51410fc6
KZ
710 v = &pr->vals[num];
711 if (name)
712 *name = v->name;
713 if (data)
6d042d0d 714 *data = (char *) v->data;
51410fc6
KZ
715 if (len)
716 *len = v->len;
6644688a
KZ
717
718 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
a0948ffe
KZ
719 return 0;
720}
a0948ffe 721
51410fc6 722int blkid_probe_lookup_value(blkid_probe pr, const char *name,
6d042d0d 723 const char **data, size_t *len)
a0948ffe 724{
51410fc6 725 int i;
a0948ffe 726
51410fc6
KZ
727 if (pr == NULL || pr->nvals == 0 || name == NULL)
728 return -1;
a0948ffe 729
51410fc6
KZ
730 for (i = 0; i < pr->nvals; i++) {
731 struct blkid_prval *v = &pr->vals[i];
a0948ffe 732
51410fc6
KZ
733 if (v->name && strcmp(name, v->name) == 0) {
734 if (data)
6d042d0d 735 *data = (char *) v->data;
51410fc6
KZ
736 if (len)
737 *len = v->len;
6644688a 738 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
51410fc6 739 return 0;
a0948ffe
KZ
740 }
741 }
51410fc6 742 return -1;
a0948ffe
KZ
743}
744
51410fc6 745int blkid_probe_has_value(blkid_probe pr, const char *name)
a0948ffe 746{
51410fc6
KZ
747 if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
748 return 1;
a0948ffe
KZ
749 return 0;
750}
751
1c1726a7
KZ
752struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
753{
754 if (pr == NULL || num < 0 || num >= pr->nvals)
755 return NULL;
756
757 return &pr->vals[num];
758}
759
760struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
761{
762 int i;
763
764 if (pr == NULL || pr->nvals == 0 || name == NULL)
765 return NULL;
766
767 for (i = 0; i < pr->nvals; i++) {
768 struct blkid_prval *v = &pr->vals[i];
769
770 if (v->name && strcmp(name, v->name) == 0) {
771 DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
772 return v;
773 }
774 }
775 return NULL;
776}
777
201529bd
KZ
778
779/* converts DCE UUID (uuid[16]) to human readable string
780 * - the @len should be always 37 */
781void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
782{
783#ifdef HAVE_LIBUUID
784 uuid_unparse(uuid, str);
785#else
786 snprintf(str, len,
787 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
788 uuid[0], uuid[1], uuid[2], uuid[3],
789 uuid[4], uuid[5],
790 uuid[6], uuid[7],
791 uuid[8], uuid[9],
792 uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
793#endif
794}
795