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)); }
static int swap_set_info(blkid_probe pr, const char *version) { struct swap_header_v1_2 *hdr; /* Swap header always located at offset of 1024 bytes */ hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024, sizeof(struct swap_header_v1_2)); if (!hdr) return -1; /* SWAPSPACE2 - check for wrong version or zeroed pagecount */ if (strcmp(version, "2") == 0 && (hdr->version != 1 || hdr->lastpage == 0)) return -1; /* arbitrary sanity check.. is there any garbage down there? */ if (hdr->padding[32] == 0 && hdr->padding[33] == 0) { if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume, sizeof(hdr->volume)) < 0) return -1; if (hdr->uuid[0] && blkid_probe_set_uuid(pr, hdr->uuid) < 0) return -1; } blkid_probe_set_version(pr, version); return 0; }
/* iso9660 [+ Microsoft Joliet Extension] */ static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag) { struct iso_volume_descriptor *iso; unsigned char label[32]; int i; int off; if (strcmp(mag->magic, "CDROM") == 0) return probe_iso9660_hsfs(pr, mag); iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor); if (!iso) return -1; memcpy(label, iso->volume_id, sizeof(label)); /* Joliet Extension */ off = ISO_VD_OFFSET; for (i = 0; i < ISO_VD_MAX; i++) { iso = (struct iso_volume_descriptor *) blkid_probe_get_buffer(pr, off, sizeof(struct iso_volume_descriptor)); if (iso == NULL || iso->vd_type == ISO_VD_END) break; if (iso->vd_type != ISO_VD_SUPPLEMENTARY) continue; if (memcmp(iso->escape_sequences, "%/@", 3) == 0 || memcmp(iso->escape_sequences, "%/C", 3) == 0 || memcmp(iso->escape_sequences, "%/E", 3) == 0) { blkid_probe_set_version(pr, "Joliet Extension"); /* Is the Joliet (UTF16BE) label equal to the label in * the PVD? If yes, use PVD label. The Jolied version * of the label could be trimed (because UTF16..). */ if (ascii_eq_utf16be(label, iso->volume_id, 32)) break; blkid_probe_set_utf8label(pr, iso->volume_id, sizeof(iso->volume_id), BLKID_ENC_UTF16BE); goto has_label; } off += ISO_SECTOR_SIZE; } /* Joliet not found, let use standard iso label */ blkid_probe_set_label(pr, label, sizeof(label)); has_label: return 0; }
/* old High Sierra format */ static int probe_iso9660_hsfs(blkid_probe pr, const struct blkid_idmag *mag) { struct high_sierra_volume_descriptor *iso; iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor); if (!iso) return -1; blkid_probe_set_version(pr, "High Sierra"); blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id)); return 0; }
static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag) { struct hfs_mdb *hfs; hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb); if (!hfs) return -1; if ((memcmp(hfs->embed_sig, "H+", 2) == 0) || (memcmp(hfs->embed_sig, "HX", 2) == 0)) return 1; /* Not hfs, but an embedded HFS+ */ hfs_set_uuid(pr, hfs->finder_info.id, sizeof(hfs->finder_info.id)); blkid_probe_set_label(pr, hfs->label, hfs->label_len); return 0; }
static void zfs_extract_guid_name(blkid_probe pr, loff_t offset) { struct nvlist *nvl; struct nvpair *nvp; size_t left = 4096; int found = 0; offset = (offset & ~(VDEV_LABEL_SIZE - 1)) + VDEV_LABEL_NVPAIR; /* Note that we currently assume that the desired fields are within * the first 4k (left) of the nvlist. This is true for all pools * I've seen, and simplifies this code somewhat, because we don't * have to handle an nvpair crossing a buffer boundary. */ nvl = (struct nvlist *)blkid_probe_get_buffer(pr, offset, left); if (nvl == NULL) return; nvdebug("zfs_extract: nvlist offset %llu\n", offset); nvp = &nvl->nvl_nvpair; while (left > sizeof(*nvp) && nvp->nvp_size != 0 && found < 3) { int avail; /* tracks that name/value data fits in nvp_size */ int namesize; nvp->nvp_size = be32_to_cpu(nvp->nvp_size); nvp->nvp_namelen = be32_to_cpu(nvp->nvp_namelen); avail = nvp->nvp_size - nvp->nvp_namelen - sizeof(*nvp); nvdebug("left %zd nvp_size %u\n", left, nvp->nvp_size); if (left < nvp->nvp_size || avail < 0) break; namesize = (nvp->nvp_namelen + 3) & ~3; nvdebug("nvlist: size %u, namelen %u, name %*s\n", nvp->nvp_size, nvp->nvp_namelen, nvp->nvp_namelen, nvp->nvp_name); if (strncmp(nvp->nvp_name, "name", nvp->nvp_namelen) == 0) { struct nvstring *nvs = (void *)(nvp->nvp_name+namesize); nvs->nvs_type = be32_to_cpu(nvs->nvs_type); nvs->nvs_strlen = be32_to_cpu(nvs->nvs_strlen); if (nvs->nvs_strlen > UINT_MAX - sizeof(*nvs)) break; avail -= nvs->nvs_strlen + sizeof(*nvs); nvdebug("nvstring: type %u string %*s\n", nvs->nvs_type, nvs->nvs_strlen, nvs->nvs_string); if (nvs->nvs_type == DATA_TYPE_STRING && avail >= 0) blkid_probe_set_label(pr, nvs->nvs_string, nvs->nvs_strlen); found++; } else if (strncmp(nvp->nvp_name, "guid", nvp->nvp_namelen) == 0) { struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize); uint64_t nvu_value; memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value)); nvu->nvu_type = be32_to_cpu(nvu->nvu_type); nvu_value = be64_to_cpu(nvu_value); avail -= sizeof(*nvu); nvdebug("nvuint64: type %u value %"PRIu64"\n", nvu->nvu_type, nvu_value); if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0) blkid_probe_sprintf_value(pr, "UUID_SUB", "%"PRIu64, nvu_value); found++; } else if (strncmp(nvp->nvp_name, "pool_guid", nvp->nvp_namelen) == 0) { struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize); uint64_t nvu_value; memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value)); nvu->nvu_type = be32_to_cpu(nvu->nvu_type); nvu_value = be64_to_cpu(nvu_value); avail -= sizeof(*nvu); nvdebug("nvuint64: type %u value %"PRIu64"\n", nvu->nvu_type, nvu_value); if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0) blkid_probe_sprintf_uuid(pr, (unsigned char *) &nvu_value, sizeof(nvu_value), "%"PRIu64, nvu_value); found++; } if (left > nvp->nvp_size) left -= nvp->nvp_size; else left = 0; nvp = (struct nvpair *)((char *)nvp + nvp->nvp_size); } }
/* 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; }