PhotoRec: fix .fits filesize detection
This commit is contained in:
parent
05698fa19d
commit
a342b0ccb7
1 changed files with 113 additions and 72 deletions
185
src/file_fits.c
185
src/file_fits.c
|
@ -32,6 +32,9 @@
|
|||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
#include "filegen.h"
|
||||
#ifdef DEBUG_FITS
|
||||
#include "log.h"
|
||||
#endif
|
||||
|
||||
static void register_header_check_fits(file_stat_t *file_stat);
|
||||
static int header_check_fits(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);
|
||||
|
@ -50,13 +53,6 @@ const file_hint_t file_hint_fits= {
|
|||
* Image metadata is store in an ASCII header
|
||||
* Specification can be found at http://fits.gsfc.nasa.gov/ */
|
||||
|
||||
static const unsigned char fits_header[9]= { 'S','I','M','P','L','E',' ',' ','='};
|
||||
|
||||
static void register_header_check_fits(file_stat_t *file_stat)
|
||||
{
|
||||
register_header_check(0, fits_header,sizeof(fits_header), &header_check_fits, file_stat);
|
||||
}
|
||||
|
||||
static uint64_t fits_get_val(const unsigned char *str)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -64,81 +60,126 @@ static uint64_t fits_get_val(const unsigned char *str)
|
|||
for(i=0;i<80 && str[i]!='=';i++);
|
||||
i++;
|
||||
for(;i<80 && str[i]==' ';i++);
|
||||
if(i<80 && str[i]=='-')
|
||||
i++;
|
||||
for(;i<80 && str[i]>='0' && str[i]<='9';i++)
|
||||
val=val*10+str[i]-'0';
|
||||
return val;
|
||||
}
|
||||
|
||||
static int header_check_fits(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)
|
||||
static uint64_t fits_info(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery, unsigned int *i_pointer)
|
||||
{
|
||||
if(memcmp(buffer,fits_header,sizeof(fits_header))==0)
|
||||
uint64_t naxis_size=1;
|
||||
unsigned int i=*i_pointer;
|
||||
/* Header is composed of 80 character fixed-length strings */
|
||||
for(; i<buffer_size &&
|
||||
memcmp(&buffer[i], "END ", 4)!=0;
|
||||
i+=80)
|
||||
{
|
||||
unsigned int i=0;
|
||||
uint64_t naxis_size_max=0;
|
||||
reset_file_recovery(file_recovery_new);
|
||||
#ifdef DJGPP
|
||||
file_recovery_new->extension="fts";
|
||||
#else
|
||||
file_recovery_new->extension=file_hint_fits.extension;
|
||||
#endif
|
||||
file_recovery_new->min_filesize=2880;
|
||||
file_recovery_new->data_check=&data_check_size;
|
||||
file_recovery_new->file_check=&file_check_size;
|
||||
do
|
||||
if(memcmp(&buffer[i], "BITPIX",6)==0)
|
||||
{
|
||||
uint64_t naxis_size=1;
|
||||
/* Header is composed of 80 character fixed-length strings */
|
||||
for(; i<buffer_size &&
|
||||
memcmp(&buffer[i], "END ", 4)!=0;
|
||||
i+=80)
|
||||
{
|
||||
if(memcmp(&buffer[i], "NAXIS ",6)==0)
|
||||
{
|
||||
/* naxis value is dicarded */
|
||||
fits_get_val(&buffer[i]);
|
||||
}
|
||||
else if(memcmp(&buffer[i], "NAXIS",5)==0)
|
||||
{
|
||||
const uint64_t naxis_val=fits_get_val(&buffer[i]);
|
||||
if(naxis_val>0)
|
||||
naxis_size*=naxis_val;
|
||||
}
|
||||
else if(memcmp(&buffer[i], "CREA_DAT=", 9)==0)
|
||||
{
|
||||
/* CREA_DAT= '2007-08-29T16:22:09' */
|
||||
/* 0123456789012345678 */
|
||||
const unsigned char *date_asc;
|
||||
unsigned int j;
|
||||
for(j=0,date_asc=&buffer[i];j<80 && *date_asc!='\'';j++,date_asc++);
|
||||
if(j<60 && *date_asc=='\'')
|
||||
{
|
||||
struct tm tm_time;
|
||||
memset(&tm_time, 0, sizeof(tm_time));
|
||||
date_asc++;
|
||||
tm_time.tm_sec=(date_asc[17]-'0')*10+(date_asc[18]-'0'); /* seconds 0-59 */
|
||||
tm_time.tm_min=(date_asc[14]-'0')*10+(date_asc[15]-'0'); /* minutes 0-59 */
|
||||
tm_time.tm_hour=(date_asc[11]-'0')*10+(date_asc[12]-'0'); /* hours 0-23*/
|
||||
tm_time.tm_mday=(date_asc[8]-'0')*10+(date_asc[9]-'0'); /* day of the month 1-31 */
|
||||
tm_time.tm_mon=(date_asc[5]-'0')*10+(date_asc[6]-'0')-1; /* month 0-11 */
|
||||
tm_time.tm_year=(date_asc[0]-'0')*1000+(date_asc[1]-'0')*100+
|
||||
(date_asc[2]-'0')*10+(date_asc[3]-'0')-1900; /* year */
|
||||
tm_time.tm_isdst = -1; /* unknown daylight saving time */
|
||||
file_recovery_new->time=mktime(&tm_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* File is composed of several 2880-bytes blocks */
|
||||
i=(i/2880+1)*2880;
|
||||
if(naxis_size_max < naxis_size && naxis_size > 1)
|
||||
naxis_size_max=naxis_size;
|
||||
const uint64_t tmp=fits_get_val(&buffer[i]);
|
||||
if(tmp>=8)
|
||||
naxis_size*=tmp/8;
|
||||
}
|
||||
else if(memcmp(&buffer[i], "NAXIS ",6)==0)
|
||||
{
|
||||
if(fits_get_val(&buffer[i])==0)
|
||||
naxis_size=0;
|
||||
}
|
||||
else if(memcmp(&buffer[i], "NAXIS",5)==0)
|
||||
{
|
||||
const uint64_t naxis_val=fits_get_val(&buffer[i]);
|
||||
naxis_size*=naxis_val;
|
||||
}
|
||||
else if(memcmp(&buffer[i], "CREA_DAT=", 9)==0)
|
||||
{
|
||||
/* CREA_DAT= '2007-08-29T16:22:09' */
|
||||
/* 0123456789012345678 */
|
||||
const unsigned char *date_asc;
|
||||
unsigned int j;
|
||||
for(j=0,date_asc=&buffer[i];j<80 && *date_asc!='\'';j++,date_asc++);
|
||||
if(j<60 && *date_asc=='\'')
|
||||
{
|
||||
struct tm tm_time;
|
||||
memset(&tm_time, 0, sizeof(tm_time));
|
||||
date_asc++;
|
||||
tm_time.tm_sec=(date_asc[17]-'0')*10+(date_asc[18]-'0'); /* seconds 0-59 */
|
||||
tm_time.tm_min=(date_asc[14]-'0')*10+(date_asc[15]-'0'); /* minutes 0-59 */
|
||||
tm_time.tm_hour=(date_asc[11]-'0')*10+(date_asc[12]-'0'); /* hours 0-23*/
|
||||
tm_time.tm_mday=(date_asc[8]-'0')*10+(date_asc[9]-'0'); /* day of the month 1-31 */
|
||||
tm_time.tm_mon=(date_asc[5]-'0')*10+(date_asc[6]-'0')-1; /* month 0-11 */
|
||||
tm_time.tm_year=(date_asc[0]-'0')*1000+(date_asc[1]-'0')*100+
|
||||
(date_asc[2]-'0')*10+(date_asc[3]-'0')-1900; /* year */
|
||||
tm_time.tm_isdst = -1; /* unknown daylight saving time */
|
||||
file_recovery->time=mktime(&tm_time);
|
||||
}
|
||||
}
|
||||
while(i<buffer_size &&
|
||||
memcmp(&buffer[i], "XTENSION", 8)==0);
|
||||
/* No more extension */
|
||||
file_recovery_new->calculated_file_size=i+(naxis_size_max+2880-1)/2880*2880;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
*i_pointer=i;
|
||||
return naxis_size;
|
||||
}
|
||||
|
||||
static int data_check_fits(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
|
||||
{
|
||||
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
|
||||
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
|
||||
{
|
||||
unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
|
||||
if(memcmp(&buffer[i], "XTENSION", 8)!=0)
|
||||
break;
|
||||
{
|
||||
const unsigned int i_org=i;
|
||||
const uint64_t tmp=fits_info(buffer, buffer_size, file_recovery, &i);
|
||||
#ifdef DEBUG_FITS
|
||||
log_info("data_check_fits cfr=%llu fs=%llu i=%u buffer_size=%u\n",
|
||||
(long long unsigned)file_recovery->calculated_file_size,
|
||||
(long long unsigned)file_recovery->file_size,
|
||||
i, buffer_size);
|
||||
#endif
|
||||
if(tmp==0)
|
||||
{
|
||||
file_recovery->data_check=NULL;
|
||||
file_recovery->file_check=NULL;
|
||||
return 1;
|
||||
}
|
||||
file_recovery->calculated_file_size+=(i-i_org+2880-1)/2880*2880+(tmp+2880-1)/2880*2880;
|
||||
}
|
||||
}
|
||||
if(file_recovery->file_size>=file_recovery->calculated_file_size)
|
||||
{
|
||||
file_recovery->file_size=file_recovery->calculated_file_size;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int header_check_fits(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)
|
||||
{
|
||||
unsigned int i=0;
|
||||
uint64_t naxis_size_max=0;
|
||||
reset_file_recovery(file_recovery_new);
|
||||
#ifdef DJGPP
|
||||
file_recovery_new->extension="fts";
|
||||
#else
|
||||
file_recovery_new->extension=file_hint_fits.extension;
|
||||
#endif
|
||||
file_recovery_new->min_filesize=2880;
|
||||
{
|
||||
uint64_t tmp=fits_info(buffer, buffer_size, file_recovery_new, &i);
|
||||
if(tmp==0)
|
||||
return 1;
|
||||
if(naxis_size_max < tmp && tmp > 1)
|
||||
naxis_size_max=tmp;
|
||||
}
|
||||
/* File is composed of several 2880-bytes blocks */
|
||||
file_recovery_new->data_check=&data_check_fits;
|
||||
file_recovery_new->file_check=&file_check_size;
|
||||
file_recovery_new->calculated_file_size=(i+2880-1)/2880*2880+(naxis_size_max+2880-1)/2880*2880;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void register_header_check_fits(file_stat_t *file_stat)
|
||||
{
|
||||
register_header_check(0, "SIMPLE =", 9, &header_check_fits, file_stat);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue