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