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