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