summaryrefslogtreecommitdiffstats
path: root/src/filegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/filegen.c')
-rw-r--r--src/filegen.c182
1 files changed, 160 insertions, 22 deletions
diff --git a/src/filegen.c b/src/filegen.c
index f48f21d..c197b5e 100644
--- a/src/filegen.c
+++ b/src/filegen.c
@@ -38,7 +38,6 @@
#include "types.h"
#include "common.h"
#include "filegen.h"
-#include "photorec.h"
#include "log.h"
static file_check_t file_check_plist={
@@ -66,7 +65,7 @@ static int file_check_cmp(const struct td_list_head *a, const struct td_list_hea
res=memcmp(fc_a->value,fc_b->value, (fc_a->length<=fc_b->length?fc_a->length:fc_b->length));
if(res!=0)
return res;
- return fc_b->length-fc_a->length;
+ return (int)fc_b->length-(int)fc_a->length;
}
static void file_check_add_tail(file_check_t *file_check_new, file_check_list_t *pos)
@@ -98,12 +97,12 @@ void register_header_check(const unsigned int offset, const void *value, const u
static void index_header_check_aux(file_check_t *file_check_new)
{
- struct td_list_head *tmp;
- td_list_for_each(tmp, &file_check_list.list)
+ if(file_check_new->length>0)
{
- file_check_list_t *pos=td_list_entry(tmp, file_check_list_t, list);
- if(file_check_new->length>0)
+ struct td_list_head *tmp;
+ td_list_for_each(tmp, &file_check_list.list)
{
+ file_check_list_t *pos=td_list_entry(tmp, file_check_list_t, list);
if(pos->offset >= file_check_new->offset &&
pos->offset < file_check_new->offset+file_check_new->length)
{
@@ -237,7 +236,12 @@ void file_search_footer(file_recovery_t *file_recovery, const void*footer, const
}
#if 0
-void file_search_lc_footer(file_recovery_t *file_recovery, const unsigned char*footer, const unsigned int footer_length)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires footer_length > 0;
+ @ requires \valid_read((char *)footer+(0..footer_length-1));
+ @*/
+static void file_search_lc_footer(file_recovery_t *file_recovery, const unsigned char*footer, const unsigned int footer_length)
{
const unsigned int read_size=4096;
unsigned char*buffer;
@@ -317,7 +321,6 @@ void reset_file_recovery(file_recovery_t *file_recovery)
file_recovery->file_size=0;
file_recovery->location.list.prev=&file_recovery->location.list;
file_recovery->location.list.next=&file_recovery->location.list;
- file_recovery->location.start=0;
file_recovery->location.end=0;
file_recovery->location.data=0;
file_recovery->extension=NULL;
@@ -330,7 +333,6 @@ void reset_file_recovery(file_recovery_t *file_recovery)
file_recovery->offset_ok=0;
file_recovery->checkpoint_status=0;
file_recovery->checkpoint_offset=0;
-// file_recovery->blocksize=512;
file_recovery->flags=0;
file_recovery->extra=0;
}
@@ -368,9 +370,77 @@ file_stat_t * init_file_stats(file_enable_t *files_enable)
return file_stats;
}
+/*@
+ @ requires \valid(file_recovery);
+ @ requires valid_read_string((const char*)&file_recovery->filename);
+ @ requires new_ext==\null || valid_read_string(new_ext);
+ @*/
+static int file_rename_aux(file_recovery_t *file_recovery, const char *new_ext, const int append_original_ext)
+{
+ /* new_filename is large enough to avoid a buffer overflow */
+ char *new_filename;
+ const char *src=file_recovery->filename;
+ const char *ext=NULL;
+ char *dst;
+ char *directory_sep;
+ int len;
+ len=strlen(src)+1;
+ if(new_ext!=NULL)
+ len+=strlen(new_ext);
+ new_filename=(char*)MALLOC(len);
+ dst=new_filename;
+ directory_sep=new_filename;
+ while(*src!='\0')
+ {
+ if(*src=='/')
+ {
+ directory_sep=dst;
+ ext=NULL;
+ }
+ if(*src=='.')
+ ext=src;
+ *dst++ = *src++;
+ }
+ *dst='\0';
+ dst=directory_sep;
+ while(*dst!='.' && *dst!='\0')
+ dst++;
+ /* Add extension */
+ if(new_ext!=NULL)
+ {
+ src=new_ext;
+ *dst++ = '.';
+ while(*src!='\0')
+ *dst++ = *src++;
+ }
+ else if(append_original_ext>0)
+ {
+ if(ext!=NULL)
+ {
+ while(*ext!='\0')
+ *dst++ = *ext++;
+ }
+ }
+ *dst='\0';
+ if(rename(file_recovery->filename, new_filename)<0)
+ {
+ /* Rename has failed */
+ free(new_filename);
+ return -1;
+ }
+ if(strlen(new_filename)<sizeof(file_recovery->filename))
+ {
+ strcpy(file_recovery->filename, new_filename);
+ }
+ free(new_filename);
+ return 0;
+}
+
/* The original filename begins at offset in buffer and is null terminated */
int file_rename(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext)
{
+ /* TODO: make the code from frama-c friendly */
+#ifndef __FRAMAC__
/* new_filename is large enough to avoid a buffer overflow */
char *new_filename;
const char *src=file_recovery->filename;
@@ -475,19 +545,75 @@ int file_rename(file_recovery_t *file_recovery, const void *buffer, const int bu
if(buffer==NULL)
return -1;
/* Try without the original filename */
- return file_rename(file_recovery, NULL, 0, 0, new_ext, append_original_ext);
+ return file_rename_aux(file_recovery, new_ext, append_original_ext);
}
if(strlen(new_filename)<sizeof(file_recovery->filename))
{
strcpy(file_recovery->filename, new_filename);
}
free(new_filename);
+#endif
+ return 0;
+}
+
+/*@
+ @ requires \valid(file_recovery);
+ @ requires valid_read_string((const char*)&file_recovery->filename);
+ @ requires new_ext==\null || valid_read_string(new_ext);
+ @*/
+static int file_rename_unicode_aux(file_recovery_t *file_recovery, const char *new_ext, const int append_original_ext)
+{
+ char *new_filename;
+ const char *src=file_recovery->filename;
+ const char *ext=src;
+ char *dst;
+ char *directory_sep;
+ unsigned int len=strlen(file_recovery->filename)+1;
+ /*@ assert len < sizeof(file_recovery->filename); */
+ if(new_ext!=NULL)
+ len+=strlen(new_ext);
+ if(len > sizeof(file_recovery->filename))
+ return -1;
+ new_filename=(char*)MALLOC(len);
+ strcpy(new_filename, (char *)&file_recovery->filename);
+ directory_sep=strrchr(file_recovery->filename, '/');
+ ext=strrchr(file_recovery->filename, '.');
+ /*@ assert directory_sep != \null; */
+#if 1
+ dst=directory_sep;
+ while(*dst!='.' && *dst!='\0')
+ dst++;
+ /* Add extension */
+ if(new_ext!=NULL)
+ {
+ src=new_ext;
+ *dst++ = '.';
+ while(*src!='\0')
+ *dst++ = *src++;
+ }
+ else if(append_original_ext>0)
+ {
+ while(*ext!='\0')
+ *dst++ = *ext++;
+ }
+ *dst='\0';
+#endif
+ if(rename(file_recovery->filename, new_filename)<0)
+ {
+ /* Rename has failed */
+ free(new_filename);
+ return -1;
+ }
+ strcpy(file_recovery->filename, new_filename);
+ free(new_filename);
return 0;
}
/* The original filename begins at offset in buffer and is null terminated */
int file_rename_unicode(file_recovery_t *file_recovery, const void *buffer, const int buffer_size, const int offset, const char *new_ext, const int append_original_ext)
{
+ /* TODO: make the code from frama-c friendly */
+#ifndef __FRAMAC__
/* new_filename is large enough to avoid a buffer overflow */
char *new_filename;
const char *src=file_recovery->filename;
@@ -585,18 +711,25 @@ int file_rename_unicode(file_recovery_t *file_recovery, const void *buffer, cons
if(buffer==NULL)
return -1;
/* Try without the original filename */
- return file_rename_unicode(file_recovery, NULL, 0, 0, new_ext, append_original_ext);
+ return file_rename_unicode_aux(file_recovery, new_ext, append_original_ext);
}
if(strlen(new_filename)<sizeof(file_recovery->filename))
{
strcpy(file_recovery->filename, new_filename);
}
free(new_filename);
+#endif
return 0;
}
static uint64_t offset_skipped_header=0;
+void header_ignored_cond_reset(uint64_t start, uint64_t end)
+{
+ if(start <= offset_skipped_header && offset_skipped_header <= end)
+ offset_skipped_header=0;
+}
+
/* 0: file_recovery is bad *
* 1: file_recovery is ok */
int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery_t *file_recovery_new)
@@ -612,13 +745,15 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery
}
if(file_recovery->handle==NULL)
{
- if(file_recovery_new->location.start==0 || offset_skipped_header==0)
+ if(file_recovery_new->location.start < offset_skipped_header || offset_skipped_header==0)
+ {
offset_skipped_header=file_recovery_new->location.start;
+ }
return 0;
}
memcpy(&fr_test, file_recovery, sizeof(fr_test));
-#ifdef HAVE_FTELLO
+#if defined(HAVE_FTELLO) && !defined(__FRAMAC__)
if((offset=ftello(file_recovery->handle)) < 0)
offset=ftell(file_recovery->handle);
#else
@@ -626,15 +761,17 @@ int header_ignored_adv(const file_recovery_t *file_recovery, const file_recovery
#endif
assert(offset >= 0);
file_recovery->file_check(&fr_test);
- if(fr_test.file_size>0)
- return 1;
if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0)
{
log_error("BUG in header_ignored_adv: my_fseek() failed\n");
return 1;
}
- if(file_recovery_new->location.start==0 || offset_skipped_header==0)
+ if(fr_test.file_size>0)
+ return 1;
+ if(file_recovery_new->location.start < offset_skipped_header || offset_skipped_header==0)
+ {
offset_skipped_header=file_recovery_new->location.start;
+ }
return 0;
}
@@ -645,7 +782,7 @@ void header_ignored(const file_recovery_t *file_recovery_new)
offset_skipped_header=0;
return ;
}
- if(file_recovery_new->location.start==0 || offset_skipped_header==0)
+ if(file_recovery_new->location.start < offset_skipped_header || offset_skipped_header==0)
offset_skipped_header=file_recovery_new->location.start;
}
@@ -669,7 +806,7 @@ void get_prev_location_smart(alloc_data_t *list_search_space, alloc_data_t **cur
if(file_space->start < prev_location)
break;
}
-#ifdef DEBUG_HEADER_CHECK
+#ifdef DEBUG_PREV_LOCATION
log_info("get_prev_location_smart: reset offset_skipped_header=%llu, offset=%llu\n",
(long long unsigned)(offset_skipped_header/512),
(long long unsigned)(*offset/512));
@@ -682,24 +819,25 @@ void get_prev_location_smart(alloc_data_t *list_search_space, alloc_data_t **cur
offset_skipped_header=0;
return;
}
+ *current_search_space=file_space;
if(file_space->start < prev_location || file_space->start < offset_skipped_header)
{
-#ifdef DEBUG_HEADER_CHECK
+#ifdef DEBUG_PREV_LOCATION
log_info("get_prev_location_smart: file_space->start < prev_location=%llu (in 512-bytes sectors), offset=%llu\n",
(long long unsigned)(prev_location/512),
(long long unsigned)(*offset/512));
#endif
+ *offset=offset_skipped_header;
offset_skipped_header=0;
return ;
}
- *current_search_space=file_space;
*offset=file_space->start;
}
}
int my_fseek(FILE *stream, off_t offset, int whence)
{
-#if defined(HAVE_FSEEKO) && !defined(__MINGW32__) && !defined(__ARM_EABI__)
+#if defined(HAVE_FSEEKO) && !defined(__MINGW32__) && !defined(__ARM_EABI__) && !defined(__FRAMAC__)
{
int res;
if((res=fseeko(stream, offset, whence))>=0)
@@ -725,7 +863,7 @@ time_t get_time_from_YYMMDDHHMMSS(const char *date_asc)
return mktime(&tm_time);
}
-time_t get_time_from_YYYY_MM_DD_HH_MM_SS(const char *date_asc)
+time_t get_time_from_YYYY_MM_DD_HH_MM_SS(const unsigned char *date_asc)
{
struct tm tm_time;
if(memcmp(date_asc, "0000", 4)==0)