X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=extras%2Fvolume_id%2Flib%2Fhpfs.c;h=0f0770f05fc175b904ec434899220991231584cb;hb=43f7e87f549c9b0630f27c05b0bf15102f1ed8cc;hp=ac5a35437a7494c78cc2b14612c69a744838b847;hpb=c70560feef0eb61a150cd2f956f0beead4313ffe;p=elogind.git diff --git a/extras/volume_id/lib/hpfs.c b/extras/volume_id/lib/hpfs.c index ac5a35437..0f0770f05 100644 --- a/extras/volume_id/lib/hpfs.c +++ b/extras/volume_id/lib/hpfs.c @@ -3,19 +3,24 @@ * * Copyright (C) 2005 Kay Sievers * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #ifndef _GNU_SOURCE #define _GNU_SOURCE 1 #endif -#ifdef HAVE_CONFIG_H -# include -#endif - #include #include #include @@ -24,33 +29,88 @@ #include #include "libvolume_id.h" -#include "util.h" +#include "libvolume_id-private.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]; +} PACKED; struct hpfs_super { uint8_t magic[4]; + uint8_t magic1[4]; uint8_t version; } PACKED; + +struct hpfs_spare_super +{ + uint8_t magic[4]; + uint8_t magic1[4]; +} PACKED; + #define HPFS_SUPERBLOCK_OFFSET 0x2000 +#define HPFS_SUPERBLOCK_SPARE_OFFSET 0x2200 int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size) { struct hpfs_super *hs; + struct hpfs_spare_super *hss; + struct hpfs_boot_block *hbb; + uint8_t version; - info("probing at offset 0x%llx\n", (unsigned long long) off); + info("probing at offset 0x%" PRIx64 "\n", off); - hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200); + hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x400); if (hs == NULL) return -1; + if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) != 0) + return -1; - if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) == 0) { - sprintf(id->type_version, "%u", hs->version); + hss = (struct hpfs_spare_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_SPARE_OFFSET, 0x200); + if (hss == NULL) + return -1; + if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0) + return -1; - volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); - id->type = "hpfs"; - return 0; + version = hs->version; + + /* if boot block looks valid, read label and uuid from there */ + hbb = (struct hpfs_boot_block *) volume_id_get_buffer(id, off, 0x200); + if (hbb == NULL) + return -1; + if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 && + memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 && + hbb->sig_28h == 0x28) { + volume_id_set_label_raw(id, hbb->vol_label, 11); + volume_id_set_label_string(id, hbb->vol_label, 11); + volume_id_set_uuid(id, hbb->vol_serno, 0, UUID_DOS); } + sprintf(id->type_version, "%u", version); + volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); + id->type = "hpfs"; - return -1; + return 0; }