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