TestDisk: detect APFS partition
This commit is contained in:
parent
8f11e3a897
commit
cd7b7032f6
9 changed files with 416 additions and 13 deletions
|
@ -1,4 +1,4 @@
|
||||||
.PRECIOUS: session_%.framac session_fidentify-%.framac
|
.PRECIOUS: session_%.framac session_fidentify-%.framac session_photorec-%.framac
|
||||||
FRAMA_C_FLAGS=-machdep x86_64 \
|
FRAMA_C_FLAGS=-machdep x86_64 \
|
||||||
-warn-left-shift-negative \
|
-warn-left-shift-negative \
|
||||||
-warn-right-shift-negative \
|
-warn-right-shift-negative \
|
||||||
|
@ -36,13 +36,13 @@ endif
|
||||||
bin_PROGRAMS = testdisk photorec fidentify $(QPHOTOREC)
|
bin_PROGRAMS = testdisk photorec fidentify $(QPHOTOREC)
|
||||||
EXTRA_PROGRAMS = photorecf fuzzerfidentify
|
EXTRA_PROGRAMS = photorecf fuzzerfidentify
|
||||||
|
|
||||||
smallbase_C = common.c crc.c ext2_common.c fat_common.c log.c misc.c setdate.c
|
smallbase_C = common.c crc.c apfs_common.c ext2_common.c fat_common.c log.c misc.c setdate.c
|
||||||
smallbase_H = common.h crc.h ext2_common.h fat_common.h log.h misc.h setdate.h
|
smallbase_H = common.h crc.h apfs_common.h ext2_common.h fat_common.h log.h misc.h setdate.h
|
||||||
base_C = $(smallbase_C) autoset.c ewf.c fnctdsk.c hdaccess.c hdcache.c hdwin32.c hidden.c hpa_dco.c intrf.c iso.c list_sort.c log_part.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_C = $(smallbase_C) autoset.c ewf.c fnctdsk.c hdaccess.c hdcache.c hdwin32.c hidden.c hpa_dco.c intrf.c iso.c list_sort.c log_part.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 = $(smallbase_H) alignio.h autoset.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 list.h list_sort.h log_part.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
|
base_H = $(smallbase_H) alignio.h autoset.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 list.h list_sort.h log_part.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 ext2.c fat.c fatx.c f2fs.c jfs.c gfs2.c hfs.c hfsp.c hpfs.c luks.c lvm.c md.c netware.c ntfs.c refs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c vmfs.c wbfs.c xfs.c zfs.c
|
fs_C = analyse.c apfs.c bfs.c bsd.c btrfs.c cramfs.c exfat.c ext2.c fat.c fatx.c f2fs.c jfs.c gfs2.c hfs.c hfsp.c hpfs.c luks.c lvm.c md.c netware.c ntfs.c refs.c rfs.c savehdr.c sun.c swap.c sysv.c ufs.c vmfs.c wbfs.c xfs.c zfs.c
|
||||||
fs_H = analyse.h bfs.h bsd.h btrfs.h cramfs.h exfat.h ext2.h fat.h fatx.h f2fs.h f2fs_fs.h jfs_superblock.h jfs.h gfs2.h hfs.h hfsp.h hpfs.h hfsp_struct.h luks.h luks_struct.h lvm.h md.h netware.h ntfs.h ntfs_struct.h refs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h vmfs.h wbfs.h xfs.h xfs_struct.h zfs.h
|
fs_H = analyse.h apfs.h bfs.h bsd.h btrfs.h cramfs.h exfat.h ext2.h fat.h fatx.h f2fs.h f2fs_fs.h jfs_superblock.h jfs.h gfs2.h hfs.h hfsp.h hpfs.h hfsp_struct.h luks.h luks_struct.h lvm.h md.h netware.h ntfs.h ntfs_struct.h refs.h rfs.h savehdr.h sun.h swap.h sysv.h ufs.h vmfs.h wbfs.h xfs.h xfs_struct.h zfs.h
|
||||||
|
|
||||||
testdisk_ncurses_C = addpart.c addpartn.c adv.c askloc.c chgarch.c chgarchn.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 geometryn.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_C = addpart.c addpartn.c adv.c askloc.c chgarch.c chgarchn.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 geometryn.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 addpartn.h adv.h askloc.h chgarch.h chgarchn.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 geometryn.h godmode.h hiddenn.h intrface.h intrfn.h nodisk.h ntfs_adv.h ntfs_fix.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
|
testdisk_ncurses_H = addpart.h addpartn.h adv.h askloc.h chgarch.h chgarchn.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 geometryn.h godmode.h hiddenn.h intrface.h intrfn.h nodisk.h ntfs_adv.h ntfs_fix.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
|
||||||
|
|
|
@ -30,13 +30,15 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "analyse.h"
|
#include "analyse.h"
|
||||||
|
#include "fat.h"
|
||||||
|
#include "exfat.h"
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
|
#include "apfs.h"
|
||||||
#include "bfs.h"
|
#include "bfs.h"
|
||||||
#include "bsd.h"
|
#include "bsd.h"
|
||||||
#include "btrfs.h"
|
#include "btrfs.h"
|
||||||
#include "cramfs.h"
|
#include "cramfs.h"
|
||||||
#include "exfat.h"
|
|
||||||
#include "ext2.h"
|
#include "ext2.h"
|
||||||
#include "fat.h"
|
|
||||||
#include "fatx.h"
|
#include "fatx.h"
|
||||||
#include "f2fs_fs.h"
|
#include "f2fs_fs.h"
|
||||||
#include "f2fs.h"
|
#include "f2fs.h"
|
||||||
|
@ -61,8 +63,9 @@
|
||||||
#include "wbfs.h"
|
#include "wbfs.h"
|
||||||
#include "xfs.h"
|
#include "xfs.h"
|
||||||
#include "zfs.h"
|
#include "zfs.h"
|
||||||
#include "log.h"
|
#endif
|
||||||
#include "parti386.h"
|
#include "parti386.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
int search_NTFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
int search_NTFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
||||||
{
|
{
|
||||||
|
@ -70,10 +73,12 @@ int search_NTFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partiti
|
||||||
return -1;
|
return -1;
|
||||||
{
|
{
|
||||||
const struct ntfs_boot_sector *ntfs_header=(const struct ntfs_boot_sector*)buffer;
|
const struct ntfs_boot_sector *ntfs_header=(const struct ntfs_boot_sector*)buffer;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
/* NTFS recovery using backup sector */
|
/* NTFS recovery using backup sector */
|
||||||
if(le16(ntfs_header->marker)==0xAA55 &&
|
if(le16(ntfs_header->marker)==0xAA55 &&
|
||||||
recover_NTFS(disk, ntfs_header, partition, verbose, dump_ind, 1)==0)
|
recover_NTFS(disk, ntfs_header, partition, verbose, dump_ind, 1)==0)
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -82,6 +87,7 @@ int search_HFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partitio
|
||||||
{
|
{
|
||||||
if(disk->pread(disk, buffer, 0x400, partition->part_offset)!= 0x400)
|
if(disk->pread(disk, buffer, 0x400, partition->part_offset)!= 0x400)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
{
|
{
|
||||||
const hfs_mdb_t *hfs_mdb=(const hfs_mdb_t *)buffer;
|
const hfs_mdb_t *hfs_mdb=(const hfs_mdb_t *)buffer;
|
||||||
const struct hfsp_vh *vh=(const struct hfsp_vh *)buffer;
|
const struct hfsp_vh *vh=(const struct hfsp_vh *)buffer;
|
||||||
|
@ -99,6 +105,7 @@ int search_HFS_backup(unsigned char *buffer, disk_t *disk, partition_t *partitio
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +142,7 @@ int search_FAT_backup(unsigned char *buffer, disk_t *disk, partition_t *partitio
|
||||||
|
|
||||||
int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
||||||
{
|
{
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
/* Expect a buffer filled with 8k to handle the SWAP detection */
|
/* Expect a buffer filled with 8k to handle the SWAP detection */
|
||||||
const pv_disk_t *pv=(const pv_disk_t *)buffer;
|
const pv_disk_t *pv=(const pv_disk_t *)buffer;
|
||||||
const struct cramfs_super *cramfs=(const struct cramfs_super *)buffer;
|
const struct cramfs_super *cramfs=(const struct cramfs_super *)buffer;
|
||||||
|
@ -149,6 +157,7 @@ int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partit
|
||||||
const struct xfs_sb *xfs=(const struct xfs_sb *)buffer;
|
const struct xfs_sb *xfs=(const struct xfs_sb *)buffer;
|
||||||
const union swap_header *swap_header=(const union swap_header *)buffer;
|
const union swap_header *swap_header=(const union swap_header *)buffer;
|
||||||
const struct ReFS_boot_sector *refs_header=(const struct ReFS_boot_sector *)buffer;
|
const struct ReFS_boot_sector *refs_header=(const struct ReFS_boot_sector *)buffer;
|
||||||
|
const nx_superblock_t *apfs=(const nx_superblock_t *)buffer;
|
||||||
static const uint8_t LUKS_MAGIC[LUKS_MAGIC_L] = {'L','U','K','S', 0xba, 0xbe};
|
static const uint8_t LUKS_MAGIC[LUKS_MAGIC_L] = {'L','U','K','S', 0xba, 0xbe};
|
||||||
// assert(sizeof(union swap_header)<=8*DEFAULT_SECTOR_SIZE);
|
// assert(sizeof(union swap_header)<=8*DEFAULT_SECTOR_SIZE);
|
||||||
// assert(sizeof(pv_disk_t)<=8*DEFAULT_SECTOR_SIZE);
|
// assert(sizeof(pv_disk_t)<=8*DEFAULT_SECTOR_SIZE);
|
||||||
|
@ -162,6 +171,9 @@ int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partit
|
||||||
log_trace("search_type_0 lba=%lu\n",
|
log_trace("search_type_0 lba=%lu\n",
|
||||||
(long unsigned)(partition->part_offset/disk->sector_size));
|
(long unsigned)(partition->part_offset/disk->sector_size));
|
||||||
}
|
}
|
||||||
|
if(le32(apfs->nx_magic)== 0x4253584e &&
|
||||||
|
recover_APFS(disk, apfs, partition, verbose, dump_ind)==0)
|
||||||
|
return 1;
|
||||||
if((memcmp(swap_header->magic.magic, "SWAP", 4)==0 ||
|
if((memcmp(swap_header->magic.magic, "SWAP", 4)==0 ||
|
||||||
memcmp(swap_header->magic8k.magic, "SWAP", 4)==0) &&
|
memcmp(swap_header->magic8k.magic, "SWAP", 4)==0) &&
|
||||||
recover_Linux_SWAP(swap_header, partition)==0)
|
recover_Linux_SWAP(swap_header, partition)==0)
|
||||||
|
@ -212,16 +224,20 @@ int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partit
|
||||||
if(cramfs->magic==le32(CRAMFS_MAGIC) &&
|
if(cramfs->magic==le32(CRAMFS_MAGIC) &&
|
||||||
recover_cramfs(disk, cramfs, partition, verbose, dump_ind)==0)
|
recover_cramfs(disk, cramfs, partition, verbose, dump_ind)==0)
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
|
#if !defined(SINGLE_PARTITION_TYPE) || defined(SINGLE_PARTITION_I386)
|
||||||
/* Try to locate logical partition that may host truecrypt encrypted filesystem */
|
/* Try to locate logical partition that may host truecrypt encrypted filesystem */
|
||||||
if(buffer[0x1fe]==0x55 && buffer[0x1ff]==0xAA &&
|
if(buffer[0x1fe]==0x55 && buffer[0x1ff]==0xAA &&
|
||||||
recover_i386_logical(disk, buffer, partition)==0 &&
|
recover_i386_logical(disk, buffer, partition)==0 &&
|
||||||
partition->upart_type==UP_UNK)
|
partition->upart_type==UP_UNK)
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int search_type_1(const unsigned char *buffer, const disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
int search_type_1(const unsigned char *buffer, const disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
||||||
{
|
{
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
const struct disklabel *bsd_header=(const struct disklabel *)(buffer+0x200);
|
const struct disklabel *bsd_header=(const struct disklabel *)(buffer+0x200);
|
||||||
const struct disk_super_block *beos_block=(const struct disk_super_block*)(buffer+0x200);
|
const struct disk_super_block *beos_block=(const struct disk_super_block*)(buffer+0x200);
|
||||||
const struct cramfs_super *cramfs=(const struct cramfs_super *)(buffer+0x200);
|
const struct cramfs_super *cramfs=(const struct cramfs_super *)(buffer+0x200);
|
||||||
|
@ -256,11 +272,13 @@ int search_type_1(const unsigned char *buffer, const disk_t *disk, partition_t *
|
||||||
if(le32(sunlabel->magic_start) == SUN_LABEL_MAGIC_START &&
|
if(le32(sunlabel->magic_start) == SUN_LABEL_MAGIC_START &&
|
||||||
recover_sun_i386(disk, sunlabel, partition, verbose, dump_ind)==0)
|
recover_sun_i386(disk, sunlabel, partition, verbose, dump_ind)==0)
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int search_type_2(const unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
int search_type_2(const unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
|
||||||
{
|
{
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
const hfs_mdb_t *hfs_mdb=(const hfs_mdb_t *)(buffer+0x400);
|
const hfs_mdb_t *hfs_mdb=(const hfs_mdb_t *)(buffer+0x400);
|
||||||
const struct hfsp_vh *vh=(const struct hfsp_vh *)(buffer+0x400);
|
const struct hfsp_vh *vh=(const struct hfsp_vh *)(buffer+0x400);
|
||||||
const struct ext2_super_block *sb=(const struct ext2_super_block*)(buffer+0x400);
|
const struct ext2_super_block *sb=(const struct ext2_super_block*)(buffer+0x400);
|
||||||
|
@ -286,6 +304,7 @@ int search_type_2(const unsigned char *buffer, disk_t *disk, partition_t *partit
|
||||||
if(sb_f2fs->magic == le32(F2FS_SUPER_MAGIC) &&
|
if(sb_f2fs->magic == le32(F2FS_SUPER_MAGIC) &&
|
||||||
recover_f2fs(disk, sb_f2fs, partition)==0)
|
recover_f2fs(disk, sb_f2fs, partition)==0)
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,6 +317,7 @@ int search_type_8(unsigned char *buffer, disk_t *disk,partition_t *partition,con
|
||||||
}
|
}
|
||||||
if(disk->pread(disk, buffer, 4096, partition->part_offset + 4096) != 4096)
|
if(disk->pread(disk, buffer, 4096, partition->part_offset + 4096) != 4096)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
{ /* MD 1.2 */
|
{ /* MD 1.2 */
|
||||||
const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer;
|
const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer;
|
||||||
if(le32(sb1->major_version)==1 &&
|
if(le32(sb1->major_version)==1 &&
|
||||||
|
@ -307,6 +327,7 @@ int search_type_8(unsigned char *buffer, disk_t *disk,partition_t *partition,con
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,6 +341,7 @@ int search_type_16(unsigned char *buffer, disk_t *disk,partition_t *partition,co
|
||||||
/* 8k offset */
|
/* 8k offset */
|
||||||
if(disk->pread(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 16 * 512) != 3 * DEFAULT_SECTOR_SIZE)
|
if(disk->pread(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 16 * 512) != 3 * DEFAULT_SECTOR_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
{
|
{
|
||||||
const struct ufs_super_block *ufs=(const struct ufs_super_block *)buffer;
|
const struct ufs_super_block *ufs=(const struct ufs_super_block *)buffer;
|
||||||
const struct vdev_boot_header *zfs=(const struct vdev_boot_header*)buffer;
|
const struct vdev_boot_header *zfs=(const struct vdev_boot_header*)buffer;
|
||||||
|
@ -332,6 +354,7 @@ int search_type_16(unsigned char *buffer, disk_t *disk,partition_t *partition,co
|
||||||
recover_ZFS(disk, zfs, partition, verbose, dump_ind)==0)
|
recover_ZFS(disk, zfs, partition, verbose, dump_ind)==0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +368,7 @@ int search_type_64(unsigned char *buffer, disk_t *disk,partition_t *partition,co
|
||||||
/* 32k offset */
|
/* 32k offset */
|
||||||
if(disk->pread(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 63 * 512) != 3 * DEFAULT_SECTOR_SIZE)
|
if(disk->pread(disk, buffer, 3 * DEFAULT_SECTOR_SIZE, partition->part_offset + 63 * 512) != 3 * DEFAULT_SECTOR_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
{
|
{
|
||||||
const struct jfs_superblock* jfs=(const struct jfs_superblock*)(buffer+0x200);
|
const struct jfs_superblock* jfs=(const struct jfs_superblock*)(buffer+0x200);
|
||||||
/* Test JFS */
|
/* Test JFS */
|
||||||
|
@ -352,6 +376,7 @@ int search_type_64(unsigned char *buffer, disk_t *disk,partition_t *partition,co
|
||||||
recover_JFS(disk, jfs, partition, verbose, dump_ind)==0)
|
recover_JFS(disk, jfs, partition, verbose, dump_ind)==0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,6 +389,7 @@ int search_type_128(unsigned char *buffer, disk_t *disk, partition_t *partition,
|
||||||
}
|
}
|
||||||
if(disk->pread(disk, buffer, 11 * DEFAULT_SECTOR_SIZE, partition->part_offset + 126 * 512) != 11 * DEFAULT_SECTOR_SIZE)
|
if(disk->pread(disk, buffer, 11 * DEFAULT_SECTOR_SIZE, partition->part_offset + 126 * 512) != 11 * DEFAULT_SECTOR_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
{
|
{
|
||||||
const unsigned char *buffer_1024=buffer+0x400;
|
const unsigned char *buffer_1024=buffer+0x400;
|
||||||
const struct reiserfs_super_block *rfs=(const struct reiserfs_super_block *)buffer_1024;
|
const struct reiserfs_super_block *rfs=(const struct reiserfs_super_block *)buffer_1024;
|
||||||
|
@ -389,6 +415,7 @@ int search_type_128(unsigned char *buffer, disk_t *disk, partition_t *partition,
|
||||||
recover_gfs2(disk, gfs2, partition, dump_ind)==0)
|
recover_gfs2(disk, gfs2, partition, dump_ind)==0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,17 +428,20 @@ int search_type_2048(unsigned char *buffer, disk_t *disk, partition_t *partition
|
||||||
}
|
}
|
||||||
if(disk->pread(disk, buffer, 2*DEFAULT_SECTOR_SIZE, partition->part_offset + 2048 * 512) != 2*DEFAULT_SECTOR_SIZE)
|
if(disk->pread(disk, buffer, 2*DEFAULT_SECTOR_SIZE, partition->part_offset + 2048 * 512) != 2*DEFAULT_SECTOR_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
{
|
{
|
||||||
const struct vmfs_volume *sb_vmfs=(const struct vmfs_volume *)buffer;
|
const struct vmfs_volume *sb_vmfs=(const struct vmfs_volume *)buffer;
|
||||||
if(le32(sb_vmfs->magic)==0xc001d00d &&
|
if(le32(sb_vmfs->magic)==0xc001d00d &&
|
||||||
recover_VMFS(disk, sb_vmfs, partition, verbose, dump_ind)==0)
|
recover_VMFS(disk, sb_vmfs, partition, verbose, dump_ind)==0)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_linux(disk_t *disk, partition_t *partition, const int verbose)
|
int check_linux(disk_t *disk, partition_t *partition, const int verbose)
|
||||||
{
|
{
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
if(check_JFS(disk, partition)==0 ||
|
if(check_JFS(disk, partition)==0 ||
|
||||||
check_rfs(disk, partition, verbose)==0 ||
|
check_rfs(disk, partition, verbose)==0 ||
|
||||||
check_EXT2(disk, partition, verbose)==0 ||
|
check_EXT2(disk, partition, verbose)==0 ||
|
||||||
|
@ -423,6 +453,7 @@ int check_linux(disk_t *disk, partition_t *partition, const int verbose)
|
||||||
check_gfs2(disk, partition)==0 ||
|
check_gfs2(disk, partition)==0 ||
|
||||||
check_ZFS(disk, partition)==0)
|
check_ZFS(disk, partition)==0)
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
105
src/apfs.c
Normal file
105
src/apfs.c
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
File: apfs.c
|
||||||
|
|
||||||
|
Copyright (C) 2021 Christophe GRENIER <grenier@cgsecurity.org>
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#include <time.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "apfs.h"
|
||||||
|
#include "fnctdsk.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "guid_cpy.h"
|
||||||
|
|
||||||
|
static void set_APFS_info(const nx_superblock_t *sb, partition_t *partition)
|
||||||
|
{
|
||||||
|
partition->upart_type=UP_APFS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_APFS(disk_t *disk_car, partition_t *partition)
|
||||||
|
{
|
||||||
|
unsigned char *buffer=(unsigned char*)MALLOC(APFS_SUPERBLOCK_SIZE);
|
||||||
|
const nx_superblock_t* sb=(const nx_superblock_t *)buffer;
|
||||||
|
if(disk_car->pread(disk_car, buffer, APFS_SUPERBLOCK_SIZE, partition->part_offset) != APFS_SUPERBLOCK_SIZE)
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(test_APFS(sb, partition)!=0)
|
||||||
|
{
|
||||||
|
free(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
set_APFS_info(sb, partition);
|
||||||
|
free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recover_APFS(const disk_t *disk, const nx_superblock_t *sb, partition_t *partition, const int verbose, const int dump_ind)
|
||||||
|
{
|
||||||
|
if(test_APFS(sb, partition)!=0)
|
||||||
|
return 1;
|
||||||
|
if(dump_ind!=0)
|
||||||
|
{
|
||||||
|
if(partition!=NULL && disk!=NULL)
|
||||||
|
log_info("\nAPFS magic value at %u/%u/%u\n",
|
||||||
|
offset2cylinder(disk,partition->part_offset),
|
||||||
|
offset2head(disk,partition->part_offset),
|
||||||
|
offset2sector(disk,partition->part_offset));
|
||||||
|
/* There is a little offset ... */
|
||||||
|
dump_log(sb,DEFAULT_SECTOR_SIZE);
|
||||||
|
}
|
||||||
|
if(partition==NULL)
|
||||||
|
return 0;
|
||||||
|
set_APFS_info(sb, partition);
|
||||||
|
partition->part_type_i386=P_LINUX;
|
||||||
|
partition->part_type_mac=PMAC_LINUX;
|
||||||
|
partition->part_type_sun=PSUN_LINUX;
|
||||||
|
partition->part_type_gpt=GPT_ENT_TYPE_MAC_APFS;
|
||||||
|
partition->part_size=le32(sb->nx_block_size) * le64(sb->nx_block_count);
|
||||||
|
guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->nx_uuid);
|
||||||
|
if(verbose>0)
|
||||||
|
{
|
||||||
|
log_info("\n");
|
||||||
|
}
|
||||||
|
partition->sborg_offset=0;
|
||||||
|
partition->sb_size=le32(sb->nx_block_size);
|
||||||
|
partition->sb_offset=0;
|
||||||
|
if(verbose>0)
|
||||||
|
{
|
||||||
|
log_info("recover_APFS: s_blocksize=%u\n", partition->blocksize);
|
||||||
|
log_info("recover_APFS: s_blocks_count %lu\n", (long unsigned int)le64(sb->nx_block_count));
|
||||||
|
if(disk==NULL)
|
||||||
|
log_info("recover_APFS: part_size %lu\n", (long unsigned)(partition->part_size / DEFAULT_SECTOR_SIZE));
|
||||||
|
else
|
||||||
|
log_info("recover_APFS: part_size %lu\n", (long unsigned)(partition->part_size / disk->sector_size));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
48
src/apfs.h
Normal file
48
src/apfs.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
File: apfs.h
|
||||||
|
|
||||||
|
Copyright (C) 2021 Christophe GRENIER <grenier@cgsecurity.org>
|
||||||
|
|
||||||
|
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 _APFS_H
|
||||||
|
#define _APFS_H
|
||||||
|
#include "apfs_common.h"
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
/*@
|
||||||
|
@ requires \valid(disk_car);
|
||||||
|
@ requires valid_disk(disk_car);
|
||||||
|
@ requires \valid(partition);
|
||||||
|
@ requires \separated(disk_car, partition);
|
||||||
|
@*/
|
||||||
|
int check_APFS(disk_t *disk_car, partition_t *partition);
|
||||||
|
|
||||||
|
/*@
|
||||||
|
@ requires \valid(disk_car);
|
||||||
|
@ requires valid_disk(disk_car);
|
||||||
|
@ requires \valid_read(sb);
|
||||||
|
@ requires \valid(partition);
|
||||||
|
@ requires \separated(disk_car, partition);
|
||||||
|
@*/
|
||||||
|
int recover_APFS(const disk_t *disk_car, const nx_superblock_t *sb, partition_t *partition, const int verbose, const int dump_ind);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* closing brace for extern "C" */
|
||||||
|
#endif
|
||||||
|
#endif
|
76
src/apfs_common.c
Normal file
76
src/apfs_common.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
File: apfs_common.c
|
||||||
|
|
||||||
|
Copyright (C) 2021 Christophe GRENIER <grenier@cgsecurity.org>
|
||||||
|
|
||||||
|
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 <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
#include "types.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "apfs_common.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
static uint64_t fletcher64(const uint32_t *data, const size_t cnt, const uint64_t init)
|
||||||
|
{
|
||||||
|
size_t k;
|
||||||
|
uint64_t sum1 = init & 0xFFFFFFFFU;
|
||||||
|
uint64_t sum2 = (init >> 32);
|
||||||
|
for (k = 0; k < cnt; k++)
|
||||||
|
{
|
||||||
|
sum1 = (sum1 + le32(data[k]));
|
||||||
|
sum2 = (sum2 + sum1);
|
||||||
|
}
|
||||||
|
sum1 = sum1 % 0xFFFFFFFF;
|
||||||
|
sum2 = sum2 % 0xFFFFFFFF;
|
||||||
|
return (sum2 << 32) | sum1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t VerifyBlock(const void *block, const size_t size)
|
||||||
|
{
|
||||||
|
uint64_t cs;
|
||||||
|
const uint32_t *data = (const uint32_t *)block;
|
||||||
|
const size_t size4 = size / sizeof(uint32_t);
|
||||||
|
|
||||||
|
cs = fletcher64(data + 2, size4 - 2, 0);
|
||||||
|
cs = fletcher64(data, 2, cs);
|
||||||
|
return cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test_APFS(const nx_superblock_t *sb, const partition_t *partition)
|
||||||
|
{
|
||||||
|
if(le32(sb->nx_magic)!=0x4253584e)
|
||||||
|
return 1;
|
||||||
|
if(le32(sb->nx_xp_desc_blocks) + le32(sb->nx_xp_data_blocks) > le64(sb->nx_block_count))
|
||||||
|
return 2;
|
||||||
|
if(le32(sb->nx_block_size) < NX_MINIMUM_BLOCK_SIZE ||
|
||||||
|
le32(sb->nx_block_size) > NX_MAXIMUM_BLOCK_SIZE)
|
||||||
|
return 3;
|
||||||
|
if(VerifyBlock(sb, 4096) != 0)
|
||||||
|
return 4;
|
||||||
|
return 0;
|
||||||
|
}
|
104
src/apfs_common.h
Normal file
104
src/apfs_common.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#ifndef _APFS_COMMON_H
|
||||||
|
#define _APFS_COMMON_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
#define MAX_CKSUM_SIZE 8
|
||||||
|
#define NX_EPH_INFO_COUNT 4
|
||||||
|
#define NX_EPH_INFO_VERSION_1 1
|
||||||
|
#define NX_EPH_MIN_BLOCK_COUNT 8
|
||||||
|
#define NX_MAGIC 'BSXN'
|
||||||
|
#define NX_MAX_FILE_SYSTEM_EPH_STRUCTS 4
|
||||||
|
#define NX_MAX_FILE_SYSTEMS 100
|
||||||
|
#define NX_MAXIMUM_BLOCK_SIZE 65536
|
||||||
|
#define NX_MINIMUM_BLOCK_SIZE 4096
|
||||||
|
#define NX_TX_MIN_CHECKPOINT_COUNT 4
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NX_CNTR_OBJ_CKSUM_SET
|
||||||
|
= 0,
|
||||||
|
NX_CNTR_OBJ_CKSUM_FAIL = 1,
|
||||||
|
NX_NUM_COUNTERS = 32
|
||||||
|
} nx_counter_id_t;
|
||||||
|
|
||||||
|
typedef uint64_t oid_t;
|
||||||
|
typedef uint64_t xid_t;
|
||||||
|
|
||||||
|
struct obj_phys {
|
||||||
|
uint8_t o_cksum[MAX_CKSUM_SIZE];
|
||||||
|
oid_t o_oid;
|
||||||
|
xid_t o_xid;
|
||||||
|
uint32_t o_type;
|
||||||
|
uint32_t o_subtype;
|
||||||
|
} __attribute__((gcc_struct, __packed__));
|
||||||
|
|
||||||
|
typedef struct obj_phys obj_phys_t;
|
||||||
|
typedef int64_t paddr_t;
|
||||||
|
|
||||||
|
struct prange {
|
||||||
|
paddr_t pr_start_paddr;
|
||||||
|
uint64_t pr_block_count;
|
||||||
|
} __attribute__((gcc_struct, __packed__));
|
||||||
|
typedef struct prange prange_t;
|
||||||
|
|
||||||
|
typedef unsigned char apfs_uuid_t[16];
|
||||||
|
|
||||||
|
struct nx_superblock {
|
||||||
|
obj_phys_t nx_o;
|
||||||
|
uint32_t nx_magic;
|
||||||
|
uint32_t nx_block_size;
|
||||||
|
uint64_t nx_block_count;
|
||||||
|
uint64_t nx_features;
|
||||||
|
uint64_t nx_readonly_compatible_features;
|
||||||
|
uint64_t nx_incompatible_features;
|
||||||
|
apfs_uuid_t nx_uuid;
|
||||||
|
oid_t nx_next_oid;
|
||||||
|
xid_t nx_next_xid;
|
||||||
|
uint32_t nx_xp_desc_blocks;
|
||||||
|
uint32_t nx_xp_data_blocks;
|
||||||
|
paddr_t nx_xp_desc_base;
|
||||||
|
paddr_t nx_xp_data_base;
|
||||||
|
uint32_t nx_xp_desc_next;
|
||||||
|
uint32_t nx_xp_data_next;
|
||||||
|
uint32_t nx_xp_desc_index;
|
||||||
|
uint32_t nx_xp_desc_len;
|
||||||
|
uint32_t nx_xp_data_index;
|
||||||
|
uint32_t nx_xp_data_len;
|
||||||
|
oid_t nx_spaceman_oid;
|
||||||
|
oid_t nx_omap_oid;
|
||||||
|
oid_t nx_reaper_oid;
|
||||||
|
uint32_t nx_test_type;
|
||||||
|
uint32_t nx_max_file_systems;
|
||||||
|
oid_t nx_fs_oid[NX_MAX_FILE_SYSTEMS];
|
||||||
|
uint64_t nx_counters[NX_NUM_COUNTERS];
|
||||||
|
prange_t nx_blocked_out_prange;
|
||||||
|
oid_t nx_evict_mapping_tree_oid;
|
||||||
|
uint64_t nx_flags;
|
||||||
|
paddr_t nx_efi_jumpstart;
|
||||||
|
apfs_uuid_t nx_fusion_uuid;
|
||||||
|
prange_t nx_keylocker;
|
||||||
|
uint64_t nx_ephemeral_info[NX_EPH_INFO_COUNT];
|
||||||
|
oid_t nx_test_oid;
|
||||||
|
oid_t nx_fusion_mt_oid;
|
||||||
|
oid_t nx_fusion_wbc_oid;
|
||||||
|
prange_t nx_fusion_wbc;
|
||||||
|
uint64_t nx_newest_mounted_version;
|
||||||
|
prange_t nx_mkb_locker;
|
||||||
|
};
|
||||||
|
typedef struct nx_superblock nx_superblock_t;
|
||||||
|
|
||||||
|
//#define APFS_SUPERBLOCK_SIZE (sizeof(nx_superblock_t))
|
||||||
|
#define APFS_SUPERBLOCK_SIZE 4096
|
||||||
|
/*@
|
||||||
|
@ requires \valid_read(sb);
|
||||||
|
@ requires partition==\null || (\valid_read(partition) && valid_partition(partition));
|
||||||
|
@ requires \separated(sb, partition);
|
||||||
|
@ assigns \nothing;
|
||||||
|
@ */
|
||||||
|
int test_APFS(const nx_superblock_t *sb, const partition_t *partition);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* closing brace for extern "C" */
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -245,6 +245,7 @@ struct efi_guid_s
|
||||||
|
|
||||||
enum upart_type {
|
enum upart_type {
|
||||||
UP_UNK=0,
|
UP_UNK=0,
|
||||||
|
UP_APFS,
|
||||||
UP_BEOS,
|
UP_BEOS,
|
||||||
UP_BTRFS,
|
UP_BTRFS,
|
||||||
UP_CRAMFS,
|
UP_CRAMFS,
|
||||||
|
@ -458,8 +459,9 @@ struct param_disk_struct
|
||||||
disk->sector_size > 0
|
disk->sector_size > 0
|
||||||
));
|
));
|
||||||
*/
|
*/
|
||||||
|
/*@ predicate valid_list_disk(list_disk_t* root) = ((root == \null) || (\valid_read(root))); */
|
||||||
|
|
||||||
/*@ predicate valid_list_disk{L}(list_disk_t* root) =
|
/* TODO predicate valid_list_disk{L}(list_disk_t* root) =
|
||||||
\forall list_disk_t *node; \valid(node) && ld_reachable(root,node) ==> \valid(node->disk);
|
\forall list_disk_t *node; \valid(node) && ld_reachable(root,node) ==> \valid(node->disk);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if !defined(SINGLE_PARTITION_TYPE) || defined(SINGLE_PARTITION_GPT)
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -56,6 +56,7 @@
|
||||||
#include "chgtype.h"
|
#include "chgtype.h"
|
||||||
#include "partgpt.h"
|
#include "partgpt.h"
|
||||||
#include "savehdr.h"
|
#include "savehdr.h"
|
||||||
|
#include "apfs.h"
|
||||||
#include "bfs.h"
|
#include "bfs.h"
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
|
@ -80,6 +81,7 @@ static int check_part_gpt(disk_t *disk, const int verbose, partition_t *partitio
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
@ requires \valid(disk_car);
|
@ requires \valid(disk_car);
|
||||||
|
@ ensures valid_list_part(\result);
|
||||||
@*/
|
@*/
|
||||||
static list_part_t *read_part_gpt(disk_t *disk_car, const int verbose, const int saveheader);
|
static list_part_t *read_part_gpt(disk_t *disk_car, const int verbose, const int saveheader);
|
||||||
|
|
||||||
|
@ -100,7 +102,6 @@ static void set_next_status_gpt(const disk_t *disk_car, partition_t *partition);
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
@ requires list_part == \null || \valid_read(list_part);
|
@ requires list_part == \null || \valid_read(list_part);
|
||||||
@ assigns \nothing;
|
|
||||||
@*/
|
@*/
|
||||||
static int test_structure_gpt(const list_part_t *list_part);
|
static int test_structure_gpt(const list_part_t *list_part);
|
||||||
|
|
||||||
|
@ -201,6 +202,11 @@ arch_fnct_t arch_gpt=
|
||||||
.is_part_known=&is_part_known_gpt
|
.is_part_known=&is_part_known_gpt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*@
|
||||||
|
@ requires \valid(disk_car);
|
||||||
|
@ requires valid_disk(disk_car);
|
||||||
|
@*/
|
||||||
|
// ensures valid_list_part(\result);
|
||||||
static list_part_t *read_part_gpt_aux(disk_t *disk_car, const int verbose, const int saveheader, const uint64_t hdr_lba)
|
static list_part_t *read_part_gpt_aux(disk_t *disk_car, const int verbose, const int saveheader, const uint64_t hdr_lba)
|
||||||
{
|
{
|
||||||
struct gpt_hdr *gpt;
|
struct gpt_hdr *gpt;
|
||||||
|
@ -398,7 +404,10 @@ list_part_t *add_partition_gpt_cli(const disk_t *disk_car, list_part_t *list_par
|
||||||
new_partition=partition_new(&arch_gpt);
|
new_partition=partition_new(&arch_gpt);
|
||||||
new_partition->part_offset=disk_car->sector_size;
|
new_partition->part_offset=disk_car->sector_size;
|
||||||
new_partition->part_size=disk_car->disk_size-new_partition->part_offset;
|
new_partition->part_size=disk_car->disk_size-new_partition->part_offset;
|
||||||
/*@ loop invariant valid_read_string(*current_cmd); */
|
/*@
|
||||||
|
@ loop invariant valid_list_part(list_part);
|
||||||
|
@ loop invariant valid_read_string(*current_cmd);
|
||||||
|
@ */
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
skip_comma_in_command(current_cmd);
|
skip_comma_in_command(current_cmd);
|
||||||
|
@ -434,19 +443,23 @@ list_part_t *add_partition_gpt_cli(const disk_t *disk_car, list_part_t *list_par
|
||||||
{
|
{
|
||||||
int insert_error=0;
|
int insert_error=0;
|
||||||
list_part_t *new_list_part=insert_new_partition(list_part, new_partition, 0, &insert_error);
|
list_part_t *new_list_part=insert_new_partition(list_part, new_partition, 0, &insert_error);
|
||||||
|
/*@ assert valid_list_part(new_list_part); */
|
||||||
if(insert_error>0)
|
if(insert_error>0)
|
||||||
{
|
{
|
||||||
free(new_partition);
|
free(new_partition);
|
||||||
|
/*@ assert valid_list_part(new_list_part); */
|
||||||
return new_list_part;
|
return new_list_part;
|
||||||
}
|
}
|
||||||
new_partition->status=STATUS_PRIM;
|
new_partition->status=STATUS_PRIM;
|
||||||
if(test_structure_gpt(list_part)!=0)
|
if(test_structure_gpt(list_part)!=0)
|
||||||
new_partition->status=STATUS_DELETED;
|
new_partition->status=STATUS_DELETED;
|
||||||
|
/*@ assert valid_list_part(new_list_part); */
|
||||||
return new_list_part;
|
return new_list_part;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
free(new_partition);
|
free(new_partition);
|
||||||
|
/*@ assert valid_list_part(list_part); */
|
||||||
return list_part;
|
return list_part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,6 +562,12 @@ static int check_part_gpt(disk_t *disk, const int verbose,partition_t *partition
|
||||||
if(ret!=0)
|
if(ret!=0)
|
||||||
screen_buffer_add("No HFS or HFS+ structure\n");
|
screen_buffer_add("No HFS or HFS+ structure\n");
|
||||||
}
|
}
|
||||||
|
else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_MAC_APFS)==0)
|
||||||
|
{
|
||||||
|
ret=check_APFS(disk, partition);
|
||||||
|
if(ret!=0)
|
||||||
|
screen_buffer_add("No valid APFS structure\n");
|
||||||
|
}
|
||||||
else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_BEOS_BFS)==0)
|
else if(guid_cmp(partition->part_type_gpt, GPT_ENT_TYPE_BEOS_BFS)==0)
|
||||||
{
|
{
|
||||||
ret=check_BeFS(disk, partition);
|
ret=check_BeFS(disk, partition);
|
||||||
|
@ -576,6 +595,7 @@ static const char *get_gpt_typename(const efi_guid_t part_type_gpt)
|
||||||
for(i=0; gpt_sys_types[i].name!=NULL; i++)
|
for(i=0; gpt_sys_types[i].name!=NULL; i++)
|
||||||
if(guid_cmp(gpt_sys_types[i].part_type, part_type_gpt)==0)
|
if(guid_cmp(gpt_sys_types[i].part_type, part_type_gpt)==0)
|
||||||
return gpt_sys_types[i].name;
|
return gpt_sys_types[i].name;
|
||||||
|
#ifndef __FRAMAC__
|
||||||
log_info("%8x %04x %04x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
log_info("%8x %04x %04x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||||
part_type_gpt.time_low,
|
part_type_gpt.time_low,
|
||||||
part_type_gpt.time_mid,
|
part_type_gpt.time_mid,
|
||||||
|
@ -588,6 +608,7 @@ static const char *get_gpt_typename(const efi_guid_t part_type_gpt)
|
||||||
part_type_gpt.node[3],
|
part_type_gpt.node[3],
|
||||||
part_type_gpt.node[4],
|
part_type_gpt.node[4],
|
||||||
part_type_gpt.node[5]);
|
part_type_gpt.node[5]);
|
||||||
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,3 +616,4 @@ static const char *get_partition_typename_gpt(const partition_t *partition)
|
||||||
{
|
{
|
||||||
return get_gpt_typename(partition->part_type_gpt);
|
return get_gpt_typename(partition->part_type_gpt);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#include "analyse.h"
|
#include "analyse.h"
|
||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
#include "intrf.h"
|
#include "intrf.h"
|
||||||
|
#include "fat_common.h"
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
|
#include "apfs.h"
|
||||||
#include "bfs.h"
|
#include "bfs.h"
|
||||||
#include "bsd.h"
|
#include "bsd.h"
|
||||||
#include "btrfs.h"
|
#include "btrfs.h"
|
||||||
|
@ -46,7 +49,6 @@
|
||||||
#include "exfat.h"
|
#include "exfat.h"
|
||||||
#include "ext2.h"
|
#include "ext2.h"
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
#include "fat_common.h"
|
|
||||||
#include "fatx.h"
|
#include "fatx.h"
|
||||||
#include "f2fs_fs.h"
|
#include "f2fs_fs.h"
|
||||||
#include "f2fs.h"
|
#include "f2fs.h"
|
||||||
|
@ -73,6 +75,7 @@
|
||||||
#include "vmfs.h"
|
#include "vmfs.h"
|
||||||
#include "wbfs.h"
|
#include "wbfs.h"
|
||||||
#include "zfs.h"
|
#include "zfs.h"
|
||||||
|
#endif
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
|
@ -91,6 +94,8 @@ static int get_geometry_from_nonembr(const unsigned char *buffer, const int verb
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
@ requires \valid(disk_car);
|
@ requires \valid(disk_car);
|
||||||
|
@ requires valid_disk(disk_car);
|
||||||
|
@ ensures valid_list_part(\result);
|
||||||
@*/
|
@*/
|
||||||
static list_part_t *read_part_none(disk_t *disk_car, const int verbose, const int saveheader);
|
static list_part_t *read_part_none(disk_t *disk_car, const int verbose, const int saveheader);
|
||||||
|
|
||||||
|
@ -143,6 +148,7 @@ static unsigned int get_part_type_none(const partition_t *partition);
|
||||||
static const char *get_partition_typename_none(const partition_t *partition);
|
static const char *get_partition_typename_none(const partition_t *partition);
|
||||||
|
|
||||||
static const struct systypes none_sys_types[] = {
|
static const struct systypes none_sys_types[] = {
|
||||||
|
{UP_APFS, "APFS"},
|
||||||
{UP_BEOS, "BeFS"},
|
{UP_BEOS, "BeFS"},
|
||||||
{UP_BTRFS, "btrfs"},
|
{UP_BTRFS, "btrfs"},
|
||||||
{UP_CRAMFS, "CramFS"},
|
{UP_CRAMFS, "CramFS"},
|
||||||
|
@ -257,6 +263,7 @@ static list_part_t *read_part_none(disk_t *disk, const int verbose, const int sa
|
||||||
partition=partition_new(&arch_none);
|
partition=partition_new(&arch_none);
|
||||||
buffer_disk=(unsigned char *)MALLOC(16*DEFAULT_SECTOR_SIZE);
|
buffer_disk=(unsigned char *)MALLOC(16*DEFAULT_SECTOR_SIZE);
|
||||||
partition->part_size=disk->disk_size;
|
partition->part_size=disk->disk_size;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
if(recover_MD_from_partition(disk, partition, verbose)==0)
|
if(recover_MD_from_partition(disk, partition, verbose)==0)
|
||||||
res=1;
|
res=1;
|
||||||
else
|
else
|
||||||
|
@ -341,6 +348,7 @@ static list_part_t *read_part_none(disk_t *disk, const int verbose, const int sa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
free(buffer_disk);
|
free(buffer_disk);
|
||||||
if(res<=0)
|
if(res<=0)
|
||||||
partition_reset(partition,&arch_none);
|
partition_reset(partition,&arch_none);
|
||||||
|
@ -350,7 +358,9 @@ static list_part_t *read_part_none(disk_t *disk, const int verbose, const int sa
|
||||||
partition->status=STATUS_PRIM;
|
partition->status=STATUS_PRIM;
|
||||||
screen_buffer_reset();
|
screen_buffer_reset();
|
||||||
check_part_none(disk, verbose,partition,saveheader);
|
check_part_none(disk, verbose,partition,saveheader);
|
||||||
|
#ifndef __FRAMAC__
|
||||||
aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk, partition);
|
aff_part_buffer(AFF_PART_ORDER|AFF_PART_STATUS,disk, partition);
|
||||||
|
#endif
|
||||||
list_part=insert_new_partition(NULL, partition, 0, &insert_error);
|
list_part=insert_new_partition(NULL, partition, 0, &insert_error);
|
||||||
if(insert_error>0)
|
if(insert_error>0)
|
||||||
free(partition);
|
free(partition);
|
||||||
|
@ -395,8 +405,12 @@ static void init_structure_none(const disk_t *disk_car,list_part_t *list_part, c
|
||||||
static int check_part_none(disk_t *disk_car,const int verbose,partition_t *partition, const int saveheader)
|
static int check_part_none(disk_t *disk_car,const int verbose,partition_t *partition, const int saveheader)
|
||||||
{
|
{
|
||||||
int ret=0;
|
int ret=0;
|
||||||
|
#if !defined(__FRAMAC__) && !defined(MAIN_photorec)
|
||||||
switch(partition->upart_type)
|
switch(partition->upart_type)
|
||||||
{
|
{
|
||||||
|
case UP_APFS:
|
||||||
|
ret=check_APFS(disk_car, partition);
|
||||||
|
break;
|
||||||
case UP_BEOS:
|
case UP_BEOS:
|
||||||
ret=check_BeFS(disk_car,partition);
|
ret=check_BeFS(disk_car,partition);
|
||||||
break;
|
break;
|
||||||
|
@ -525,6 +539,7 @@ static int check_part_none(disk_t *disk_car,const int verbose,partition_t *parti
|
||||||
case UP_UNK:
|
case UP_UNK:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue