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