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