305d71ea0a
using frama-c
229 lines
7.2 KiB
C
229 lines
7.2 KiB
C
/*
|
|
|
|
File: phbs.c
|
|
|
|
Copyright (C) 1998-2009 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
|
|
#ifdef HAVE_TIME_H
|
|
#include <time.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_TIME_H
|
|
#include <sys/time.h>
|
|
#endif
|
|
#include "types.h"
|
|
#include "common.h"
|
|
#include "intrf.h"
|
|
#ifdef HAVE_NCURSES
|
|
#include "intrfn.h"
|
|
#endif
|
|
#include "list.h"
|
|
#include "filegen.h"
|
|
#include "photorec.h"
|
|
#include "log.h"
|
|
#include "file_tar.h"
|
|
#include "pnext.h"
|
|
#include "phnc.h"
|
|
#include "phbs.h"
|
|
#include "file_found.h"
|
|
|
|
#define READ_SIZE 1024*512
|
|
|
|
#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_tar)
|
|
extern const file_hint_t file_hint_tar;
|
|
#endif
|
|
extern file_check_list_t file_check_list;
|
|
extern int need_to_stop;
|
|
|
|
/*@
|
|
@ requires \valid(dst);
|
|
@ requires \valid_read(src);
|
|
@ requires \separated(src, dst);
|
|
@*/
|
|
static inline void file_recovery_cpy(file_recovery_t *dst, const file_recovery_t *src)
|
|
{
|
|
memcpy(dst, src, sizeof(*dst));
|
|
dst->location.list.prev=&dst->location.list;
|
|
dst->location.list.next=&dst->location.list;
|
|
}
|
|
|
|
pstatus_t photorec_find_blocksize(struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space)
|
|
{
|
|
uint64_t offset=0;
|
|
unsigned char *buffer_start;
|
|
unsigned char *buffer_olddata;
|
|
unsigned char *buffer;
|
|
time_t start_time;
|
|
time_t previous_time;
|
|
unsigned int buffer_size;
|
|
const unsigned int blocksize=params->blocksize;
|
|
const unsigned int read_size=(blocksize>65536?blocksize:65536);
|
|
/*@ assert read_size >= 65536; */
|
|
alloc_data_t *current_search_space;
|
|
file_recovery_t file_recovery;
|
|
#ifndef DISABLED_FOR_FRAMAC
|
|
params->file_nbr=0;
|
|
reset_file_recovery(&file_recovery);
|
|
file_recovery.blocksize=blocksize;
|
|
buffer_size=blocksize + READ_SIZE;
|
|
buffer_start=(unsigned char *)MALLOC(buffer_size);
|
|
buffer_olddata=buffer_start;
|
|
buffer=buffer_olddata + blocksize;
|
|
start_time=time(NULL);
|
|
previous_time=start_time;
|
|
memset(buffer_olddata, 0, blocksize);
|
|
current_search_space=td_list_first_entry(&list_search_space->list, alloc_data_t, list);
|
|
if(current_search_space!=list_search_space)
|
|
offset=current_search_space->start;
|
|
if(options->verbose>0)
|
|
info_list_search_space(list_search_space, current_search_space, params->disk->sector_size, 0, options->verbose);
|
|
params->disk->pread(params->disk, buffer, READ_SIZE, offset);
|
|
while(current_search_space!=list_search_space)
|
|
{
|
|
const uint64_t old_offset=offset;
|
|
{
|
|
file_recovery_t file_recovery_new;
|
|
file_recovery_new.blocksize=blocksize;
|
|
file_recovery_new.location.start=offset;
|
|
#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_tar)
|
|
if(file_recovery.file_stat!=NULL && file_recovery.file_stat->file_hint==&file_hint_tar &&
|
|
is_valid_tar_header((const struct tar_posix_header *)(buffer-0x200)))
|
|
{ /* Currently saving a tar, do not check the data for know header */
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
const struct td_list_head *tmpl;
|
|
file_recovery_new.file_stat=NULL;
|
|
td_list_for_each(tmpl, &file_check_list.list)
|
|
{
|
|
const struct td_list_head *tmp;
|
|
const file_check_list_t *pos=td_list_entry_const(tmpl, const file_check_list_t, list);
|
|
td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list)
|
|
{
|
|
const file_check_t *file_check=td_list_entry_const(tmp, const file_check_t, list);
|
|
/*@ assert valid_file_check_node(file_check); */
|
|
if((file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) &&
|
|
file_check->header_check(buffer, read_size, 1, &file_recovery, &file_recovery_new)!=0)
|
|
{
|
|
file_recovery_new.file_stat=file_check->file_stat;
|
|
break;
|
|
}
|
|
}
|
|
if(file_recovery_new.file_stat!=NULL)
|
|
break;
|
|
}
|
|
if(file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=NULL)
|
|
{
|
|
/* A new file begins, backup file offset */
|
|
current_search_space=file_found(current_search_space, offset, file_recovery_new.file_stat);
|
|
params->file_nbr++;
|
|
file_recovery_cpy(&file_recovery, &file_recovery_new);
|
|
}
|
|
}
|
|
}
|
|
/* Check for data EOF */
|
|
if(file_recovery.file_stat!=NULL)
|
|
{
|
|
data_check_t res=DC_CONTINUE;
|
|
if(file_recovery.data_check!=NULL)
|
|
res=file_recovery.data_check(buffer_olddata, 2*blocksize, &file_recovery);
|
|
file_recovery.file_size+=blocksize;
|
|
if(res==DC_STOP || res==DC_ERROR)
|
|
{
|
|
/* EOF found */
|
|
reset_file_recovery(&file_recovery);
|
|
}
|
|
}
|
|
/* Check for maximum filesize */
|
|
if(file_recovery.file_stat!=NULL && file_recovery.file_stat->file_hint->max_filesize>0 && file_recovery.file_size>=file_recovery.file_stat->file_hint->max_filesize)
|
|
{
|
|
reset_file_recovery(&file_recovery);
|
|
}
|
|
|
|
if(params->file_nbr >= 10)
|
|
{
|
|
current_search_space=list_search_space;
|
|
}
|
|
else
|
|
get_next_sector(list_search_space, ¤t_search_space, &offset, blocksize);
|
|
if(current_search_space==list_search_space)
|
|
{
|
|
/* End of disk found => EOF */
|
|
reset_file_recovery(&file_recovery);
|
|
}
|
|
buffer_olddata+=blocksize;
|
|
buffer+=blocksize;
|
|
if( old_offset+blocksize!=offset ||
|
|
buffer+read_size>buffer_start+buffer_size)
|
|
{
|
|
memcpy(buffer_start, buffer_olddata, blocksize);
|
|
buffer_olddata=buffer_start;
|
|
buffer=buffer_olddata+blocksize;
|
|
if(options->verbose>1)
|
|
{
|
|
log_verbose("Reading sector %10llu/%llu\n",
|
|
(unsigned long long)((offset - params->partition->part_offset) / params->disk->sector_size),
|
|
(unsigned long long)((params->partition->part_size-1) / params->disk->sector_size));
|
|
}
|
|
if(params->disk->pread(params->disk, buffer, READ_SIZE, offset) != READ_SIZE)
|
|
{
|
|
#ifdef HAVE_NCURSES
|
|
wmove(stdscr,11,0);
|
|
wclrtoeol(stdscr);
|
|
wprintw(stdscr,"Error reading sector %10lu\n",
|
|
(unsigned long)((offset - params->partition->part_offset) / params->disk->sector_size));
|
|
#endif
|
|
}
|
|
#ifdef HAVE_NCURSES
|
|
{
|
|
time_t current_time;
|
|
current_time=time(NULL);
|
|
if(current_time>previous_time)
|
|
{
|
|
previous_time=current_time;
|
|
if(photorec_progressbar(stdscr, 0, params, offset, current_time))
|
|
{
|
|
log_info("PhotoRec has been stopped\n");
|
|
current_search_space=list_search_space;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if(need_to_stop!=0)
|
|
{
|
|
log_info("PhotoRec has been stopped\n");
|
|
current_search_space=list_search_space;
|
|
}
|
|
}
|
|
} /* end while(current_search_space!=list_search_space) */
|
|
free(buffer_start);
|
|
#endif
|
|
return PSTATUS_OK;
|
|
}
|