]>
Commit | Line | Data |
---|---|---|
0e89abac KZ |
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 | ||
ad08ae0a | 10 | #include <inttypes.h> |
0e89abac KZ |
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 | ||
0e89abac KZ |
23 | #include "superblocks.h" |
24 | ||
25 | /** | |
26 | * SECTION:superblocks | |
27 | * @title: Superblocks probing | |
28 | * @short_description: filesystems and raids superblocks probing. | |
29 | * | |
455fe9a0 | 30 | * The library API has been originally designed for superblocks probing only. |
0e89abac KZ |
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 | |
455fe9a0 | 36 | * superblocks probing is enabled by default (and controlled by |
0e89abac KZ |
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 | * | |
b5d8aac1 KZ |
51 | * @UUID_SUB: subvolume uuid (e.g. btrfs) |
52 | * | |
c57e6f52 | 53 | * @LOGUUID: external log UUID (e.g. xfs) |
0a200255 | 54 | * |
0e89abac KZ |
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 | * | |
92838067 | 65 | * @SBMAGIC: super block magic string |
0e89abac | 66 | * |
92838067 | 67 | * @SBMAGIC_OFFSET: offset of SBMAGIC |
0e89abac | 68 | * |
d9d9a709 | 69 | * @FSSIZE: size of filesystem (implemented for XFS/BTRFS/Ext only) |
fafe46bc | 70 | * |
b7cb26ec AA |
71 | * @FSLASTBLOCK: last fsblock/total number of fsblocks |
72 | * | |
0f447d49 AA |
73 | * @FSBLOCKSIZE: file system block size |
74 | * | |
fafe46bc ZAK |
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 | |
cd129b7d | 82 | * |
895f0b60 | 83 | * @BLOCK_SIZE: minimal block size accessible by file system |
0e89abac KZ |
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 | { | |
49a969dd TW |
97 | /* First, as access to locked OPAL region triggers IO errors */ |
98 | &luks_opal_idinfo, | |
99 | ||
0e89abac KZ |
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, | |
048c6291 | 113 | |
a083b725 | 114 | &bcache_idinfo, |
64094168 | 115 | &bcachefs_idinfo, |
41254972 | 116 | &bluestore_idinfo, |
0834e00a | 117 | &drbd_idinfo, |
2dc8cfb9 | 118 | &drbdmanage_idinfo, |
1e03bc3b | 119 | &drbdproxy_datalog_idinfo, |
0e89abac KZ |
120 | &lvm2_idinfo, |
121 | &lvm1_idinfo, | |
122 | &snapcow_idinfo, | |
cbc729f0 | 123 | &verity_hash_idinfo, |
78f9ecb9 | 124 | &integrity_idinfo, |
93ba7961 | 125 | &luks_idinfo, |
3a1e412f | 126 | &vmfs_volume_idinfo, |
1266fcf9 | 127 | &ubi_idinfo, |
6418cba4 | 128 | &vdo_idinfo, |
f82b085c | 129 | &stratis_idinfo, |
136f89ce | 130 | &bitlocker_idinfo, |
773a1fe3 | 131 | &cs_fvault2_idinfo, |
0e89abac KZ |
132 | |
133 | /* Filesystems */ | |
134 | &vfat_idinfo, | |
135 | &swsuspend_idinfo, | |
136 | &swap_idinfo, | |
137 | &xfs_idinfo, | |
0a200255 | 138 | &xfs_log_idinfo, |
aaf13326 | 139 | &exfs_idinfo, |
0e89abac KZ |
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, | |
84992b8a | 158 | &refs_idinfo, |
0e89abac KZ |
159 | &cramfs_idinfo, |
160 | &romfs_idinfo, | |
a9a298ca AK |
161 | &scoutfs_meta_idinfo, |
162 | &scoutfs_data_idinfo, | |
0e89abac KZ |
163 | &minix_idinfo, |
164 | &gfs_idinfo, | |
165 | &gfs2_idinfo, | |
166 | &ocfs_idinfo, | |
167 | &ocfs2_idinfo, | |
168 | &oracleasm_idinfo, | |
169 | &vxfs_idinfo, | |
170 | &squashfs_idinfo, | |
11402f5e | 171 | &squashfs3_idinfo, |
0e89abac | 172 | &netware_idinfo, |
4b297604 | 173 | &btrfs_idinfo, |
e38ccfcd | 174 | &ubifs_idinfo, |
3a1e412f | 175 | &bfs_idinfo, |
5f9fb168 | 176 | &vmfs_fs_idinfo, |
8604c255 | 177 | &befs_idinfo, |
b44b8600 | 178 | &nilfs2_idinfo, |
7dcfc89e | 179 | &exfat_idinfo, |
b0a89709 | 180 | &f2fs_idinfo, |
084f092a | 181 | &mpool_idinfo, |
9d691cbc | 182 | &apfs_idinfo, |
7b2a874e | 183 | &zonefs_idinfo, |
0945f02e | 184 | &erofs_idinfo, |
0e89abac KZ |
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, | |
861902b5 | 199 | .safeprobe = superblocks_safeprobe, |
0e89abac KZ |
200 | }; |
201 | ||
b7f9a38d KZ |
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 | { | |
b7f9a38d KZ |
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 | { | |
b7f9a38d KZ |
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 | * | |
fd7c9e35 KZ |
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 | |
b7f9a38d KZ |
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 | * | |
fd7c9e35 KZ |
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 | |
b7f9a38d KZ |
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; | |
538a2fe9 | 292 | size_t i; |
b7f9a38d | 293 | |
b7f9a38d KZ |
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 | } | |
c62a6311 | 309 | DBG(LOWPROBE, ul_debug("a new probing usage-filter initialized")); |
b7f9a38d KZ |
310 | return 0; |
311 | } | |
312 | ||
8287d790 KZ |
313 | /** |
314 | * blkid_known_fstype: | |
315 | * @fstype: filesystem name | |
316 | * | |
9e930041 | 317 | * Returns: 1 for known filesystems, or 0 for unknown filesystem. |
8287d790 KZ |
318 | */ |
319 | int blkid_known_fstype(const char *fstype) | |
320 | { | |
538a2fe9 | 321 | size_t i; |
8287d790 | 322 | |
8287d790 KZ |
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 | ||
70db6c7e KZ |
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 | { | |
538a2fe9 | 341 | if (idx < ARRAY_SIZE(idinfos)) { |
70db6c7e KZ |
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 | ||
0e89abac KZ |
351 | /* |
352 | * The blkid_do_probe() backend. | |
353 | */ | |
354 | static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) | |
355 | { | |
538a2fe9 | 356 | size_t i; |
296d96e2 | 357 | int rc = BLKID_PROBE_NONE; |
0e89abac | 358 | |
7f787ced | 359 | if (chn->idx < -1) |
296d96e2 | 360 | return -EINVAL; |
20e1c3dc | 361 | |
af17d349 | 362 | blkid_probe_chain_reset_values(pr, chn); |
0e89abac | 363 | |
b480afca KZ |
364 | if (pr->flags & BLKID_FL_NOSCAN_DEV) { |
365 | DBG(LOWPROBE, ul_debug("*** ignore (noscan flag)")); | |
d2a8b8d1 | 366 | return BLKID_PROBE_NONE; |
b480afca | 367 | } |
0e89abac | 368 | |
b480afca | 369 | if (pr->size <= 0 || (pr->size <= 1024 && !S_ISCHR(pr->mode))) { |
108013b4 KZ |
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 */ | |
b480afca | 373 | DBG(LOWPROBE, ul_debug("*** ignore (size <= 1024)")); |
d2a8b8d1 | 374 | return BLKID_PROBE_NONE; |
b480afca | 375 | } |
d2a8b8d1 KZ |
376 | |
377 | DBG(LOWPROBE, ul_debug("--> starting probing loop [SUBLKS idx=%d]", | |
378 | chn->idx)); | |
108013b4 | 379 | |
538a2fe9 | 380 | i = chn->idx < 0 ? 0 : chn->idx + 1U; |
0e89abac KZ |
381 | |
382 | for ( ; i < ARRAY_SIZE(idinfos); i++) { | |
383 | const struct blkid_idinfo *id; | |
c76e710b | 384 | const struct blkid_idmag *mag = NULL; |
f12cd8d1 | 385 | uint64_t off = 0; |
92838067 | 386 | |
0e89abac | 387 | chn->idx = i; |
f3464ff4 | 388 | id = idinfos[i]; |
0e89abac | 389 | |
f3464ff4 | 390 | if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) { |
c62a6311 | 391 | DBG(LOWPROBE, ul_debug("filter out: %s", id->name)); |
296d96e2 | 392 | rc = BLKID_PROBE_NONE; |
0e89abac | 393 | continue; |
f3464ff4 | 394 | } |
8c2b156e | 395 | |
b9710f1f | 396 | if (id->minsz && (unsigned)id->minsz > pr->size) { |
296d96e2 | 397 | rc = BLKID_PROBE_NONE; |
8c2b156e | 398 | continue; /* the device is too small */ |
296d96e2 | 399 | } |
8c2b156e | 400 | |
69b3afc0 | 401 | /* don't probe for RAIDs, swap or journal on CD/DVDs */ |
8c2b156e | 402 | if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) && |
296d96e2 HR |
403 | blkid_probe_is_cdrom(pr)) { |
404 | rc = BLKID_PROBE_NONE; | |
108013b4 | 405 | continue; |
296d96e2 | 406 | } |
108013b4 | 407 | |
69b3afc0 | 408 | /* don't probe for RAIDs on floppies */ |
296d96e2 HR |
409 | if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) { |
410 | rc = BLKID_PROBE_NONE; | |
55113b15 | 411 | continue; |
296d96e2 | 412 | } |
55113b15 | 413 | |
c62a6311 | 414 | DBG(LOWPROBE, ul_debug("[%zd] %s:", i, id->name)); |
108013b4 | 415 | |
296d96e2 HR |
416 | rc = blkid_probe_get_idmag(pr, id, &off, &mag); |
417 | if (rc < 0) | |
418 | break; | |
419 | if (rc != BLKID_PROBE_OK) | |
0e89abac KZ |
420 | continue; |
421 | ||
422 | /* final check by probing function */ | |
423 | if (id->probefunc) { | |
c62a6311 | 424 | DBG(LOWPROBE, ul_debug("\tcall probefunc()")); |
f1a5ad69 | 425 | errno = 0; |
296d96e2 | 426 | rc = id->probefunc(pr, mag); |
77b85278 | 427 | blkid_probe_prune_buffers(pr); |
296d96e2 | 428 | if (rc != BLKID_PROBE_OK) { |
af17d349 | 429 | blkid_probe_chain_reset_values(pr, chn); |
296d96e2 HR |
430 | if (rc < 0) |
431 | break; | |
0e89abac | 432 | continue; |
0e753e3e | 433 | } |
0e89abac KZ |
434 | } |
435 | ||
9e930041 | 436 | /* all checks passed */ |
0e89abac | 437 | if (chn->flags & BLKID_SUBLKS_TYPE) |
a2b9ff9a | 438 | rc = blkid_probe_set_value(pr, "TYPE", |
47afae0c | 439 | (const unsigned char *) id->name, |
0e89abac | 440 | strlen(id->name) + 1); |
92838067 | 441 | |
a2b9ff9a KZ |
442 | if (!rc) |
443 | rc = blkid_probe_set_usage(pr, id->usage); | |
0e89abac | 444 | |
a2b9ff9a KZ |
445 | if (!rc && mag) |
446 | rc = blkid_probe_set_magic(pr, off, mag->len, | |
47afae0c | 447 | (const unsigned char *) mag->magic); |
a2b9ff9a | 448 | if (rc) { |
af17d349 | 449 | blkid_probe_chain_reset_values(pr, chn); |
d2a8b8d1 | 450 | DBG(LOWPROBE, ul_debug("failed to set result -- ignore")); |
a2b9ff9a KZ |
451 | continue; |
452 | } | |
92838067 | 453 | |
c62a6311 | 454 | DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]", |
0e89abac | 455 | id->name, chn->idx)); |
296d96e2 | 456 | return BLKID_PROBE_OK; |
0e89abac | 457 | } |
046959cc | 458 | |
c62a6311 | 459 | DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]", |
296d96e2 HR |
460 | rc, chn->idx)); |
461 | return rc; | |
0e89abac KZ |
462 | } |
463 | ||
464 | /* | |
465 | * This is the same function as blkid_do_probe(), but returns only one result | |
9e930041 | 466 | * (cannot be used in while()) and checks for ambivalent results (more |
0e89abac KZ |
467 | * filesystems on the device) -- in such case returns -2. |
468 | * | |
048c6291 SJR |
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. | |
108013b4 KZ |
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. | |
0e89abac KZ |
475 | */ |
476 | static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn) | |
477 | { | |
6c4a7811 | 478 | struct list_head vals; |
0e89abac KZ |
479 | int idx = -1; |
480 | int count = 0; | |
481 | int intol = 0; | |
90a2086e | 482 | int rc; |
0e89abac | 483 | |
6c4a7811 OO |
484 | INIT_LIST_HEAD(&vals); |
485 | ||
20e1c3dc | 486 | if (pr->flags & BLKID_FL_NOSCAN_DEV) |
d2a8b8d1 | 487 | return BLKID_PROBE_NONE; |
20e1c3dc | 488 | |
0e89abac | 489 | while ((rc = superblocks_probe(pr, chn)) == 0) { |
108013b4 | 490 | |
90a2086e | 491 | if (blkid_probe_is_tiny(pr) && !count) |
d2a8b8d1 | 492 | return BLKID_PROBE_OK; /* floppy or so -- returns the first result. */ |
90a2086e | 493 | |
0e89abac KZ |
494 | count++; |
495 | ||
3be35981 KZ |
496 | if (chn->idx >= 0 && |
497 | idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO)) | |
0e89abac | 498 | break; |
90a2086e | 499 | |
3be35981 KZ |
500 | if (chn->idx >= 0 && |
501 | !(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT)) | |
0e89abac | 502 | intol++; |
c81e7008 | 503 | |
90a2086e KZ |
504 | if (count == 1) { |
505 | /* save the first result */ | |
af17d349 | 506 | blkid_probe_chain_save_values(pr, chn, &vals); |
90a2086e KZ |
507 | idx = chn->idx; |
508 | } | |
509 | } | |
c81e7008 | 510 | |
0e89abac | 511 | if (rc < 0) |
af17d349 | 512 | goto done; /* error */ |
90a2086e | 513 | |
0e89abac | 514 | if (count > 1 && intol) { |
c62a6311 | 515 | DBG(LOWPROBE, ul_debug("ERROR: superblocks chain: " |
0540ea54 | 516 | "ambivalent result detected (%d filesystems)!", |
0e89abac | 517 | count)); |
2bd739c9 | 518 | rc = BLKID_PROBE_AMBIGUOUS; /* error, ambivalent result (more FS) */ |
af17d349 KZ |
519 | goto done; |
520 | } | |
521 | if (!count) { | |
522 | rc = BLKID_PROBE_NONE; | |
523 | goto done; | |
0e89abac | 524 | } |
0e89abac | 525 | |
90a2086e KZ |
526 | if (idx != -1) { |
527 | /* restore the first result */ | |
af17d349 KZ |
528 | blkid_probe_chain_reset_values(pr, chn); |
529 | blkid_probe_append_values_list(pr, &vals); | |
90a2086e KZ |
530 | chn->idx = idx; |
531 | } | |
0e89abac | 532 | |
c81e7008 KZ |
533 | /* |
534 | * The RAID device could be partitioned. The problem are RAID1 devices | |
9e930041 | 535 | * where the partition table is visible from underlying devices. We |
c81e7008 KZ |
536 | * have to ignore such partition tables. |
537 | */ | |
90a2086e | 538 | if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID) |
a9eef56c | 539 | pr->prob_flags |= BLKID_PROBE_FL_IGNORE_PT; |
c81e7008 | 540 | |
af17d349 KZ |
541 | rc = BLKID_PROBE_OK; |
542 | done: | |
543 | blkid_probe_free_values_list(&vals); | |
544 | return rc; | |
0e89abac KZ |
545 | } |
546 | ||
1c1726a7 KZ |
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", | |
47afae0c KZ |
553 | (const unsigned char *) version, |
554 | strlen(version) + 1); | |
1c1726a7 KZ |
555 | return 0; |
556 | } | |
557 | ||
fafe46bc | 558 | |
1c1726a7 KZ |
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 | ||
cd129b7d MP |
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 | ||
0e89abac KZ |
579 | static int blkid_probe_set_usage(blkid_probe pr, int usage) |
580 | { | |
861902b5 | 581 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
92385aaf | 582 | const char *u = NULL; |
0e89abac | 583 | |
861902b5 KZ |
584 | if (!(chn->flags & BLKID_SUBLKS_USAGE)) |
585 | return 0; | |
586 | ||
0e89abac KZ |
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 | ||
92385aaf KZ |
598 | return blkid_probe_set_value(pr, "USAGE", |
599 | (const unsigned char *) u, strlen(u) + 1); | |
0e89abac | 600 | } |
305ad223 | 601 | |
0567efc7 | 602 | /* size used by filesystem for data */ |
ad08ae0a AA |
603 | int blkid_probe_set_fssize(blkid_probe pr, uint64_t size) |
604 | { | |
605 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
606 | ||
c9b2297e | 607 | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) |
ad08ae0a AA |
608 | return 0; |
609 | ||
610 | return blkid_probe_sprintf_value(pr, "FSSIZE", "%" PRIu64, size); | |
611 | } | |
612 | ||
b7cb26ec AA |
613 | int blkid_probe_set_fslastblock(blkid_probe pr, uint64_t lastblock) |
614 | { | |
615 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
616 | ||
c9b2297e | 617 | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) |
b7cb26ec AA |
618 | return 0; |
619 | ||
620 | return blkid_probe_sprintf_value(pr, "FSLASTBLOCK", "%" PRIu64, | |
621 | lastblock); | |
622 | } | |
623 | ||
0f447d49 AA |
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 | ||
6575d8f4 | 635 | int blkid_probe_set_fsendianness(blkid_probe pr, enum blkid_endianness endianness) |
8ace285b TW |
636 | { |
637 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
92385aaf | 638 | const char *value; |
8ace285b TW |
639 | |
640 | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) | |
641 | return 0; | |
642 | ||
8ace285b TW |
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 | ||
92385aaf KZ |
654 | return blkid_probe_set_value(pr, "ENDIANNESS", |
655 | (const unsigned char *) value, strlen(value) + 1); | |
656 | ||
8ace285b TW |
657 | } |
658 | ||
fafe46bc | 659 | int blkid_probe_set_id_label(blkid_probe pr, const char *name, |
47afae0c | 660 | const unsigned char *data, size_t len) |
fafe46bc ZAK |
661 | { |
662 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
663 | struct blkid_prval *v; | |
6c4a7811 | 664 | int rc = 0; |
fafe46bc ZAK |
665 | |
666 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) | |
667 | return 0; | |
668 | ||
669 | v = blkid_probe_assign_value(pr, name); | |
670 | if (!v) | |
6c4a7811 | 671 | return -ENOMEM; |
fafe46bc | 672 | |
6c4a7811 OO |
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 | } | |
fafe46bc | 682 | |
af17d349 | 683 | blkid_probe_free_value(v); |
6c4a7811 | 684 | return rc; |
fafe46bc | 685 | |
fafe46bc ZAK |
686 | } |
687 | ||
1e9d4d4a | 688 | int blkid_probe_set_utf8_id_label(blkid_probe pr, const char *name, |
47afae0c | 689 | const unsigned char *data, size_t len, int enc) |
1e9d4d4a PR |
690 | { |
691 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
692 | struct blkid_prval *v; | |
6c4a7811 | 693 | int rc = 0; |
1e9d4d4a PR |
694 | |
695 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) | |
696 | return 0; | |
697 | ||
698 | v = blkid_probe_assign_value(pr, name); | |
699 | if (!v) | |
6c4a7811 | 700 | return -ENOMEM; |
1e9d4d4a | 701 | |
35c6ed61 KZ |
702 | v->len = (len * 3) + 1; |
703 | v->data = calloc(1, v->len); | |
6c4a7811 OO |
704 | if (!v->data) |
705 | rc = -ENOMEM; | |
1e9d4d4a | 706 | |
6c4a7811 | 707 | if (!rc) { |
35c6ed61 | 708 | ul_encode_to_utf8(enc, v->data, v->len, data, len); |
6c4a7811 OO |
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 | ||
af17d349 | 716 | blkid_probe_free_value(v); |
6c4a7811 | 717 | return rc; |
1e9d4d4a PR |
718 | } |
719 | ||
47afae0c | 720 | int blkid_probe_set_label(blkid_probe pr, const unsigned char *label, size_t len) |
1c1726a7 KZ |
721 | { |
722 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
723 | struct blkid_prval *v; | |
6c4a7811 | 724 | int rc = 0; |
1c1726a7 KZ |
725 | |
726 | if ((chn->flags & BLKID_SUBLKS_LABELRAW) && | |
6c4a7811 OO |
727 | (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0) |
728 | return rc; | |
729 | ||
1c1726a7 KZ |
730 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) |
731 | return 0; | |
6c4a7811 | 732 | |
1c1726a7 KZ |
733 | v = blkid_probe_assign_value(pr, "LABEL"); |
734 | if (!v) | |
6c4a7811 | 735 | return -ENOMEM; |
1c1726a7 | 736 | |
6c4a7811 OO |
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 | } | |
1c1726a7 | 743 | |
af17d349 | 744 | blkid_probe_free_value(v); |
6c4a7811 | 745 | return rc; |
1c1726a7 KZ |
746 | } |
747 | ||
47afae0c | 748 | int blkid_probe_set_utf8label(blkid_probe pr, const unsigned char *label, |
1c1726a7 KZ |
749 | size_t len, int enc) |
750 | { | |
751 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
752 | struct blkid_prval *v; | |
6c4a7811 | 753 | int rc = 0; |
1c1726a7 KZ |
754 | |
755 | if ((chn->flags & BLKID_SUBLKS_LABELRAW) && | |
6c4a7811 OO |
756 | (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0) |
757 | return rc; | |
758 | ||
1c1726a7 KZ |
759 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) |
760 | return 0; | |
6c4a7811 | 761 | |
1c1726a7 KZ |
762 | v = blkid_probe_assign_value(pr, "LABEL"); |
763 | if (!v) | |
6c4a7811 | 764 | return -ENOMEM; |
1c1726a7 | 765 | |
35c6ed61 KZ |
766 | v->len = (len * 3) + 1; |
767 | v->data = calloc(1, v->len); | |
6c4a7811 OO |
768 | if (!v->data) |
769 | rc = -ENOMEM; | |
770 | if (!rc) { | |
35c6ed61 | 771 | ul_encode_to_utf8(enc, v->data, v->len, label, len); |
6c4a7811 OO |
772 | v->len = blkid_rtrim_whitespace(v->data) + 1; |
773 | if (v->len > 1) | |
774 | return 0; | |
775 | } | |
776 | ||
af17d349 | 777 | blkid_probe_free_value(v); |
6c4a7811 | 778 | return rc; |
1c1726a7 KZ |
779 | } |
780 | ||
47afae0c | 781 | int blkid_probe_sprintf_uuid(blkid_probe pr, const unsigned char *uuid, |
1c1726a7 KZ |
782 | size_t len, const char *fmt, ...) |
783 | { | |
784 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
1c1726a7 | 785 | va_list ap; |
6c4a7811 | 786 | int rc = 0; |
1c1726a7 | 787 | |
9c06cdbf | 788 | if (blkid_uuid_is_empty(uuid, len)) |
1c1726a7 KZ |
789 | return 0; |
790 | ||
791 | if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && | |
6c4a7811 OO |
792 | (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, len)) < 0) |
793 | return rc; | |
794 | ||
1c1726a7 KZ |
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 | ||
1c1726a7 KZ |
802 | return rc; |
803 | } | |
804 | ||
9e930041 | 805 | /* function to set UUIDs that are in superblocks stored as strings */ |
47afae0c | 806 | int blkid_probe_strncpy_uuid(blkid_probe pr, const unsigned char *str, size_t len) |
1c1726a7 KZ |
807 | { |
808 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
809 | struct blkid_prval *v; | |
6c4a7811 | 810 | int rc = 0; |
1c1726a7 KZ |
811 | |
812 | if (str == NULL || *str == '\0') | |
6c4a7811 OO |
813 | return -EINVAL; |
814 | ||
1c1726a7 | 815 | if (!len) |
47afae0c | 816 | len = strlen((const char *) str); |
1c1726a7 KZ |
817 | |
818 | if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && | |
6c4a7811 OO |
819 | (rc = blkid_probe_set_value(pr, "UUID_RAW", str, len)) < 0) |
820 | return rc; | |
821 | ||
1c1726a7 KZ |
822 | if (!(chn->flags & BLKID_SUBLKS_UUID)) |
823 | return 0; | |
824 | ||
825 | v = blkid_probe_assign_value(pr, "UUID"); | |
6c4a7811 OO |
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; | |
1c1726a7 | 834 | } |
6c4a7811 | 835 | |
af17d349 | 836 | blkid_probe_free_value(v); |
6c4a7811 | 837 | return rc; |
1c1726a7 KZ |
838 | } |
839 | ||
840 | /* default _set_uuid function to set DCE UUIDs */ | |
47afae0c | 841 | int blkid_probe_set_uuid_as(blkid_probe pr, const unsigned char *uuid, const char *name) |
1c1726a7 KZ |
842 | { |
843 | struct blkid_chain *chn = blkid_probe_get_chain(pr); | |
844 | struct blkid_prval *v; | |
6c4a7811 | 845 | int rc = 0; |
1c1726a7 | 846 | |
9c06cdbf | 847 | if (blkid_uuid_is_empty(uuid, 16)) |
1c1726a7 KZ |
848 | return 0; |
849 | ||
850 | if (!name) { | |
851 | if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && | |
6c4a7811 OO |
852 | (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, 16)) < 0) |
853 | return rc; | |
854 | ||
1c1726a7 KZ |
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 | ||
6c4a7811 OO |
862 | if (!v) |
863 | return -ENOMEM; | |
864 | ||
b443c177 | 865 | v->len = UUID_STR_LEN; |
6c4a7811 OO |
866 | v->data = calloc(1, v->len); |
867 | if (!v->data) | |
868 | rc = -ENOMEM; | |
1c1726a7 | 869 | |
6c4a7811 OO |
870 | if (!rc) { |
871 | blkid_unparse_uuid(uuid, (char *) v->data, v->len); | |
872 | return 0; | |
873 | } | |
874 | ||
af17d349 | 875 | blkid_probe_free_value(v); |
6c4a7811 | 876 | return rc; |
1c1726a7 KZ |
877 | } |
878 | ||
47afae0c | 879 | int blkid_probe_set_uuid(blkid_probe pr, const unsigned char *uuid) |
1c1726a7 KZ |
880 | { |
881 | return blkid_probe_set_uuid_as(pr, uuid, NULL); | |
882 | } | |
305ad223 | 883 | |
305ad223 KZ |
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 | * | |
bd64c5a3 | 932 | * Deprecated: Use blkid_probe_filter_superblocks_type(). |
305ad223 KZ |
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 | ||
fd7c9e35 | 954 |