diff options
Diffstat (limited to 'libblkid/src/superblocks/hpfs.c')
-rw-r--r-- | libblkid/src/superblocks/hpfs.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/libblkid/src/superblocks/hpfs.c b/libblkid/src/superblocks/hpfs.c new file mode 100644 index 0000000..dcf4520 --- /dev/null +++ b/libblkid/src/superblocks/hpfs.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * + * Inspired by libvolume_id by + * Kay Sievers <kay.sievers@vrfy.org> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdint.h> + +#include "superblocks.h" + +struct hpfs_boot_block +{ + uint8_t jmp[3]; + uint8_t oem_id[8]; + uint8_t bytes_per_sector[2]; + uint8_t sectors_per_cluster; + uint8_t n_reserved_sectors[2]; + uint8_t n_fats; + uint8_t n_rootdir_entries[2]; + uint8_t n_sectors_s[2]; + uint8_t media_byte; + uint16_t sectors_per_fat; + uint16_t sectors_per_track; + uint16_t heads_per_cyl; + uint32_t n_hidden_sectors; + uint32_t n_sectors_l; + uint8_t drive_number; + uint8_t mbz; + uint8_t sig_28h; + uint8_t vol_serno[4]; + uint8_t vol_label[11]; + uint8_t sig_hpfs[8]; + uint8_t pad[448]; + uint8_t magic[2]; +} __attribute__((packed)); + +struct hpfs_super_block +{ + uint8_t magic[4]; + uint8_t magic1[4]; + uint8_t version; +} __attribute__((packed)); + +struct hpfs_spare_super +{ + uint8_t magic[4]; + uint8_t magic1[4]; +} __attribute__((packed)); + + +#define HPFS_SB_OFFSET 0x2000 +#define HPFS_SBSPARE_OFFSET 0x2200 + +static int probe_hpfs(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct hpfs_super_block *hs; + struct hpfs_spare_super *hss; + struct hpfs_boot_block *hbb; + uint8_t version; + + /* super block */ + hs = blkid_probe_get_sb(pr, mag, struct hpfs_super_block); + if (!hs) + return errno ? -errno : 1; + version = hs->version; + + /* spare super block */ + hss = (struct hpfs_spare_super *) + blkid_probe_get_buffer(pr, + HPFS_SBSPARE_OFFSET, + sizeof(struct hpfs_spare_super)); + if (!hss) + return errno ? -errno : 1; + if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0) + return 1; + + /* boot block (with UUID and LABEL) */ + hbb = (struct hpfs_boot_block *) + blkid_probe_get_buffer(pr, + 0, + sizeof(struct hpfs_boot_block)); + if (!hbb) + return errno ? -errno : 1; + if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 && + memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 && + hbb->sig_28h == 0x28) { + blkid_probe_set_label(pr, hbb->vol_label, sizeof(hbb->vol_label)); + blkid_probe_sprintf_uuid(pr, + hbb->vol_serno, sizeof(hbb->vol_serno), + "%02X%02X-%02X%02X", + hbb->vol_serno[3], hbb->vol_serno[2], + hbb->vol_serno[1], hbb->vol_serno[0]); + } + blkid_probe_sprintf_version(pr, "%u", version); + blkid_probe_set_block_size(pr, 512); + + return 0; +} + +const struct blkid_idinfo hpfs_idinfo = +{ + .name = "hpfs", + .usage = BLKID_USAGE_FILESYSTEM, + .probefunc = probe_hpfs, + .magics = + { + { + .magic = "\x49\xe8\x95\xf9", + .len = 4, + .kboff = (HPFS_SB_OFFSET >> 10) + }, + { NULL } + } +}; + + |