static int probe_exfat(blkid_probe pr, const struct blkid_idmag *mag) { struct exfat_super_block *sb; struct exfat_entry_label *label; sb = blkid_probe_get_sb(pr, mag, struct exfat_super_block); if (!sb || !CLUSTER_SIZE(sb)) return errno ? -errno : BLKID_PROBE_NONE; label = find_label(pr, sb); if (label) blkid_probe_set_utf8label(pr, label->name, min(label->length * 2, 30), BLKID_ENC_UTF16LE); else if (errno) return -errno; blkid_probe_sprintf_uuid(pr, sb->volume_serial, 4, "%02hhX%02hhX-%02hhX%02hhX", sb->volume_serial[3], sb->volume_serial[2], sb->volume_serial[1], sb->volume_serial[0]); blkid_probe_sprintf_version(pr, "%u.%u", sb->version.vermaj, sb->version.vermin); return BLKID_PROBE_OK; }
/* 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; }
static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag) { struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; struct hfsplus_bnode_descriptor *descr; struct hfsplus_bheader_record *bnode; struct hfsplus_catalog_key *key; struct hfsplus_vol_header *hfsplus; struct hfs_mdb *sbd; unsigned int alloc_block_size; unsigned int alloc_first_block; unsigned int embed_first_block; unsigned int off = 0; unsigned int blocksize; unsigned int cat_block; unsigned int ext_block_start; unsigned int ext_block_count; unsigned int record_count; unsigned int leaf_node_head; unsigned int leaf_node_count; unsigned int leaf_node_size; unsigned int leaf_block; int ext; uint64_t leaf_off; unsigned char *buf; sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb); if (!sbd) return -1; /* Check for a HFS+ volume embedded in a HFS volume */ if (memcmp(sbd->signature, "BD", 2) == 0) { if ((memcmp(sbd->embed_sig, "H+", 2) != 0) && (memcmp(sbd->embed_sig, "HX", 2) != 0)) /* This must be an HFS volume, so fail */ return 1; alloc_block_size = be32_to_cpu(sbd->al_blk_size); alloc_first_block = be16_to_cpu(sbd->al_bl_st); embed_first_block = be16_to_cpu(sbd->embed_startblock); off = (alloc_first_block * 512) + (embed_first_block * alloc_block_size); buf = blkid_probe_get_buffer(pr, off + (mag->kboff * 1024), sizeof(struct hfsplus_vol_header)); hfsplus = (struct hfsplus_vol_header *) buf; } else hfsplus = blkid_probe_get_sb(pr, mag, struct hfsplus_vol_header); if (!hfsplus) return -1; if ((memcmp(hfsplus->signature, "H+", 2) != 0) && (memcmp(hfsplus->signature, "HX", 2) != 0)) return 1; hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id)); blocksize = be32_to_cpu(hfsplus->blocksize); if (blocksize < HFSPLUS_SECTOR_SIZE) return -1; memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); cat_block = be32_to_cpu(extents[0].start_block); buf = blkid_probe_get_buffer(pr, off + ((blkid_loff_t) cat_block * blocksize), 0x2000); if (!buf) return 0; bnode = (struct hfsplus_bheader_record *) &buf[sizeof(struct hfsplus_bnode_descriptor)]; leaf_node_head = be32_to_cpu(bnode->leaf_head); leaf_node_size = be16_to_cpu(bnode->node_size); leaf_node_count = be32_to_cpu(bnode->leaf_count); if (leaf_node_count == 0) return 0; leaf_block = (leaf_node_head * leaf_node_size) / blocksize; /* get physical location */ for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) { ext_block_start = be32_to_cpu(extents[ext].start_block); ext_block_count = be32_to_cpu(extents[ext].block_count); if (ext_block_count == 0) return 0; /* this is our extent */ if (leaf_block < ext_block_count) break; leaf_block -= ext_block_count; } if (ext == HFSPLUS_EXTENT_COUNT) return 0; leaf_off = (ext_block_start + leaf_block) * blocksize; buf = blkid_probe_get_buffer(pr, (blkid_loff_t) off + leaf_off, leaf_node_size); if (!buf) return 0; descr = (struct hfsplus_bnode_descriptor *) buf; record_count = be16_to_cpu(descr->num_recs); if (record_count == 0) return 0; if (descr->type != HFS_NODE_LEAF) return 0; key = (struct hfsplus_catalog_key *) &buf[sizeof(struct hfsplus_bnode_descriptor)]; if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID) return 0; blkid_probe_set_utf8label(pr, key->unicode, be16_to_cpu(key->unicode_len) * 2, BLKID_ENC_UTF16BE); return 0; }