/src/util-linux/libblkid/src/superblocks/superblocks.c
Line | Count | Source |
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: pool member UUID or device item UUID, etc. (e.g., zfs, 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 | 5.27k | { |
213 | 5.27k | pr->chains[BLKID_CHAIN_SUBLKS].enabled = enable; |
214 | 5.27k | return 0; |
215 | 5.27k | } |
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 | 5.27k | { |
229 | 5.27k | pr->chains[BLKID_CHAIN_SUBLKS].flags = flags; |
230 | 5.27k | return 0; |
231 | 5.27k | } |
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 | 0 | { |
243 | 0 | return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS); |
244 | 0 | } |
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 | 0 | { |
256 | 0 | return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS); |
257 | 0 | } |
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 | 5.27k | { |
273 | 5.27k | return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names); |
274 | 5.27k | } |
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 | 0 | { |
290 | 0 | unsigned long *fltr; |
291 | 0 | struct blkid_chain *chn; |
292 | 0 | size_t i; |
293 | |
|
294 | 0 | fltr = blkid_probe_get_filter(pr, BLKID_CHAIN_SUBLKS, TRUE); |
295 | 0 | if (!fltr) |
296 | 0 | return -1; |
297 | | |
298 | 0 | chn = &pr->chains[BLKID_CHAIN_SUBLKS]; |
299 | |
|
300 | 0 | for (i = 0; i < chn->driver->nidinfos; i++) { |
301 | 0 | const struct blkid_idinfo *id = chn->driver->idinfos[i]; |
302 | |
|
303 | 0 | if (id->usage & usage) { |
304 | 0 | if (flag & BLKID_FLTR_NOTIN) |
305 | 0 | blkid_bmp_set_item(chn->fltr, i); |
306 | 0 | } else if (flag & BLKID_FLTR_ONLYIN) |
307 | 0 | blkid_bmp_set_item(chn->fltr, i); |
308 | 0 | } |
309 | 0 | DBG(LOWPROBE, ul_debug("a new probing usage-filter initialized")); |
310 | 0 | return 0; |
311 | 0 | } |
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 | 0 | { |
321 | 0 | size_t i; |
322 | |
|
323 | 0 | for (i = 0; i < ARRAY_SIZE(idinfos); i++) { |
324 | 0 | const struct blkid_idinfo *id = idinfos[i]; |
325 | 0 | if (strcmp(id->name, fstype) == 0) |
326 | 0 | return 1; |
327 | 0 | } |
328 | 0 | return 0; |
329 | 0 | } |
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 | 0 | { |
341 | 0 | if (idx < ARRAY_SIZE(idinfos)) { |
342 | 0 | if (name) |
343 | 0 | *name = idinfos[idx]->name; |
344 | 0 | if (usage) |
345 | 0 | *usage = idinfos[idx]->usage; |
346 | 0 | return 0; |
347 | 0 | } |
348 | 0 | return -1; |
349 | 0 | } |
350 | | |
351 | | /* |
352 | | * The blkid_do_probe() backend. |
353 | | */ |
354 | | static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) |
355 | 7.48k | { |
356 | 7.48k | size_t i; |
357 | 7.48k | int rc = BLKID_PROBE_NONE; |
358 | | |
359 | 7.48k | if (chn->idx < -1) |
360 | 0 | return -EINVAL; |
361 | | |
362 | 7.48k | blkid_probe_chain_reset_values(pr, chn); |
363 | | |
364 | 7.48k | if (pr->flags & BLKID_FL_NOSCAN_DEV) { |
365 | 0 | DBG(LOWPROBE, ul_debug("*** ignore (noscan flag)")); |
366 | 0 | return BLKID_PROBE_NONE; |
367 | 0 | } |
368 | | |
369 | 7.48k | 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 | 0 | DBG(LOWPROBE, ul_debug("*** ignore (size <= 1024)")); |
374 | 0 | return BLKID_PROBE_NONE; |
375 | 0 | } |
376 | | |
377 | 7.48k | DBG(LOWPROBE, ul_debug("--> starting probing loop [SUBLKS idx=%d]", |
378 | 7.48k | chn->idx)); |
379 | | |
380 | 7.48k | i = chn->idx < 0 ? 0 : chn->idx + 1U; |
381 | | |
382 | 433k | for ( ; i < ARRAY_SIZE(idinfos); i++) { |
383 | 428k | const struct blkid_idinfo *id; |
384 | 428k | const struct blkid_idmag *mag = NULL; |
385 | 428k | uint64_t off = 0; |
386 | | |
387 | 428k | chn->idx = i; |
388 | 428k | id = idinfos[i]; |
389 | | |
390 | 428k | if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) { |
391 | 10.5k | DBG(LOWPROBE, ul_debug("filter out: %s", id->name)); |
392 | 10.5k | rc = BLKID_PROBE_NONE; |
393 | 10.5k | continue; |
394 | 10.5k | } |
395 | | |
396 | 418k | if (id->minsz && (unsigned)id->minsz > pr->size) { |
397 | 15.6k | rc = BLKID_PROBE_NONE; |
398 | 15.6k | continue; /* the device is too small */ |
399 | 15.6k | } |
400 | | |
401 | | /* don't probe for RAIDs, swap or journal on CD/DVDs */ |
402 | 402k | if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) && |
403 | 141k | blkid_probe_is_cdrom(pr)) { |
404 | 0 | rc = BLKID_PROBE_NONE; |
405 | 0 | continue; |
406 | 0 | } |
407 | | |
408 | | /* don't probe for RAIDs on floppies */ |
409 | 402k | if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) { |
410 | 0 | rc = BLKID_PROBE_NONE; |
411 | 0 | continue; |
412 | 0 | } |
413 | | |
414 | 402k | DBG(LOWPROBE, ul_debug("[%zd] %s:", i, id->name)); |
415 | | |
416 | 402k | rc = blkid_probe_get_idmag(pr, id, &off, &mag); |
417 | 402k | if (rc < 0) |
418 | 0 | break; |
419 | 402k | if (rc != BLKID_PROBE_OK) |
420 | 305k | continue; |
421 | | |
422 | | /* final check by probing function */ |
423 | 96.8k | if (id->probefunc) { |
424 | 96.8k | DBG(LOWPROBE, ul_debug("\tcall probefunc()")); |
425 | 96.8k | errno = 0; |
426 | 96.8k | rc = id->probefunc(pr, mag); |
427 | 96.8k | blkid_probe_prune_buffers(pr); |
428 | 96.8k | if (rc != BLKID_PROBE_OK) { |
429 | 94.5k | blkid_probe_chain_reset_values(pr, chn); |
430 | 94.5k | if (rc < 0) |
431 | 34 | break; |
432 | 94.5k | continue; |
433 | 94.5k | } |
434 | 96.8k | } |
435 | | |
436 | | /* all checks passed */ |
437 | 2.23k | if (chn->flags & BLKID_SUBLKS_TYPE) |
438 | 2.23k | rc = blkid_probe_set_value(pr, "TYPE", |
439 | 2.23k | (const unsigned char *) id->name, |
440 | 2.23k | strlen(id->name) + 1); |
441 | | |
442 | 2.23k | if (!rc) |
443 | 2.23k | rc = blkid_probe_set_usage(pr, id->usage); |
444 | | |
445 | 2.23k | if (!rc && mag) |
446 | 2.01k | rc = blkid_probe_set_magic(pr, off, mag->len, |
447 | 2.01k | (const unsigned char *) mag->magic); |
448 | 2.23k | if (rc) { |
449 | 0 | blkid_probe_chain_reset_values(pr, chn); |
450 | 0 | DBG(LOWPROBE, ul_debug("failed to set result -- ignore")); |
451 | 0 | continue; |
452 | 0 | } |
453 | | |
454 | 2.23k | DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]", |
455 | 2.23k | id->name, chn->idx)); |
456 | 2.23k | return BLKID_PROBE_OK; |
457 | 2.23k | } |
458 | | |
459 | 5.24k | DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]", |
460 | 5.24k | rc, chn->idx)); |
461 | 5.24k | return rc; |
462 | 7.48k | } |
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 | 5.27k | { |
478 | 5.27k | struct list_head vals; |
479 | 5.27k | int idx = -1; |
480 | 5.27k | int count = 0; |
481 | 5.27k | int intol = 0; |
482 | 5.27k | int rc; |
483 | | |
484 | 5.27k | INIT_LIST_HEAD(&vals); |
485 | | |
486 | 5.27k | if (pr->flags & BLKID_FL_NOSCAN_DEV) |
487 | 0 | return BLKID_PROBE_NONE; |
488 | | |
489 | 7.48k | while ((rc = superblocks_probe(pr, chn)) == 0) { |
490 | | |
491 | 2.23k | if (blkid_probe_is_tiny(pr) && !count) |
492 | 0 | return BLKID_PROBE_OK; /* floppy or so -- returns the first result. */ |
493 | | |
494 | 2.23k | count++; |
495 | | |
496 | 2.23k | if (chn->idx >= 0 && |
497 | 2.23k | idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO)) |
498 | 29 | break; |
499 | | |
500 | 2.21k | if (chn->idx >= 0 && |
501 | 2.21k | !(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT)) |
502 | 1.95k | intol++; |
503 | | |
504 | 2.21k | if (count == 1) { |
505 | | /* save the first result */ |
506 | 1.40k | blkid_probe_chain_save_values(pr, chn, &vals); |
507 | 1.40k | idx = chn->idx; |
508 | 1.40k | } |
509 | 2.21k | } |
510 | | |
511 | 5.27k | if (rc < 0) |
512 | 34 | goto done; /* error */ |
513 | | |
514 | 5.23k | if (count > 1 && intol) { |
515 | 406 | DBG(LOWPROBE, ul_debug("ERROR: superblocks chain: " |
516 | 406 | "ambivalent result detected (%d filesystems)!", |
517 | 406 | count)); |
518 | 406 | rc = BLKID_PROBE_AMBIGUOUS; /* error, ambivalent result (more FS) */ |
519 | 406 | goto done; |
520 | 406 | } |
521 | 4.83k | if (!count) { |
522 | 3.81k | rc = BLKID_PROBE_NONE; |
523 | 3.81k | goto done; |
524 | 3.81k | } |
525 | | |
526 | 1.01k | if (idx != -1) { |
527 | | /* restore the first result */ |
528 | 989 | blkid_probe_chain_reset_values(pr, chn); |
529 | 989 | blkid_probe_append_values_list(pr, &vals); |
530 | 989 | chn->idx = idx; |
531 | 989 | } |
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 | 1.01k | if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID) |
539 | 11 | pr->prob_flags |= BLKID_PROBE_FL_IGNORE_PT; |
540 | | |
541 | 1.01k | rc = BLKID_PROBE_OK; |
542 | 5.27k | done: |
543 | 5.27k | blkid_probe_free_values_list(&vals); |
544 | 5.27k | return rc; |
545 | 1.01k | } |
546 | | |
547 | | int blkid_probe_set_version(blkid_probe pr, const char *version) |
548 | 789 | { |
549 | 789 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
550 | | |
551 | 789 | if (chn->flags & BLKID_SUBLKS_VERSION) |
552 | 0 | return blkid_probe_set_value(pr, "VERSION", |
553 | 0 | (const unsigned char *) version, |
554 | 0 | strlen(version) + 1); |
555 | 789 | return 0; |
556 | 789 | } |
557 | | |
558 | | |
559 | | int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...) |
560 | 890 | { |
561 | 890 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
562 | 890 | int rc = 0; |
563 | | |
564 | 890 | if (chn->flags & BLKID_SUBLKS_VERSION) { |
565 | 0 | va_list ap; |
566 | |
|
567 | 0 | va_start(ap, fmt); |
568 | 0 | rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap); |
569 | 0 | va_end(ap); |
570 | 0 | } |
571 | 890 | return rc; |
572 | 890 | } |
573 | | |
574 | | int blkid_probe_set_block_size(blkid_probe pr, unsigned block_size) |
575 | 1.16k | { |
576 | 1.16k | return blkid_probe_sprintf_value(pr, "BLOCK_SIZE", "%u", block_size); |
577 | 1.16k | } |
578 | | |
579 | | static int blkid_probe_set_usage(blkid_probe pr, int usage) |
580 | 2.23k | { |
581 | 2.23k | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
582 | 2.23k | const char *u = NULL; |
583 | | |
584 | 2.23k | if (!(chn->flags & BLKID_SUBLKS_USAGE)) |
585 | 2.23k | return 0; |
586 | | |
587 | 0 | if (usage & BLKID_USAGE_FILESYSTEM) |
588 | 0 | u = "filesystem"; |
589 | 0 | else if (usage & BLKID_USAGE_RAID) |
590 | 0 | u = "raid"; |
591 | 0 | else if (usage & BLKID_USAGE_CRYPTO) |
592 | 0 | u = "crypto"; |
593 | 0 | else if (usage & BLKID_USAGE_OTHER) |
594 | 0 | u = "other"; |
595 | 0 | else |
596 | 0 | u = "unknown"; |
597 | |
|
598 | 0 | return blkid_probe_set_value(pr, "USAGE", |
599 | 0 | (const unsigned char *) u, strlen(u) + 1); |
600 | 2.23k | } |
601 | | |
602 | | /* size used by filesystem for data */ |
603 | | int blkid_probe_set_fssize(blkid_probe pr, uint64_t size) |
604 | 589 | { |
605 | 589 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
606 | | |
607 | 589 | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) |
608 | 589 | return 0; |
609 | | |
610 | 0 | return blkid_probe_sprintf_value(pr, "FSSIZE", "%" PRIu64, size); |
611 | 589 | } |
612 | | |
613 | | int blkid_probe_set_fslastblock(blkid_probe pr, uint64_t lastblock) |
614 | 100 | { |
615 | 100 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
616 | | |
617 | 100 | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) |
618 | 100 | return 0; |
619 | | |
620 | 0 | return blkid_probe_sprintf_value(pr, "FSLASTBLOCK", "%" PRIu64, |
621 | 0 | lastblock); |
622 | 100 | } |
623 | | |
624 | | int blkid_probe_set_fsblocksize(blkid_probe pr, uint32_t block_size) |
625 | 1.18k | { |
626 | 1.18k | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
627 | | |
628 | 1.18k | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) |
629 | 1.18k | return 0; |
630 | | |
631 | 0 | return blkid_probe_sprintf_value(pr, "FSBLOCKSIZE", "%" PRIu32, |
632 | 0 | block_size); |
633 | 1.18k | } |
634 | | |
635 | | int blkid_probe_set_fsendianness(blkid_probe pr, enum blkid_endianness endianness) |
636 | 410 | { |
637 | 410 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
638 | 410 | const char *value; |
639 | | |
640 | 410 | if (!(chn->flags & BLKID_SUBLKS_FSINFO)) |
641 | 410 | return 0; |
642 | | |
643 | 0 | switch (endianness) { |
644 | 0 | case BLKID_ENDIANNESS_LITTLE: |
645 | 0 | value = "LITTLE"; |
646 | 0 | break; |
647 | 0 | case BLKID_ENDIANNESS_BIG: |
648 | 0 | value = "BIG"; |
649 | 0 | break; |
650 | 0 | default: |
651 | 0 | return -EINVAL; |
652 | 0 | } |
653 | | |
654 | 0 | return blkid_probe_set_value(pr, "ENDIANNESS", |
655 | 0 | (const unsigned char *) value, strlen(value) + 1); |
656 | |
|
657 | 0 | } |
658 | | |
659 | | int blkid_probe_set_id_label(blkid_probe pr, const char *name, |
660 | | const unsigned char *data, size_t len) |
661 | 915 | { |
662 | 915 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
663 | 915 | struct blkid_prval *v; |
664 | 915 | int rc = 0; |
665 | | |
666 | 915 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) |
667 | 915 | return 0; |
668 | | |
669 | 0 | v = blkid_probe_assign_value(pr, name); |
670 | 0 | if (!v) |
671 | 0 | return -ENOMEM; |
672 | | |
673 | 0 | rc = blkid_probe_value_set_data(v, data, len); |
674 | 0 | if (!rc) { |
675 | | /* remove white spaces */ |
676 | 0 | v->len = blkid_rtrim_whitespace(v->data) + 1; |
677 | 0 | if (v->len > 1) |
678 | 0 | v->len = blkid_ltrim_whitespace(v->data) + 1; |
679 | 0 | if (v->len > 1) |
680 | 0 | return 0; |
681 | 0 | } |
682 | | |
683 | 0 | blkid_probe_free_value(v); |
684 | 0 | return rc; |
685 | |
|
686 | 0 | } |
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 | 370 | { |
691 | 370 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
692 | 370 | struct blkid_prval *v; |
693 | 370 | int rc = 0; |
694 | | |
695 | 370 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) |
696 | 370 | return 0; |
697 | | |
698 | 0 | v = blkid_probe_assign_value(pr, name); |
699 | 0 | if (!v) |
700 | 0 | return -ENOMEM; |
701 | | |
702 | 0 | v->len = (len * 3) + 1; |
703 | 0 | v->data = calloc(1, v->len); |
704 | 0 | if (!v->data) |
705 | 0 | rc = -ENOMEM; |
706 | |
|
707 | 0 | if (!rc) { |
708 | 0 | ul_encode_to_utf8(enc, v->data, v->len, data, len); |
709 | 0 | v->len = blkid_rtrim_whitespace(v->data) + 1; |
710 | 0 | if (v->len > 1) |
711 | 0 | v->len = blkid_ltrim_whitespace(v->data) + 1; |
712 | 0 | if (v->len > 1) |
713 | 0 | return 0; |
714 | 0 | } |
715 | | |
716 | 0 | blkid_probe_free_value(v); |
717 | 0 | return rc; |
718 | 0 | } |
719 | | |
720 | | int blkid_probe_set_label(blkid_probe pr, const unsigned char *label, size_t len) |
721 | 887 | { |
722 | 887 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
723 | 887 | struct blkid_prval *v; |
724 | 887 | int rc = 0; |
725 | | |
726 | 887 | if ((chn->flags & BLKID_SUBLKS_LABELRAW) && |
727 | 0 | (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0) |
728 | 0 | return rc; |
729 | | |
730 | 887 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) |
731 | 887 | return 0; |
732 | | |
733 | 0 | v = blkid_probe_assign_value(pr, "LABEL"); |
734 | 0 | if (!v) |
735 | 0 | return -ENOMEM; |
736 | | |
737 | 0 | rc = blkid_probe_value_set_data(v, label, len); |
738 | 0 | if (!rc) { |
739 | 0 | v->len = blkid_rtrim_whitespace(v->data) + 1; |
740 | 0 | if (v->len > 1) |
741 | 0 | return 0; |
742 | 0 | } |
743 | | |
744 | 0 | blkid_probe_free_value(v); |
745 | 0 | return rc; |
746 | 0 | } |
747 | | |
748 | | int blkid_probe_set_utf8label(blkid_probe pr, const unsigned char *label, |
749 | | size_t len, int enc) |
750 | 151 | { |
751 | 151 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
752 | 151 | struct blkid_prval *v; |
753 | 151 | int rc = 0; |
754 | | |
755 | 151 | if ((chn->flags & BLKID_SUBLKS_LABELRAW) && |
756 | 0 | (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0) |
757 | 0 | return rc; |
758 | | |
759 | 151 | if (!(chn->flags & BLKID_SUBLKS_LABEL)) |
760 | 151 | return 0; |
761 | | |
762 | 0 | v = blkid_probe_assign_value(pr, "LABEL"); |
763 | 0 | if (!v) |
764 | 0 | return -ENOMEM; |
765 | | |
766 | 0 | v->len = (len * 3) + 1; |
767 | 0 | v->data = calloc(1, v->len); |
768 | 0 | if (!v->data) |
769 | 0 | rc = -ENOMEM; |
770 | 0 | if (!rc) { |
771 | 0 | ul_encode_to_utf8(enc, v->data, v->len, label, len); |
772 | 0 | v->len = blkid_rtrim_whitespace(v->data) + 1; |
773 | 0 | if (v->len > 1) |
774 | 0 | return 0; |
775 | 0 | } |
776 | | |
777 | 0 | blkid_probe_free_value(v); |
778 | 0 | return rc; |
779 | 0 | } |
780 | | |
781 | | int blkid_probe_sprintf_uuid(blkid_probe pr, const unsigned char *uuid, |
782 | | size_t len, const char *fmt, ...) |
783 | 525 | { |
784 | 525 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
785 | 525 | va_list ap; |
786 | 525 | int rc = 0; |
787 | | |
788 | 525 | if (blkid_uuid_is_empty(uuid, len)) |
789 | 38 | return 0; |
790 | | |
791 | 487 | if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && |
792 | 0 | (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, len)) < 0) |
793 | 0 | return rc; |
794 | | |
795 | 487 | if (!(chn->flags & BLKID_SUBLKS_UUID)) |
796 | 487 | return 0; |
797 | | |
798 | 487 | va_start(ap, fmt); |
799 | 0 | rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap); |
800 | 0 | va_end(ap); |
801 | |
|
802 | 0 | return rc; |
803 | 487 | } |
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 | 2 | { |
808 | 2 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
809 | 2 | struct blkid_prval *v; |
810 | 2 | int rc = 0; |
811 | | |
812 | 2 | if (str == NULL || *str == '\0') |
813 | 0 | return -EINVAL; |
814 | | |
815 | 2 | if (!len) |
816 | 0 | len = strlen((const char *) str); |
817 | | |
818 | 2 | if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && |
819 | 0 | (rc = blkid_probe_set_value(pr, "UUID_RAW", str, len)) < 0) |
820 | 0 | return rc; |
821 | | |
822 | 2 | if (!(chn->flags & BLKID_SUBLKS_UUID)) |
823 | 2 | return 0; |
824 | | |
825 | 0 | v = blkid_probe_assign_value(pr, "UUID"); |
826 | 0 | if (!v) |
827 | 0 | rc= -ENOMEM; |
828 | 0 | if (!rc) |
829 | 0 | rc = blkid_probe_value_set_data(v, str, len); |
830 | 0 | if (!rc) { |
831 | 0 | v->len = blkid_rtrim_whitespace(v->data) + 1; |
832 | 0 | if (v->len > 1) |
833 | 0 | return 0; |
834 | 0 | } |
835 | | |
836 | 0 | blkid_probe_free_value(v); |
837 | 0 | return rc; |
838 | 0 | } |
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 | 851 | { |
843 | 851 | struct blkid_chain *chn = blkid_probe_get_chain(pr); |
844 | 851 | struct blkid_prval *v; |
845 | 851 | int rc = 0; |
846 | | |
847 | 851 | if (blkid_uuid_is_empty(uuid, 16)) |
848 | 96 | return 0; |
849 | | |
850 | 755 | if (!name) { |
851 | 723 | if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && |
852 | 0 | (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, 16)) < 0) |
853 | 0 | return rc; |
854 | | |
855 | 723 | if (!(chn->flags & BLKID_SUBLKS_UUID)) |
856 | 723 | return 0; |
857 | | |
858 | 0 | v = blkid_probe_assign_value(pr, "UUID"); |
859 | 0 | } else |
860 | 32 | v = blkid_probe_assign_value(pr, name); |
861 | | |
862 | 32 | if (!v) |
863 | 0 | return -ENOMEM; |
864 | | |
865 | 32 | v->len = UUID_STR_LEN; |
866 | 32 | v->data = calloc(1, v->len); |
867 | 32 | if (!v->data) |
868 | 0 | rc = -ENOMEM; |
869 | | |
870 | 32 | if (!rc) { |
871 | 32 | blkid_unparse_uuid(uuid, (char *) v->data, v->len); |
872 | 32 | return 0; |
873 | 32 | } |
874 | | |
875 | 0 | blkid_probe_free_value(v); |
876 | 0 | return rc; |
877 | 32 | } |
878 | | |
879 | | int blkid_probe_set_uuid(blkid_probe pr, const unsigned char *uuid) |
880 | 804 | { |
881 | 804 | return blkid_probe_set_uuid_as(pr, uuid, NULL); |
882 | 804 | } |
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 | 0 | { |
895 | 0 | return blkid_probe_set_superblocks_flags(pr, flags); |
896 | 0 | } |
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 | 0 | { |
908 | 0 | return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS); |
909 | 0 | } |
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 | 0 | { |
921 | 0 | return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS); |
922 | 0 | } |
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 | 0 | { |
936 | 0 | return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names); |
937 | 0 | } |
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 | 0 | { |
951 | 0 | return blkid_probe_filter_superblocks_usage(pr, flag, usage); |
952 | 0 | } |
953 | | |
954 | | |