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