summaryrefslogtreecommitdiffstats
path: root/src/file_mxf.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2016-06-22 12:10:24 +0200
committerChristophe Grenier <grenier@cgsecurity.org>2016-06-22 12:10:24 +0200
commit6e45e14d17a463b9c27d4cf922957cbd4d37e196 (patch)
treed5aba4d9046503d5ea9f2bff0f018f40ba448d52 /src/file_mxf.c
parent9de993e4d3691f8c24c09c2118f207eb6ca62dbb (diff)
PhotoRec: fix recovered .mxf filesize
Diffstat (limited to 'src/file_mxf.c')
-rw-r--r--src/file_mxf.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/file_mxf.c b/src/file_mxf.c
index 066b36c..8d2a588 100644
--- a/src/file_mxf.c
+++ b/src/file_mxf.c
@@ -28,6 +28,8 @@
#include <stdio.h>
#include "types.h"
#include "filegen.h"
+#include "common.h"
+#include "log.h"
static void register_header_check_mxf(file_stat_t *file_stat);
@@ -46,10 +48,98 @@ const file_hint_t file_hint_mxf= {
* Material Exchange Format (MXF)
* */
+struct partition_pack_next
+{
+ uint16_t major_version;
+ uint16_t minor_version;
+ uint32_t kagsize;
+ uint64_t this_partition;
+ uint64_t previous_partition;
+ uint64_t footer_partition;
+ uint64_t header_byte_count;
+ uint64_t index_byte_count;
+ uint32_t index_SID;
+ uint64_t body_offset;
+ uint32_t body_SID;
+ char op_pattern[16];
+ char essence_container[0];
+} __attribute__ ((gcc_struct, __packed__));
+
+static data_check_t data_check_mxf(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
+{
+ static const unsigned char mxf_header[4]= { 0x06, 0x0e, 0x2b, 0x34 };
+ while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
+ file_recovery->calculated_file_size + 15 < file_recovery->file_size + buffer_size/2)
+ {
+ const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
+ if(memcmp(&buffer[i], mxf_header, sizeof(mxf_header))!=0)
+ return DC_STOP;
+#ifdef DEBUG_MXF
+ log_info("data_check_mxf: header found 0x%02x\n", buffer[i+0x10]);
+ log_info("fs=0x%llx\n", file_recovery->calculated_file_size);
+#endif
+ switch(buffer[i+0x10])
+ {
+ case 0x81:
+ file_recovery->calculated_file_size+=0x14+buffer[i+0x11];
+ break;
+ case 0x82:
+ file_recovery->calculated_file_size+=0x14+(buffer[i+0x11]<<8)+buffer[i+0x12];
+ case 0x83:
+ file_recovery->calculated_file_size+=0x14+(buffer[i+0x11]<<16)+(buffer[i+0x12]<<8)+buffer[i+0x13];
+ break;
+ case 0x84:
+ file_recovery->calculated_file_size+=0x14+(buffer[i+0x11]<<24)+(buffer[i+0x12]<<16)+(buffer[i+0x13]<<8)+buffer[i+0x14];
+ break;
+ default:
+ file_recovery->calculated_file_size+=0x14+buffer[i+0x10];
+ break;
+ }
+ }
+ return DC_CONTINUE;
+}
+
static int header_check_mxf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
+ if(buffer[0x0d]!=0x02 || buffer[0x0e]!=0x04)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_mxf.extension;
+ switch(buffer[0x10])
+ {
+ case 0x81:
+ {
+ const struct partition_pack_next *hdr=(const struct partition_pack_next *)&buffer[0x12];
+ file_recovery_new->calculated_file_size=be64(hdr->footer_partition);
+ }
+ break;
+ case 0x82:
+ {
+ const struct partition_pack_next *hdr=(const struct partition_pack_next *)&buffer[0x13];
+ file_recovery_new->calculated_file_size=be64(hdr->footer_partition);
+ }
+ break;
+ case 0x83:
+ {
+ const struct partition_pack_next *hdr=(const struct partition_pack_next *)&buffer[0x14];
+ file_recovery_new->calculated_file_size=be64(hdr->footer_partition);
+ }
+ break;
+ case 0x84:
+ {
+ const struct partition_pack_next *hdr=(const struct partition_pack_next *)&buffer[0x15];
+ file_recovery_new->calculated_file_size=be64(hdr->footer_partition);
+ }
+ break;
+ default:
+ {
+ const struct partition_pack_next *hdr=(const struct partition_pack_next *)&buffer[0x11];
+ file_recovery_new->calculated_file_size=be64(hdr->footer_partition);
+ }
+ break;
+ }
+ file_recovery_new->data_check=&data_check_mxf;
+ file_recovery_new->file_check=&file_check_size;
return 1;
}