1 /*
2 * superblocks.c - reads information from filesystem and raid superblocks
3 *
4 * Copyright (C) 2008-2009 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 #include <sys/stat.h>
18 #include <errno.h>
19 #include <stdint.h>
20 #include <stdarg.h>
21
22 #include "superblocks.h"
23
24 /**
25 * SECTION:superblocks
26 * @title: Superblocks probing
27 * @short_description: filesystems and raids superblocks probing.
28 *
29 * The library API has been originally designed for superblocks probing only.
30 * This is reason why some *deprecated* superblock specific functions don't use
31 * '_superblocks_' namespace in the function name. Please, don't use these
32 * functions in new code.
33 *
34 * The 'superblocks' probers support NAME=value (tags) interface only. The
35 * superblocks probing is enabled by default (and controlled by
36 * blkid_probe_enable_superblocks()).
37 *
38 * Currently supported tags:
39 *
40 * @TYPE: filesystem type
41 *
42 * @SEC_TYPE: secondary filesystem type
43 *
44 * @LABEL: filesystem label
45 *
46 * @LABEL_RAW: raw label from FS superblock
47 *
48 * @UUID: filesystem UUID (lower case)
49 *
50 * @UUID_SUB: subvolume uuid (e.g. btrfs)
51 *
52 * @LOGUUID: external log UUID (e.g. xfs)
53 *
54 * @UUID_RAW: raw UUID from FS superblock
55 *
56 * @EXT_JOURNAL: external journal UUID
57 *
58 * @USAGE: usage string: "raid", "filesystem", ...
59 *
60 * @VERSION: filesystem version
61 *
62 * @MOUNT: cluster mount name (?) -- ocfs only
63 *
64 * @SBMAGIC: super block magic string
65 *
66 * @SBMAGIC_OFFSET: offset of SBMAGIC
67 *
68 * @FSSIZE: size of filesystem [not-implemented yet]
69 *
70 * @SYSTEM_ID: ISO9660 system identifier
71 *
72 * @PUBLISHER_ID: ISO9660 publisher identifier
73 *
74 * @APPLICATION_ID: ISO9660 application identifier
75 *
76 * @BOOT_SYSTEM_ID: ISO9660 boot system identifier
77 *
78 * @BLOCK_SIZE: block size
79 */
80
81 static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn);
82 static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn);
83
84 static int blkid_probe_set_usage(blkid_probe pr, int usage);
85
86
87 /*
88 * Superblocks chains probing functions
89 */
90 static const struct blkid_idinfo *idinfos[] =
91 {
92 /* RAIDs */
93 &linuxraid_idinfo,
94 &ddfraid_idinfo,
95 &iswraid_idinfo,
96 &lsiraid_idinfo,
97 &viaraid_idinfo,
98 &silraid_idinfo,
99 &nvraid_idinfo,
100 &pdcraid_idinfo,
101 &highpoint45x_idinfo,
102 &highpoint37x_idinfo,
103 &adraid_idinfo,
104 &jmraid_idinfo,
105
106 &bcache_idinfo,
107 &bluestore_idinfo,
108 &drbd_idinfo,
109 &drbdmanage_idinfo,
110 &drbdproxy_datalog_idinfo,
111 &lvm2_idinfo,
112 &lvm1_idinfo,
113 &snapcow_idinfo,
114 &verity_hash_idinfo,
115 &integrity_idinfo,
116 &luks_idinfo,
117 &vmfs_volume_idinfo,
118 &ubi_idinfo,
119 &vdo_idinfo,
120 &stratis_idinfo,
121 &bitlocker_idinfo,
122
123 /* Filesystems */
124 &vfat_idinfo,
125 &swsuspend_idinfo,
126 &swap_idinfo,
127 &xfs_idinfo,
128 &xfs_log_idinfo,
129 &exfs_idinfo,
130 &ext4dev_idinfo,
131 &ext4_idinfo,
132 &ext3_idinfo,
133 &ext2_idinfo,
134 &jbd_idinfo,
135 &reiser_idinfo,
136 &reiser4_idinfo,
137 &jfs_idinfo,
138 &udf_idinfo,
139 &iso9660_idinfo,
140 &zfs_idinfo,
141 &hfsplus_idinfo,
142 &hfs_idinfo,
143 &ufs_idinfo,
144 &hpfs_idinfo,
145 &sysv_idinfo,
146 &xenix_idinfo,
147 &ntfs_idinfo,
148 &refs_idinfo,
149 &cramfs_idinfo,
150 &romfs_idinfo,
151 &minix_idinfo,
152 &gfs_idinfo,
153 &gfs2_idinfo,
154 &ocfs_idinfo,
155 &ocfs2_idinfo,
156 &oracleasm_idinfo,
157 &vxfs_idinfo,
158 &squashfs_idinfo,
159 &squashfs3_idinfo,
160 &netware_idinfo,
161 &btrfs_idinfo,
162 &ubifs_idinfo,
163 &bfs_idinfo,
164 &vmfs_fs_idinfo,
165 &befs_idinfo,
166 &nilfs2_idinfo,
167 &exfat_idinfo,
168 &f2fs_idinfo,
169 &mpool_idinfo,
170 &apfs_idinfo,
171 &zonefs_idinfo
172 };
173
174 /*
175 * Driver definition
176 */
177 const struct blkid_chaindrv superblocks_drv = {
178 .id = BLKID_CHAIN_SUBLKS,
179 .name = "superblocks",
180 .dflt_enabled = TRUE,
181 .dflt_flags = BLKID_SUBLKS_DEFAULT,
182 .idinfos = idinfos,
183 .nidinfos = ARRAY_SIZE(idinfos),
184 .has_fltr = TRUE,
185 .probe = superblocks_probe,
186 .safeprobe = superblocks_safeprobe,
187 };
188
189 /**
190 * blkid_probe_enable_superblocks:
191 * @pr: probe
192 * @enable: TRUE/FALSE
193 *
194 * Enables/disables the superblocks probing for non-binary interface.
195 *
196 * Returns: 0 on success, or -1 in case of error.
197 */
blkid_probe_enable_superblocks(blkid_probe pr,int enable)198 int blkid_probe_enable_superblocks(blkid_probe pr, int enable)
199 {
200 pr->chains[BLKID_CHAIN_SUBLKS].enabled = enable;
201 return 0;
202 }
203
204 /**
205 * blkid_probe_set_superblocks_flags:
206 * @pr: prober
207 * @flags: BLKID_SUBLKS_* flags
208 *
209 * Sets probing flags to the superblocks prober. This function is optional, the
210 * default are BLKID_SUBLKS_DEFAULTS flags.
211 *
212 * Returns: 0 on success, or -1 in case of error.
213 */
blkid_probe_set_superblocks_flags(blkid_probe pr,int flags)214 int blkid_probe_set_superblocks_flags(blkid_probe pr, int flags)
215 {
216 pr->chains[BLKID_CHAIN_SUBLKS].flags = flags;
217 return 0;
218 }
219
220 /**
221 * blkid_probe_reset_superblocks_filter:
222 * @pr: prober
223 *
224 * Resets superblocks probing filter
225 *
226 * Returns: 0 on success, or -1 in case of error.
227 */
blkid_probe_reset_superblocks_filter(blkid_probe pr)228 int blkid_probe_reset_superblocks_filter(blkid_probe pr)
229 {
230 return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS);
231 }
232
233 /**
234 * blkid_probe_invert_superblocks_filter:
235 * @pr: prober
236 *
237 * Inverts superblocks probing filter
238 *
239 * Returns: 0 on success, or -1 in case of error.
240 */
blkid_probe_invert_superblocks_filter(blkid_probe pr)241 int blkid_probe_invert_superblocks_filter(blkid_probe pr)
242 {
243 return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS);
244 }
245
246 /**
247 * blkid_probe_filter_superblocks_type:
248 * @pr: prober
249 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
250 * @names: NULL terminated array of probing function names (e.g. "vfat").
251 *
252 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names;
253 *
254 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
255 *
256 * Returns: 0 on success, or -1 in case of error.
257 */
blkid_probe_filter_superblocks_type(blkid_probe pr,int flag,char * names[])258 int blkid_probe_filter_superblocks_type(blkid_probe pr, int flag, char *names[])
259 {
260 return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names);
261 }
262
263 /**
264 * blkid_probe_filter_superblocks_usage:
265 * @pr: prober
266 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
267 * @usage: BLKID_USAGE_* flags
268 *
269 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @usage;
270 *
271 * %BLKID_FLTR_ONLYIN - probe for items which are IN @usage
272 *
273 * Returns: 0 on success, or -1 in case of error.
274 */
blkid_probe_filter_superblocks_usage(blkid_probe pr,int flag,int usage)275 int blkid_probe_filter_superblocks_usage(blkid_probe pr, int flag, int usage)
276 {
277 unsigned long *fltr;
278 struct blkid_chain *chn;
279 size_t i;
280
281 fltr = blkid_probe_get_filter(pr, BLKID_CHAIN_SUBLKS, TRUE);
282 if (!fltr)
283 return -1;
284
285 chn = &pr->chains[BLKID_CHAIN_SUBLKS];
286
287 for (i = 0; i < chn->driver->nidinfos; i++) {
288 const struct blkid_idinfo *id = chn->driver->idinfos[i];
289
290 if (id->usage & usage) {
291 if (flag & BLKID_FLTR_NOTIN)
292 blkid_bmp_set_item(chn->fltr, i);
293 } else if (flag & BLKID_FLTR_ONLYIN)
294 blkid_bmp_set_item(chn->fltr, i);
295 }
296 DBG(LOWPROBE, ul_debug("a new probing usage-filter initialized"));
297 return 0;
298 }
299
300 /**
301 * blkid_known_fstype:
302 * @fstype: filesystem name
303 *
304 * Returns: 1 for known filesystems, or 0 for unknown filesystem.
305 */
blkid_known_fstype(const char * fstype)306 int blkid_known_fstype(const char *fstype)
307 {
308 size_t i;
309
310 for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
311 const struct blkid_idinfo *id = idinfos[i];
312 if (strcmp(id->name, fstype) == 0)
313 return 1;
314 }
315 return 0;
316 }
317
318 /**
319 * blkid_superblocks_get_name:
320 * @idx: number >= 0
321 * @name: returns name of supported filesystem/raid (optional)
322 * @usage: returns BLKID_USAGE_* flags, (optional)
323 *
324 * Returns: -1 if @idx is out of range, or 0 on success.
325 */
blkid_superblocks_get_name(size_t idx,const char ** name,int * usage)326 int blkid_superblocks_get_name(size_t idx, const char **name, int *usage)
327 {
328 if (idx < ARRAY_SIZE(idinfos)) {
329 if (name)
330 *name = idinfos[idx]->name;
331 if (usage)
332 *usage = idinfos[idx]->usage;
333 return 0;
334 }
335 return -1;
336 }
337
338 /*
339 * The blkid_do_probe() backend.
340 */
superblocks_probe(blkid_probe pr,struct blkid_chain * chn)341 static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
342 {
343 size_t i;
344 int rc = BLKID_PROBE_NONE;
345
346 if (chn->idx < -1)
347 return -EINVAL;
348
349 blkid_probe_chain_reset_values(pr, chn);
350
351 if (pr->flags & BLKID_FL_NOSCAN_DEV) {
352 DBG(LOWPROBE, ul_debug("*** ignore (noscan flag)"));
353 return BLKID_PROBE_NONE;
354 }
355
356 if (pr->size <= 0 || (pr->size <= 1024 && !S_ISCHR(pr->mode))) {
357 /* Ignore very very small block devices or regular files (e.g.
358 * extended partitions). Note that size of the UBI char devices
359 * is 1 byte */
360 DBG(LOWPROBE, ul_debug("*** ignore (size <= 1024)"));
361 return BLKID_PROBE_NONE;
362 }
363
364 DBG(LOWPROBE, ul_debug("--> starting probing loop [SUBLKS idx=%d]",
365 chn->idx));
366
367 i = chn->idx < 0 ? 0 : chn->idx + 1U;
368
369 for ( ; i < ARRAY_SIZE(idinfos); i++) {
370 const struct blkid_idinfo *id;
371 const struct blkid_idmag *mag = NULL;
372 uint64_t off = 0;
373
374 chn->idx = i;
375 id = idinfos[i];
376
377 if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) {
378 DBG(LOWPROBE, ul_debug("filter out: %s", id->name));
379 rc = BLKID_PROBE_NONE;
380 continue;
381 }
382
383 if (id->minsz && (unsigned)id->minsz > pr->size) {
384 rc = BLKID_PROBE_NONE;
385 continue; /* the device is too small */
386 }
387
388 /* don't probe for RAIDs, swap or journal on CD/DVDs */
389 if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) &&
390 blkid_probe_is_cdrom(pr)) {
391 rc = BLKID_PROBE_NONE;
392 continue;
393 }
394
395 /* don't probe for RAIDs on floppies */
396 if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) {
397 rc = BLKID_PROBE_NONE;
398 continue;
399 }
400
401 DBG(LOWPROBE, ul_debug("[%zd] %s:", i, id->name));
402
403 rc = blkid_probe_get_idmag(pr, id, &off, &mag);
404 if (rc < 0)
405 break;
406 if (rc != BLKID_PROBE_OK)
407 continue;
408
409 /* final check by probing function */
410 if (id->probefunc) {
411 DBG(LOWPROBE, ul_debug("\tcall probefunc()"));
412 rc = id->probefunc(pr, mag);
413 if (rc != BLKID_PROBE_OK) {
414 blkid_probe_chain_reset_values(pr, chn);
415 if (rc < 0)
416 break;
417 continue;
418 }
419 }
420
421 /* all checks passed */
422 if (chn->flags & BLKID_SUBLKS_TYPE)
423 rc = blkid_probe_set_value(pr, "TYPE",
424 (const unsigned char *) id->name,
425 strlen(id->name) + 1);
426
427 if (!rc)
428 rc = blkid_probe_set_usage(pr, id->usage);
429
430 if (!rc && mag)
431 rc = blkid_probe_set_magic(pr, off, mag->len,
432 (const unsigned char *) mag->magic);
433 if (rc) {
434 blkid_probe_chain_reset_values(pr, chn);
435 DBG(LOWPROBE, ul_debug("failed to set result -- ignore"));
436 continue;
437 }
438
439 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]",
440 id->name, chn->idx));
441 return BLKID_PROBE_OK;
442 }
443
444 DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]",
445 rc, chn->idx));
446 return rc;
447 }
448
449 /*
450 * This is the same function as blkid_do_probe(), but returns only one result
451 * (cannot be used in while()) and checks for ambivalent results (more
452 * filesystems on the device) -- in such case returns -2.
453 *
454 * The function does not check for filesystems when a RAID or crypto signature
455 * is detected. The function also does not check for collision between RAIDs
456 * and crypto devices. The first detected RAID or crypto device is returned.
457 *
458 * The function does not probe for ambivalent results on very small devices
459 * (e.g. floppies), on small devices the first detected filesystem is returned.
460 */
superblocks_safeprobe(blkid_probe pr,struct blkid_chain * chn)461 static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
462 {
463 struct list_head vals;
464 int idx = -1;
465 int count = 0;
466 int intol = 0;
467 int rc;
468
469 INIT_LIST_HEAD(&vals);
470
471 if (pr->flags & BLKID_FL_NOSCAN_DEV)
472 return BLKID_PROBE_NONE;
473
474 while ((rc = superblocks_probe(pr, chn)) == 0) {
475
476 if (blkid_probe_is_tiny(pr) && !count)
477 return BLKID_PROBE_OK; /* floppy or so -- returns the first result. */
478
479 count++;
480
481 if (chn->idx >= 0 &&
482 idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO))
483 break;
484
485 if (chn->idx >= 0 &&
486 !(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
487 intol++;
488
489 if (count == 1) {
490 /* save the first result */
491 blkid_probe_chain_save_values(pr, chn, &vals);
492 idx = chn->idx;
493 }
494 }
495
496 if (rc < 0)
497 goto done; /* error */
498
499 if (count > 1 && intol) {
500 DBG(LOWPROBE, ul_debug("ERROR: superblocks chain: "
501 "ambivalent result detected (%d filesystems)!",
502 count));
503 rc = -2; /* error, ambivalent result (more FS) */
504 goto done;
505 }
506 if (!count) {
507 rc = BLKID_PROBE_NONE;
508 goto done;
509 }
510
511 if (idx != -1) {
512 /* restore the first result */
513 blkid_probe_chain_reset_values(pr, chn);
514 blkid_probe_append_values_list(pr, &vals);
515 chn->idx = idx;
516 }
517
518 /*
519 * The RAID device could be partitioned. The problem are RAID1 devices
520 * where the partition table is visible from underlying devices. We
521 * have to ignore such partition tables.
522 */
523 if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
524 pr->prob_flags |= BLKID_PROBE_FL_IGNORE_PT;
525
526 rc = BLKID_PROBE_OK;
527 done:
528 blkid_probe_free_values_list(&vals);
529 return rc;
530 }
531
blkid_probe_set_version(blkid_probe pr,const char * version)532 int blkid_probe_set_version(blkid_probe pr, const char *version)
533 {
534 struct blkid_chain *chn = blkid_probe_get_chain(pr);
535
536 if (chn->flags & BLKID_SUBLKS_VERSION)
537 return blkid_probe_set_value(pr, "VERSION",
538 (const unsigned char *) version,
539 strlen(version) + 1);
540 return 0;
541 }
542
543
blkid_probe_sprintf_version(blkid_probe pr,const char * fmt,...)544 int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
545 {
546 struct blkid_chain *chn = blkid_probe_get_chain(pr);
547 int rc = 0;
548
549 if (chn->flags & BLKID_SUBLKS_VERSION) {
550 va_list ap;
551
552 va_start(ap, fmt);
553 rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap);
554 va_end(ap);
555 }
556 return rc;
557 }
558
blkid_probe_set_block_size(blkid_probe pr,unsigned block_size)559 int blkid_probe_set_block_size(blkid_probe pr, unsigned block_size)
560 {
561 return blkid_probe_sprintf_value(pr, "BLOCK_SIZE", "%u", block_size);
562 }
563
blkid_probe_set_usage(blkid_probe pr,int usage)564 static int blkid_probe_set_usage(blkid_probe pr, int usage)
565 {
566 struct blkid_chain *chn = blkid_probe_get_chain(pr);
567 char *u = NULL;
568
569 if (!(chn->flags & BLKID_SUBLKS_USAGE))
570 return 0;
571
572 if (usage & BLKID_USAGE_FILESYSTEM)
573 u = "filesystem";
574 else if (usage & BLKID_USAGE_RAID)
575 u = "raid";
576 else if (usage & BLKID_USAGE_CRYPTO)
577 u = "crypto";
578 else if (usage & BLKID_USAGE_OTHER)
579 u = "other";
580 else
581 u = "unknown";
582
583 return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1);
584 }
585
blkid_probe_set_id_label(blkid_probe pr,const char * name,const unsigned char * data,size_t len)586 int blkid_probe_set_id_label(blkid_probe pr, const char *name,
587 const unsigned char *data, size_t len)
588 {
589 struct blkid_chain *chn = blkid_probe_get_chain(pr);
590 struct blkid_prval *v;
591 int rc = 0;
592
593 if (!(chn->flags & BLKID_SUBLKS_LABEL))
594 return 0;
595
596 v = blkid_probe_assign_value(pr, name);
597 if (!v)
598 return -ENOMEM;
599
600 rc = blkid_probe_value_set_data(v, data, len);
601 if (!rc) {
602 /* remove white spaces */
603 v->len = blkid_rtrim_whitespace(v->data) + 1;
604 if (v->len > 1)
605 v->len = blkid_ltrim_whitespace(v->data) + 1;
606 if (v->len > 1)
607 return 0;
608 }
609
610 blkid_probe_free_value(v);
611 return rc;
612
613 }
614
blkid_probe_set_utf8_id_label(blkid_probe pr,const char * name,const unsigned char * data,size_t len,int enc)615 int blkid_probe_set_utf8_id_label(blkid_probe pr, const char *name,
616 const unsigned char *data, size_t len, int enc)
617 {
618 struct blkid_chain *chn = blkid_probe_get_chain(pr);
619 struct blkid_prval *v;
620 int rc = 0;
621
622 if (!(chn->flags & BLKID_SUBLKS_LABEL))
623 return 0;
624
625 v = blkid_probe_assign_value(pr, name);
626 if (!v)
627 return -ENOMEM;
628
629 v->len = (len * 3) + 1;
630 v->data = calloc(1, v->len);
631 if (!v->data)
632 rc = -ENOMEM;
633
634 if (!rc) {
635 ul_encode_to_utf8(enc, v->data, v->len, data, len);
636 v->len = blkid_rtrim_whitespace(v->data) + 1;
637 if (v->len > 1)
638 v->len = blkid_ltrim_whitespace(v->data) + 1;
639 if (v->len > 1)
640 return 0;
641 }
642
643 blkid_probe_free_value(v);
644 return rc;
645 }
646
blkid_probe_set_label(blkid_probe pr,const unsigned char * label,size_t len)647 int blkid_probe_set_label(blkid_probe pr, const unsigned char *label, size_t len)
648 {
649 struct blkid_chain *chn = blkid_probe_get_chain(pr);
650 struct blkid_prval *v;
651 int rc = 0;
652
653 if ((chn->flags & BLKID_SUBLKS_LABELRAW) &&
654 (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0)
655 return rc;
656
657 if (!(chn->flags & BLKID_SUBLKS_LABEL))
658 return 0;
659
660 v = blkid_probe_assign_value(pr, "LABEL");
661 if (!v)
662 return -ENOMEM;
663
664 rc = blkid_probe_value_set_data(v, label, len);
665 if (!rc) {
666 v->len = blkid_rtrim_whitespace(v->data) + 1;
667 if (v->len > 1)
668 return 0;
669 }
670
671 blkid_probe_free_value(v);
672 return rc;
673 }
674
blkid_probe_set_utf8label(blkid_probe pr,const unsigned char * label,size_t len,int enc)675 int blkid_probe_set_utf8label(blkid_probe pr, const unsigned char *label,
676 size_t len, int enc)
677 {
678 struct blkid_chain *chn = blkid_probe_get_chain(pr);
679 struct blkid_prval *v;
680 int rc = 0;
681
682 if ((chn->flags & BLKID_SUBLKS_LABELRAW) &&
683 (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0)
684 return rc;
685
686 if (!(chn->flags & BLKID_SUBLKS_LABEL))
687 return 0;
688
689 v = blkid_probe_assign_value(pr, "LABEL");
690 if (!v)
691 return -ENOMEM;
692
693 v->len = (len * 3) + 1;
694 v->data = calloc(1, v->len);
695 if (!v->data)
696 rc = -ENOMEM;
697 if (!rc) {
698 ul_encode_to_utf8(enc, v->data, v->len, label, len);
699 v->len = blkid_rtrim_whitespace(v->data) + 1;
700 if (v->len > 1)
701 return 0;
702 }
703
704 blkid_probe_free_value(v);
705 return rc;
706 }
707
blkid_probe_sprintf_uuid(blkid_probe pr,const unsigned char * uuid,size_t len,const char * fmt,...)708 int blkid_probe_sprintf_uuid(blkid_probe pr, const unsigned char *uuid,
709 size_t len, const char *fmt, ...)
710 {
711 struct blkid_chain *chn = blkid_probe_get_chain(pr);
712 va_list ap;
713 int rc = 0;
714
715 if (blkid_uuid_is_empty(uuid, len))
716 return 0;
717
718 if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
719 (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, len)) < 0)
720 return rc;
721
722 if (!(chn->flags & BLKID_SUBLKS_UUID))
723 return 0;
724
725 va_start(ap, fmt);
726 rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap);
727 va_end(ap);
728
729 return rc;
730 }
731
732 /* function to set UUIDs that are in superblocks stored as strings */
blkid_probe_strncpy_uuid(blkid_probe pr,const unsigned char * str,size_t len)733 int blkid_probe_strncpy_uuid(blkid_probe pr, const unsigned char *str, size_t len)
734 {
735 struct blkid_chain *chn = blkid_probe_get_chain(pr);
736 struct blkid_prval *v;
737 int rc = 0;
738
739 if (str == NULL || *str == '\0')
740 return -EINVAL;
741
742 if (!len)
743 len = strlen((const char *) str);
744
745 if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
746 (rc = blkid_probe_set_value(pr, "UUID_RAW", str, len)) < 0)
747 return rc;
748
749 if (!(chn->flags & BLKID_SUBLKS_UUID))
750 return 0;
751
752 v = blkid_probe_assign_value(pr, "UUID");
753 if (!v)
754 rc= -ENOMEM;
755 if (!rc)
756 rc = blkid_probe_value_set_data(v, str, len);
757 if (!rc) {
758 v->len = blkid_rtrim_whitespace(v->data) + 1;
759 if (v->len > 1)
760 return 0;
761 }
762
763 blkid_probe_free_value(v);
764 return rc;
765 }
766
767 /* default _set_uuid function to set DCE UUIDs */
blkid_probe_set_uuid_as(blkid_probe pr,const unsigned char * uuid,const char * name)768 int blkid_probe_set_uuid_as(blkid_probe pr, const unsigned char *uuid, const char *name)
769 {
770 struct blkid_chain *chn = blkid_probe_get_chain(pr);
771 struct blkid_prval *v;
772 int rc = 0;
773
774 if (blkid_uuid_is_empty(uuid, 16))
775 return 0;
776
777 if (!name) {
778 if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
779 (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, 16)) < 0)
780 return rc;
781
782 if (!(chn->flags & BLKID_SUBLKS_UUID))
783 return 0;
784
785 v = blkid_probe_assign_value(pr, "UUID");
786 } else
787 v = blkid_probe_assign_value(pr, name);
788
789 if (!v)
790 return -ENOMEM;
791
792 v->len = UUID_STR_LEN;
793 v->data = calloc(1, v->len);
794 if (!v->data)
795 rc = -ENOMEM;
796
797 if (!rc) {
798 blkid_unparse_uuid(uuid, (char *) v->data, v->len);
799 return 0;
800 }
801
802 blkid_probe_free_value(v);
803 return rc;
804 }
805
blkid_probe_set_uuid(blkid_probe pr,const unsigned char * uuid)806 int blkid_probe_set_uuid(blkid_probe pr, const unsigned char *uuid)
807 {
808 return blkid_probe_set_uuid_as(pr, uuid, NULL);
809 }
810
811 /**
812 * blkid_probe_set_request:
813 * @pr: probe
814 * @flags: BLKID_PROBREQ_* (deprecated) or BLKID_SUBLKS_* flags
815 *
816 * Returns: 0 on success, or -1 in case of error.
817 *
818 * Deprecated: Use blkid_probe_set_superblocks_flags().
819 */
blkid_probe_set_request(blkid_probe pr,int flags)820 int blkid_probe_set_request(blkid_probe pr, int flags)
821 {
822 return blkid_probe_set_superblocks_flags(pr, flags);
823 }
824
825 /**
826 * blkid_probe_reset_filter:
827 * @pr: prober
828 *
829 * Returns: 0 on success, or -1 in case of error.
830 *
831 * Deprecated: Use blkid_probe_reset_superblocks_filter().
832 */
blkid_probe_reset_filter(blkid_probe pr)833 int blkid_probe_reset_filter(blkid_probe pr)
834 {
835 return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS);
836 }
837
838 /**
839 * blkid_probe_invert_filter:
840 * @pr: prober
841 *
842 * Returns: 0 on success, or -1 in case of error.
843 *
844 * Deprecated: Use blkid_probe_invert_superblocks_filter().
845 */
blkid_probe_invert_filter(blkid_probe pr)846 int blkid_probe_invert_filter(blkid_probe pr)
847 {
848 return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS);
849 }
850
851 /**
852 * blkid_probe_filter_types
853 * @pr: prober
854 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
855 * @names: NULL terminated array of probing function names (e.g. "vfat").
856 *
857 * Returns: 0 on success, or -1 in case of error.
858 *
859 * Deprecated: Use blkid_probe_filter_superblocks_type().
860 */
blkid_probe_filter_types(blkid_probe pr,int flag,char * names[])861 int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[])
862 {
863 return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names);
864 }
865
866 /**
867 * blkid_probe_filter_usage
868 * @pr: prober
869 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
870 * @usage: BLKID_USAGE_* flags
871 *
872 * Returns: 0 on success, or -1 in case of error.
873 *
874 * Deprecated: Use blkid_probe_filter_superblocks_usage().
875 */
blkid_probe_filter_usage(blkid_probe pr,int flag,int usage)876 int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage)
877 {
878 return blkid_probe_filter_superblocks_usage(pr, flag, usage);
879 }
880
881
882