From fbdc01bbc359a38383ce36db1682e0db6c1f4046 Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Wed, 20 Jul 2011 07:43:29 +0200 Subject: [PATCH] Add detection of Vmware VMFS partition --- src/Makefile.am | 4 +- src/analyse.c | 21 ++++++++++ src/analyse.h | 1 + src/common.h | 1 + src/godmode.c | 9 ++++- src/partnone.c | 9 +++++ src/vmfs.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vmfs.h | 49 +++++++++++++++++++++++ 8 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 src/vmfs.c create mode 100644 src/vmfs.h diff --git a/src/Makefile.am b/src/Makefile.am index 3581b753..9f4c5e07 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,8 +16,8 @@ EXTRA_PROGRAMS = photorecf base_C = autoset.c common.c crc.c ewf.c fnctdsk.c hdaccess.c hdcache.c hdwin32.c hidden.c hpa_dco.c intrf.c iso.c log.c log_part.c misc.c msdos.c parti386.c partgpt.c parthumax.c partmac.c partsun.c partnone.c partxbox.c io_redir.c ntfs_io.c ntfs_utl.c partauto.c sudo.c unicode.c win32.c base_H = alignio.h autoset.h common.h crc.h ewf.h fnctdsk.h hdaccess.h hdwin32.h hidden.h guid_cmp.h guid_cpy.h hdcache.h hpa_dco.h intrf.h iso.h iso9660.h lang.h log.h log_part.h misc.h types.h io_redir.h msdos.h ntfs_utl.h parti386.h partgpt.h parthumax.h partmac.h partsun.h partxbox.h partauto.h sudo.h unicode.h win32.h -fs_C = analyse.c bfs.c bsd.c btrfs.c cramfs.c exfat.c fat.c fatx.c ext2.c jfs.c hfs.c hfsp.c hpfs.c luks.c lvm.c md.c netware.c ntfs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c xfs.c zfs.c -fs_H = analyse.h bfs.h bsd.h btrfs.h cramfs.h exfat.h fat.h fatx.h ext2.h jfs_superblock.h jfs.h hfs.h hfsp.h hpfs.h luks.h lvm.h md.h netware.h ntfs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h xfs.h zfs.h +fs_C = analyse.c bfs.c bsd.c btrfs.c cramfs.c exfat.c fat.c fatx.c ext2.c jfs.c hfs.c hfsp.c hpfs.c luks.c lvm.c md.c netware.c ntfs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c vmfs.c xfs.c zfs.c +fs_H = analyse.h bfs.h bsd.h btrfs.h cramfs.h exfat.h fat.h fatx.h ext2.h jfs_superblock.h jfs.h hfs.h hfsp.h hpfs.h luks.h lvm.h md.h netware.h ntfs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h vmfs.h xfs.h zfs.h testdisk_ncurses_C = addpart.c adv.c askloc.c chgtype.c chgtypen.c dimage.c dirn.c dirpart.c diskacc.c diskcapa.c edit.c ext2_sb.c ext2_sbn.c fat1x.c fat32.c fat_adv.c fat_cluster.c fatn.c geometry.c godmode.c hiddenn.c intrface.c intrfn.c nodisk.c ntfs_adv.c ntfs_fix.c ntfs_udl.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c tanalyse.c tbanner.c tdelete.c tdiskop.c tdisksel.c testdisk.c texfat.c thfs.c tload.c tlog.c tmbrcode.c tntfs.c toptions.c tpartwr.c testdisk_ncurses_H = addpart.h adv.h askloc.h chgtype.h chgtypen.h dimage.h dirn.h dirpart.h diskacc.h diskcapa.h edit.h ext2_sb.h ext2_sbn.h fat1x.h fat32.h fat_adv.h fat_cluster.h fatn.h geometry.h godmode.h hiddenn.h intrface.h intrfn.h nodisk.h ntfs_udl.h partgptn.h parti386n.h partmacn.h partsunn.h partxboxn.h tanalyse.h tdelete.h tdiskop.h tdisksel.h texfat.h thfs.h tload.h tlog.h tmbrcode.h tntfs.h toptions.h tpartwr.h diff --git a/src/analyse.c b/src/analyse.c index b3c967df..269d814a 100644 --- a/src/analyse.c +++ b/src/analyse.c @@ -53,6 +53,7 @@ #include "swap.h" #include "sysv.h" #include "ufs.h" +#include "vmfs.h" #include "xfs.h" #include "zfs.h" #include "log.h" @@ -380,6 +381,26 @@ int search_type_128(unsigned char *buffer, disk_t *disk, partition_t *partition, return 0; } +int search_type_2048(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind) +{ + void *data; + if(verbose>2) + { + log_trace("search_type_2048 lba=%lu\n", + (long unsigned)(partition->part_offset/disk->sector_size)); + } + data=disk->pread_fast(disk, buffer, 2*DEFAULT_SECTOR_SIZE, partition->part_offset + 2048 * 512); + if(data==NULL) + return -1; + { + const struct vmfs_volume *sb_vmfs=(const struct vmfs_volume *)data; + if(le32(sb_vmfs->magic)==0xc001d00d && + recover_VMFS(disk, sb_vmfs, partition, verbose, dump_ind)==0) + return 1; + } + return 0; +} + int check_linux(disk_t *disk, partition_t *partition, const int verbose) { if(check_JFS(disk, partition)==0 || diff --git a/src/analyse.h b/src/analyse.h index d0a95cc0..a6c4f886 100644 --- a/src/analyse.h +++ b/src/analyse.h @@ -30,6 +30,7 @@ int search_type_8(unsigned char *buffer, disk_t *disk_car,partition_t *partition int search_type_16(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind); int search_type_64(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind); int search_type_128(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind); +int search_type_2048(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind); int search_EXFAT_backup(unsigned char *buffer, disk_t *disk, partition_t *partition); int search_FAT_backup(unsigned char *buffer, disk_t *disk_car,partition_t *partition, const int verbose, const int dump_ind); int search_HFS_backup(unsigned char *buffer, disk_t *disk_car,partition_t *partition, const int verbose, const int dump_ind); diff --git a/src/common.h b/src/common.h index 14830873..f3236d9a 100644 --- a/src/common.h +++ b/src/common.h @@ -262,6 +262,7 @@ enum upart_type { UP_SYSV4, UP_UFS, UP_UFS2, + UP_VMFS, UP_XFS, UP_XFS2, UP_XFS3, diff --git a/src/godmode.c b/src/godmode.c index 640d1c0b..ce2d1b3f 100644 --- a/src/godmode.c +++ b/src/godmode.c @@ -644,7 +644,7 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o if(res<=0 && test_nbr==6) { if(search_now==0) - test_nbr=13; + test_nbr=14; else { if(disk_car->pread(disk_car, buffer_disk0, 8 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 8 * DEFAULT_SECTOR_SIZE) @@ -691,7 +691,12 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o res=search_type_128(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } - if(test_nbr>=13) + if(res<=0 && test_nbr==13) + { + res=search_type_2048(buffer_disk,disk_car,partition,verbose,dump_ind); + test_nbr++; + } + if(test_nbr>=14) { sector_inc=1; test_nbr=0; diff --git a/src/partnone.c b/src/partnone.c index 50260048..ef02c517 100644 --- a/src/partnone.c +++ b/src/partnone.c @@ -65,6 +65,7 @@ #include "swap.h" #include "ufs.h" #include "xfs.h" +#include "vmfs.h" #include "log.h" static int check_part_none(disk_t *disk_car, const int verbose,partition_t *partition,const int saveheader); @@ -119,6 +120,7 @@ static const struct systypes none_sys_types[] = { {UP_UFS, "UFS"}, {UP_UFS2, "UFS 2"}, {UP_UNK, "Unknown"}, + {UP_VMFS, "VMFS"}, {UP_XFS, "XFS"}, {UP_XFS2, "XFS 2"}, {UP_XFS3, "XFS 3"}, @@ -225,6 +227,10 @@ static list_part_t *read_part_none(disk_t *disk, const int verbose, const int sa res=search_type_128(buffer_disk, disk, partition,verbose,0); } if(res<=0) + { + res=search_type_2048(buffer_disk, disk, partition,verbose,0); + } + if(res<=0) { /* Search FAT32 backup */ partition->part_offset = 6*512; res=search_FAT_backup(buffer_disk, disk, partition, verbose, 0); @@ -414,6 +420,9 @@ static int check_part_none(disk_t *disk_car,const int verbose,partition_t *parti case UP_UFS2: ret=check_ufs(disk_car,partition,verbose); break; + case UP_VMFS: + ret=check_VMFS(disk_car, partition); + break; case UP_XFS: case UP_XFS2: case UP_XFS3: diff --git a/src/vmfs.c b/src/vmfs.c new file mode 100644 index 00000000..0a2fd0df --- /dev/null +++ b/src/vmfs.c @@ -0,0 +1,102 @@ +/* + + File: vmfs.c + + Copyright (C) 2011 Christophe GRENIER + + This software 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, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef HAVE_CONFIG_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#include +#include "types.h" +#include "common.h" +#include "fnctdsk.h" +#include "log.h" +#include "vmfs.h" + +static int test_VMFS(disk_t *disk, const struct vmfs_volume *sb, partition_t *partition, const int dump_ind); +static int set_VMFS_info(const struct vmfs_volume *sb, partition_t *partition); + +int check_VMFS(disk_t *disk,partition_t *partition) +{ + unsigned char *buffer=(unsigned char*)MALLOC(2*DEFAULT_SECTOR_SIZE); + if(disk->pread(disk, buffer, 2*DEFAULT_SECTOR_SIZE, partition->part_offset+0x100000) != DEFAULT_SECTOR_SIZE) + { + free(buffer); + return 1; + } + if(test_VMFS(disk, (struct vmfs_volume*)buffer, partition, 0)!=0) + { + free(buffer); + return 1; + } + set_VMFS_info((struct vmfs_volume*)buffer, partition); + free(buffer); + return 0; +} + +static int set_VMFS_info(const struct vmfs_volume *sb, partition_t *partition) +{ + sprintf(partition->info,"VMFS %lu", (long unsigned)le32(sb->version)); + return 0; +} + +int recover_VMFS(disk_t *disk, const struct vmfs_volume *sb, partition_t *partition, const int verbose, const int dump_ind) +{ + const struct vmfs_lvm* lvm=(const struct vmfs_lvm*)(((const char *)sb)+0x200); + if(test_VMFS(disk, sb, partition, dump_ind)!=0) + return 1; + if(partition==NULL) + return 0; + set_VMFS_info(sb, partition); + partition->part_type_i386=P_VMFS; + partition->part_size=(uint64_t)le64(lvm->size); + partition->blocksize=0; + partition->sborg_offset=0; + partition->sb_offset=0; + if(verbose>0) + { + log_info("\n"); + } + return 0; +} + +static int test_VMFS(disk_t *disk, const struct vmfs_volume *sb, partition_t *partition, const int dump_ind) +{ + if(le32(sb->magic)!=0xc001d00d) + return 1; + if(dump_ind!=0) + { + if(partition!=NULL && disk!=NULL) + log_info("\nVMFS magic value at %u/%u/%u\n", + offset2cylinder(disk,partition->part_offset), + offset2head(disk,partition->part_offset), + offset2sector(disk,partition->part_offset)); + dump_log(sb,DEFAULT_SECTOR_SIZE); + } + if(partition==NULL) + return 0; + partition->upart_type=UP_VMFS; + return 0; +} diff --git a/src/vmfs.h b/src/vmfs.h new file mode 100644 index 00000000..e7dc37b2 --- /dev/null +++ b/src/vmfs.h @@ -0,0 +1,49 @@ +/* + + File: vmfs.h + + Copyright (C) 2009 Christophe GRENIER + + This software 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, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ + +#ifndef _VMFS_H +#define _VMFS_H +#ifdef __cplusplus +extern "C" { +#endif +/* VMFS boot block */ +#define VDEV_BOOT_MAGIC 0x2f5b007b10cULL +#define VDEV_BOOT_VERSION 1 /* version number */ +#define VDEV_BOOT_HEADER_SIZE (8 << 10) + +struct vmfs_volume +{ + uint32_t magic; + uint32_t version; +} __attribute__ ((__packed__)); +struct vmfs_lvm +{ + uint64_t size; + uint64_t blocks; +} __attribute__ ((__packed__)); + +int check_VMFS(disk_t *disk,partition_t *partition); +int recover_VMFS(disk_t *disk, const struct vmfs_volume *sb, partition_t *partition, const int verbose, const int dump_ind); +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif +#endif