/* function to set UUIDs that are in suberblocks stored as strings */ int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; int rc = 0; if (str == NULL || *str == '\0') return -EINVAL; if (!len) len = strlen((char *) str); if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && (rc = blkid_probe_set_value(pr, "UUID_RAW", str, len)) < 0) return rc; if (!(chn->flags & BLKID_SUBLKS_UUID)) return 0; v = blkid_probe_assign_value(pr, "UUID"); if (!v) rc= -ENOMEM; if (!rc) rc = blkid_probe_value_set_data(v, str, len); if (!rc) { v->len = blkid_rtrim_whitespace(v->data) + 1; if (v->len > 1) return 0; } blkid_probe_free_value(v); return rc; }
int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label, size_t len, int enc) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; int rc = 0; if ((chn->flags & BLKID_SUBLKS_LABELRAW) && (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0) return rc; if (!(chn->flags & BLKID_SUBLKS_LABEL)) return 0; v = blkid_probe_assign_value(pr, "LABEL"); if (!v) return -ENOMEM; v->data = blkid_encode_alloc(len, &v->len); if (!v->data) rc = -ENOMEM; if (!rc) { blkid_encode_to_utf8(enc, v->data, v->len, label, len); v->len = blkid_rtrim_whitespace(v->data) + 1; if (v->len > 1) return 0; } blkid_probe_free_value(v); return rc; }
/* function to set UUIDs that are in suberblocks stored as strings */ int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; if (str == NULL || *str == '\0') return -1; if (!len) len = strlen((char *) str); if (len > BLKID_PROBVAL_BUFSIZ) len = BLKID_PROBVAL_BUFSIZ; if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && blkid_probe_set_value(pr, "UUID_RAW", str, len) < 0) return -1; if (!(chn->flags & BLKID_SUBLKS_UUID)) return 0; v = blkid_probe_assign_value(pr, "UUID"); if (v) { if (len == BLKID_PROBVAL_BUFSIZ) len--; /* make a space for \0 */ memcpy((char *) v->data, str, len); v->data[len] = '\0'; v->len = len + 1; return 0; } return -1; }
int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; int rc = 0; if ((chn->flags & BLKID_SUBLKS_LABELRAW) && (rc = blkid_probe_set_value(pr, "LABEL_RAW", label, len)) < 0) return rc; if (!(chn->flags & BLKID_SUBLKS_LABEL)) return 0; v = blkid_probe_assign_value(pr, "LABEL"); if (!v) return -ENOMEM; rc = blkid_probe_value_set_data(v, label, len); if (!rc) { v->len = blkid_rtrim_whitespace(v->data) + 1; if (v->len > 1) return 0; } blkid_probe_free_value(v); return rc; }
int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; if (len > BLKID_PROBVAL_BUFSIZ) len = BLKID_PROBVAL_BUFSIZ; if ((chn->flags & BLKID_SUBLKS_LABELRAW) && blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0) return -1; if (!(chn->flags & BLKID_SUBLKS_LABEL)) return 0; v = blkid_probe_assign_value(pr, "LABEL"); if (!v) return -1; if (len == BLKID_PROBVAL_BUFSIZ) len--; /* make a space for \0 */ memcpy(v->data, label, len); v->data[len] = '\0'; v->len = blkid_rtrim_whitespace(v->data) + 1; if (v->len == 1) blkid_probe_reset_last_value(pr); return 0; }
static void ext_get_info(blkid_probe pr, int ver, struct ext2_super_block *es) { struct blkid_chain *chn = blkid_probe_get_chain(pr); DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", le32_to_cpu(es->s_feature_compat), le32_to_cpu(es->s_feature_incompat), le32_to_cpu(es->s_feature_ro_compat))); if (strlen(es->s_volume_name)) blkid_probe_set_label(pr, (unsigned char *) es->s_volume_name, sizeof(es->s_volume_name)); blkid_probe_set_uuid(pr, es->s_uuid); if (le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) blkid_probe_set_uuid_as(pr, es->s_journal_uuid, "EXT_JOURNAL"); if (ver != 2 && (chn->flags & BLKID_SUBLKS_SECTYPE) && ((le32_to_cpu(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0)) blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "ext2", sizeof("ext2")); blkid_probe_sprintf_version(pr, "%u.%u", le32_to_cpu(es->s_rev_level), le16_to_cpu(es->s_minor_rev_level)); }
int blkid_probe_set_version(blkid_probe pr, const char *version) { struct blkid_chain *chn = blkid_probe_get_chain(pr); if (chn->flags & BLKID_SUBLKS_VERSION) return blkid_probe_set_value(pr, "VERSION", (unsigned char *) version, strlen(version) + 1); return 0; }
static int blkid_probe_set_usage(blkid_probe pr, int usage) { struct blkid_chain *chn = blkid_probe_get_chain(pr); char *u = NULL; if (!(chn->flags & BLKID_SUBLKS_USAGE)) return 0; if (usage & BLKID_USAGE_FILESYSTEM) u = "filesystem"; else if (usage & BLKID_USAGE_RAID) u = "raid"; else if (usage & BLKID_USAGE_CRYPTO) u = "crypto"; else if (usage & BLKID_USAGE_OTHER) u = "other"; else u = "unknown"; return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1); }
int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label, size_t len, int enc) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; if ((chn->flags & BLKID_SUBLKS_LABELRAW) && blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0) return -1; if (!(chn->flags & BLKID_SUBLKS_LABEL)) return 0; v = blkid_probe_assign_value(pr, "LABEL"); if (!v) return -1; blkid_encode_to_utf8(enc, v->data, sizeof(v->data), label, len); v->len = blkid_rtrim_whitespace(v->data) + 1; if (v->len == 1) blkid_probe_reset_last_value(pr); return 0; }
int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid, size_t len, const char *fmt, ...) { struct blkid_chain *chn = blkid_probe_get_chain(pr); va_list ap; int rc = 0; if (blkid_uuid_is_empty(uuid, len)) return 0; if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, len)) < 0) return rc; if (!(chn->flags & BLKID_SUBLKS_UUID)) return 0; va_start(ap, fmt); rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap); va_end(ap); return rc; }
/* default _set_uuid function to set DCE UUIDs */ int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; int rc = 0; if (blkid_uuid_is_empty(uuid, 16)) return 0; if (!name) { if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && (rc = blkid_probe_set_value(pr, "UUID_RAW", uuid, 16)) < 0) return rc; if (!(chn->flags & BLKID_SUBLKS_UUID)) return 0; v = blkid_probe_assign_value(pr, "UUID"); } else v = blkid_probe_assign_value(pr, name); if (!v) return -ENOMEM; v->len = 37; v->data = calloc(1, v->len); if (!v->data) rc = -ENOMEM; if (!rc) { blkid_unparse_uuid(uuid, (char *) v->data, v->len); return 0; } blkid_probe_free_value(v); return rc; }
/* default _set_uuid function to set DCE UUIDs */ int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name) { struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; if (blkid_uuid_is_empty(uuid, 16)) return 0; if (!name) { if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && blkid_probe_set_value(pr, "UUID_RAW", uuid, 16) < 0) return -1; if (!(chn->flags & BLKID_SUBLKS_UUID)) return 0; v = blkid_probe_assign_value(pr, "UUID"); } else v = blkid_probe_assign_value(pr, name); blkid_unparse_uuid(uuid, (char *) v->data, sizeof(v->data)); v->len = 37; return 0; }
int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid, size_t len, const char *fmt, ...) { struct blkid_chain *chn = blkid_probe_get_chain(pr); int rc = -1; va_list ap; if (len > BLKID_PROBVAL_BUFSIZ) len = BLKID_PROBVAL_BUFSIZ; if (blkid_uuid_is_empty(uuid, len)) return 0; if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && blkid_probe_set_value(pr, "UUID_RAW", uuid, len) < 0) return -1; if (!(chn->flags & BLKID_SUBLKS_UUID)) return 0; va_start(ap, fmt); rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap); va_end(ap); /* convert to lower case (..be paranoid) */ if (!rc) { size_t i; struct blkid_prval *v = __blkid_probe_get_value(pr, blkid_probe_numof_values(pr)); if (v) { for (i = 0; i < v->len; i++) if (v->data[i] >= 'A' && v->data[i] <= 'F') v->data[i] = (v->data[i] - 'A') + 'a'; } } return rc; }
/* * The blkid_do_probe() backend. */ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) { size_t i; int rc = BLKID_PROBE_NONE; if (!pr || chn->idx < -1) return -EINVAL; blkid_probe_chain_reset_values(pr, chn); if (pr->flags & BLKID_FL_NOSCAN_DEV) return BLKID_PROBE_NONE; if (pr->size <= 0 || (pr->size <= 1024 && !S_ISCHR(pr->mode))) /* Ignore very very small block devices or regular files (e.g. * extended partitions). Note that size of the UBI char devices * is 1 byte */ return BLKID_PROBE_NONE; DBG(LOWPROBE, ul_debug("--> starting probing loop [SUBLKS idx=%d]", chn->idx)); i = chn->idx < 0 ? 0 : chn->idx + 1U; for ( ; i < ARRAY_SIZE(idinfos); i++) { const struct blkid_idinfo *id; const struct blkid_idmag *mag = NULL; uint64_t off = 0; chn->idx = i; id = idinfos[i]; if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) { DBG(LOWPROBE, ul_debug("filter out: %s", id->name)); rc = BLKID_PROBE_NONE; continue; } if (id->minsz && id->minsz > pr->size) { rc = BLKID_PROBE_NONE; continue; /* the device is too small */ } /* don't probe for RAIDs, swap or journal on CD/DVDs */ if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) && blkid_probe_is_cdrom(pr)) { rc = BLKID_PROBE_NONE; continue; } /* don't probe for RAIDs on floppies */ if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) { rc = BLKID_PROBE_NONE; continue; } DBG(LOWPROBE, ul_debug("[%zd] %s:", i, id->name)); rc = blkid_probe_get_idmag(pr, id, &off, &mag); if (rc < 0) break; if (rc != BLKID_PROBE_OK) continue; /* final check by probing function */ if (id->probefunc) { DBG(LOWPROBE, ul_debug("\tcall probefunc()")); rc = id->probefunc(pr, mag); if (rc != BLKID_PROBE_OK) { blkid_probe_chain_reset_values(pr, chn); if (rc < 0) break; continue; } } /* all cheks passed */ if (chn->flags & BLKID_SUBLKS_TYPE) rc = blkid_probe_set_value(pr, "TYPE", (unsigned char *) id->name, strlen(id->name) + 1); if (!rc) rc = blkid_probe_set_usage(pr, id->usage); if (!rc && mag) rc = blkid_probe_set_magic(pr, off, mag->len, (unsigned char *) mag->magic); if (rc) { blkid_probe_chain_reset_values(pr, chn); DBG(LOWPROBE, ul_debug("failed to set result -- ignore")); continue; } DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]", id->name, chn->idx)); return BLKID_PROBE_OK; } DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]", rc, chn->idx)); return rc; }
/* FAT label extraction from the root directory taken from Kay * Sievers's volume_id library */ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag) { struct vfat_super_block *vs; struct msdos_super_block *ms; const unsigned char *vol_label = 0; unsigned char *vol_serno = NULL, vol_label_buf[11]; uint16_t sector_size = 0, reserved; uint32_t cluster_count, fat_size; const char *version = NULL; ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block); if (!ms) return errno ? -errno : 1; vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block); if (!vs) return errno ? -errno : 1; if (!fat_valid_superblock(pr, mag, ms, vs, &cluster_count, &fat_size)) return 1; sector_size = unaligned_le16(&ms->ms_sector_size); reserved = le16_to_cpu(ms->ms_reserved); if (ms->ms_fat_length) { /* the label may be an attribute in the root directory */ uint32_t root_start = (reserved + fat_size) * sector_size; uint32_t root_dir_entries = unaligned_le16(&vs->vs_dir_entries); vol_label = search_fat_label(pr, root_start, root_dir_entries); if (vol_label) { memcpy(vol_label_buf, vol_label, 11); vol_label = vol_label_buf; } if (!vol_label || !memcmp(vol_label, no_name, 11)) vol_label = ms->ms_label; vol_serno = ms->ms_serno; blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos", sizeof("msdos")); if (cluster_count < FAT12_MAX) version = "FAT12"; else if (cluster_count < FAT16_MAX) version = "FAT16"; } else if (vs->vs_fat32_length) { unsigned char *buf; uint16_t fsinfo_sect; int maxloop = 100; /* Search the FAT32 root dir for the label attribute */ uint32_t buf_size = vs->vs_cluster_size * sector_size; uint32_t start_data_sect = reserved + fat_size; uint32_t entries = le32_to_cpu(vs->vs_fat32_length) * sector_size / sizeof(uint32_t); uint32_t next = le32_to_cpu(vs->vs_root_cluster); while (next && next < entries && --maxloop) { uint32_t next_sect_off; uint64_t next_off, fat_entry_off; int count; next_sect_off = (next - 2) * vs->vs_cluster_size; next_off = (uint64_t)(start_data_sect + next_sect_off) * sector_size; count = buf_size / sizeof(struct vfat_dir_entry); vol_label = search_fat_label(pr, next_off, count); if (vol_label) { memcpy(vol_label_buf, vol_label, 11); vol_label = vol_label_buf; break; } /* get FAT entry */ fat_entry_off = ((uint64_t) reserved * sector_size) + (next * sizeof(uint32_t)); buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size); if (buf == NULL) break; /* set next cluster */ next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff; } version = "FAT32"; if (!vol_label || !memcmp(vol_label, no_name, 11)) vol_label = vs->vs_label; vol_serno = vs->vs_serno; /* * FAT32 should have a valid signature in the fsinfo block, * but also allow all bytes set to '\0', because some volumes * do not set the signature at all. */ fsinfo_sect = le16_to_cpu(vs->vs_fsinfo_sector); if (fsinfo_sect) { struct fat32_fsinfo *fsinfo; buf = blkid_probe_get_buffer(pr, (blkid_loff_t) fsinfo_sect * sector_size, sizeof(struct fat32_fsinfo)); if (buf == NULL) return errno ? -errno : 1; fsinfo = (struct fat32_fsinfo *) buf; if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 && memcmp(fsinfo->signature1, "\x52\x52\x64\x41", 4) != 0 && memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0) return 1; if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 && memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0) return 1; } } if (vol_label && memcmp(vol_label, no_name, 11)) blkid_probe_set_label(pr, (unsigned char *) vol_label, 11); /* We can't just print them as %04X, because they are unaligned */ if (vol_serno) blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]); if (version) blkid_probe_set_version(pr, version); return 0; }