static PyObject * doGetRaidChunkSize(PyObject * s, PyObject * args) { int fd; unsigned long size; mdp_super_t sb; if (!PyArg_ParseTuple(args, "i", &fd)) return NULL; if (ioctl(fd, BLKGETSIZE, &size)) { PyErr_SetFromErrno(PyExc_SystemError); return NULL; } /* put the size in 1k blocks */ size >>= 1; if (lseek64(fd, ((off64_t) 512) * (off64_t) MD_NEW_SIZE_SECTORS(size), SEEK_SET) < 0) { PyErr_SetFromErrno(PyExc_SystemError); return NULL; } if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) { PyErr_SetFromErrno(PyExc_SystemError); return NULL; } if (sb.md_magic != MD_SB_MAGIC) { PyErr_SetString(PyExc_ValueError, "bad md magic on device"); return NULL; } return Py_BuildValue("i", sb.chunk_size / 1024); }
static PyObject * doWipeRaidSuperblock(PyObject * s, PyObject * args) { int fd; unsigned long size; struct mdp_super_t * sb; if (!PyArg_ParseTuple(args, "i", &fd)) return NULL; if (ioctl(fd, BLKGETSIZE, &size)) { PyErr_SetFromErrno(PyExc_SystemError); return NULL; } /* put the size in 1k blocks */ size >>= 1; if (lseek64(fd, ((off64_t) 512) * (off64_t) MD_NEW_SIZE_SECTORS(size), SEEK_SET) < 0) { PyErr_SetFromErrno(PyExc_SystemError); return NULL; } sb = malloc(sizeof(mdp_super_t)); sb = memset(sb, '\0', sizeof(mdp_super_t)); if (write(fd, sb, sizeof(sb)) != sizeof(sb)) { PyErr_SetFromErrno(PyExc_SystemError); return NULL; } return Py_None; }
int recover_MD_from_partition(disk_t *disk_car, partition_t *partition, const int verbose) { unsigned char *buffer=(unsigned char*)MALLOC(MD_SB_BYTES); /* MD version 0.90 */ { uint64_t offset=MD_NEW_SIZE_SECTORS(partition->part_size/512)*512; if(disk_car->pread(disk_car, buffer, MD_SB_BYTES, partition->part_offset + offset) == MD_SB_BYTES) { if(recover_MD(disk_car,(struct mdp_superblock_s*)buffer,partition,verbose,0)==0) { free(buffer); return 0; } } } /* MD version 1.0 */ if(partition->part_size > 8*2*512) { uint64_t offset=(((partition->part_size/512)-8*2) & ~(4*2-1))*512; if(disk_car->pread(disk_car, buffer, MD_SB_BYTES, partition->part_offset + offset) == MD_SB_BYTES) { const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer; if(le32(sb1->major_version)==1 && recover_MD(disk_car,(struct mdp_superblock_s*)buffer,partition,verbose,0)==0) { partition->part_offset-=le64(sb1->super_offset)*512-offset; free(buffer); return 0; } } } /* md 1.1 & 1.2 don't need special operation to be recovered */ free(buffer); return 1; }
/* * Returns -1 on error */ int dev_is_md(struct device *dev, uint64_t *sb) { int ret = 1; md_minor_version_t minor; uint64_t size, sb_offset; if (!dev_get_size(dev, &size)) { stack; return -1; } if (size < MD_RESERVED_SECTORS * 2) return 0; if (!dev_open_readonly(dev)) { stack; return -1; } /* Check if it is an md component device. */ /* Version 0.90.0 */ sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT; if (_dev_has_md_magic(dev, sb_offset)) goto out; minor = MD_MINOR_VERSION_MIN; /* Version 1, try v1.0 -> v1.2 */ do { sb_offset = _v1_sb_offset(size, minor); if (_dev_has_md_magic(dev, sb_offset)) goto out; } while (++minor <= MD_MINOR_VERSION_MAX); ret = 0; out: if (!dev_close(dev)) stack; if (ret && sb) *sb = sb_offset; return ret; }
int check_MD(disk_t *disk_car, partition_t *partition, const int verbose) { unsigned char *buffer=(unsigned char*)MALLOC(MD_SB_BYTES); /* MD version 1.1 */ if(disk_car->pread(disk_car, buffer, MD_SB_BYTES, partition->part_offset) == MD_SB_BYTES) { const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer; if(le32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC && le32(sb1->major_version)==1 && le64(sb1->super_offset)==0 && test_MD(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 1.1\n"); set_MD_info((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } if(be32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC && be32(sb1->major_version)==1 && be64(sb1->super_offset)==0 && test_MD_be(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 1.1 (BigEndian)\n"); set_MD_info_be((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } } /* MD version 1.2 */ if(disk_car->pread(disk_car, buffer, MD_SB_BYTES, partition->part_offset + 4096) == MD_SB_BYTES) { const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer; if(le32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC && le32(sb1->major_version)==1 && le64(sb1->super_offset)==8 && test_MD(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 1.2\n"); set_MD_info((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } if(be32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC && be32(sb1->major_version)==1 && be64(sb1->super_offset)==8 && test_MD_be(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 1.2 (BigEndian)\n"); set_MD_info_be((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } } /* MD version 0.90 */ { const struct mdp_superblock_s *sb=(const struct mdp_superblock_s *)buffer; const uint64_t offset=MD_NEW_SIZE_SECTORS(partition->part_size/512)*512; if(verbose>1) { log_verbose("Raid md 0.90 offset %llu\n", (long long unsigned)offset/512); } if(disk_car->pread(disk_car, buffer, MD_SB_BYTES, partition->part_offset + offset) == MD_SB_BYTES) { if(le32(sb->md_magic)==(unsigned int)MD_SB_MAGIC && le32(sb->major_version)==0 && test_MD(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 0.90\n"); set_MD_info((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } if(be32(sb->md_magic)==(unsigned int)MD_SB_MAGIC && be32(sb->major_version)==0 && test_MD_be(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 0.90 (BigEndian)\n"); set_MD_info_be((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } } } /* MD version 1.0 */ if(partition->part_size > 8*2*512) { const uint64_t offset=(uint64_t)(((partition->part_size/512)-8*2) & ~(4*2-1))*512; if(verbose>1) { log_verbose("Raid md 1.0 offset %llu\n", (long long unsigned)offset/512); } if(disk_car->pread(disk_car, buffer, MD_SB_BYTES, partition->part_offset + offset) == MD_SB_BYTES) { const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer; if(le32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC && le32(sb1->major_version)==1 && le64(sb1->super_offset)==(offset/512) && test_MD(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 1.0\n"); set_MD_info((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } if(be32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC && be32(sb1->major_version)==1 && be64(sb1->super_offset)==(offset/512) && test_MD_be(disk_car, (struct mdp_superblock_s*)buffer, partition, 0)==0) { log_info("check_MD 1.0 (BigEndian)\n"); set_MD_info_be((struct mdp_superblock_s*)buffer, partition, verbose); free(buffer); return 0; } } } free(buffer); return 1; }
static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_org, const int verbose, const int dump_ind, const int fast_mode, char **current_cmd) { unsigned char *buffer_disk; unsigned char *buffer_disk0; /* TODO use circular buffer for try_offset and try_offset_raid */ uint64_t try_offset[MAX_SEARCH_LOCATION]; uint64_t try_offset_raid[MAX_SEARCH_LOCATION]; const uint64_t min_location=get_min_location(disk_car); uint64_t search_location; unsigned int try_offset_nbr=0; unsigned int try_offset_raid_nbr=0; #ifdef HAVE_NCURSES unsigned int old_cylinder=0; #endif const unsigned int location_boundary=get_location_boundary(disk_car); indstop_t ind_stop=INDSTOP_CONTINUE; list_part_t *list_part=NULL; list_part_t *list_part_bad=NULL; partition_t *partition; /* It's not a problem to read a little bit more than necessary */ const uint64_t search_location_max=td_max((disk_car->disk_size / ((uint64_t) disk_car->geom.heads_per_cylinder * disk_car->geom.sectors_per_head * disk_car->sector_size) + 1 ) * ((uint64_t) disk_car->geom.heads_per_cylinder * disk_car->geom.sectors_per_head * disk_car->sector_size), disk_car->disk_real_size); assert(disk_car->sector_size>0); partition=partition_new(disk_car->arch); buffer_disk=(unsigned char*)MALLOC(16*DEFAULT_SECTOR_SIZE); buffer_disk0=(unsigned char*)MALLOC(16*DEFAULT_SECTOR_SIZE); { /* Will search for partition at current known partition location */ const list_part_t *element; for(element=list_part_org;element!=NULL;element=element->next) { hint_insert(try_offset, element->part->part_offset, &try_offset_nbr); } } #ifdef HAVE_NCURSES wmove(stdscr,22,0); wattrset(stdscr, A_REVERSE); waddstr(stdscr," Stop "); wattroff(stdscr, A_REVERSE); #endif screen_buffer_reset(); log_info("\nsearch_part()\n"); log_info("%s\n",disk_car->description(disk_car)); search_location=min_location; search_add_hints(disk_car, try_offset, &try_offset_nbr); /* Not every sector will be examined */ search_location_init(disk_car, location_boundary, fast_mode); /* Scan the disk */ while(ind_stop!=INDSTOP_QUIT && search_location < search_location_max) { CHS_t start; offset2CHS_inline(disk_car,search_location,&start); #ifdef HAVE_NCURSES if(disk_car->geom.heads_per_cylinder>1) { if(old_cylinder!=start.cylinder) { old_cylinder=start.cylinder; wmove(stdscr,ANALYSE_Y,ANALYSE_X); wclrtoeol(stdscr); wprintw(stdscr,"Analyse cylinder %5u/%u: %02u%%", start.cylinder, disk_car->geom.cylinders-1, (unsigned int)(search_location*100/disk_car->disk_size)); wrefresh(stdscr); switch(check_enter_key_or_s(stdscr)) { case 1: ind_stop=INDSTOP_STOP; break; case 2: ind_stop=INDSTOP_SKIP; break; } } } else if((start.cylinder & 0x7FFF)==0) { wmove(stdscr,ANALYSE_Y,ANALYSE_X); wclrtoeol(stdscr); wprintw(stdscr,"Analyse sector %11llu/%lu: %02u%%", search_location / disk_car->sector_size, (disk_car->disk_size-1)/disk_car->sector_size, (unsigned int)(search_location*100/disk_car->disk_size)); wrefresh(stdscr); switch(check_enter_key_or_s(stdscr)) { case 1: ind_stop=INDSTOP_STOP; break; case 2: ind_stop=INDSTOP_SKIP; break; } } #endif { unsigned int sector_inc=0; int test_nbr=0; int search_now=0; int search_now_raid=0; while(try_offset_nbr>0 && try_offset[0]<=search_location) { unsigned int j; if(try_offset[0]==search_location) search_now=1; for(j=0;j<try_offset_nbr-1;j++) try_offset[j]=try_offset[j+1]; try_offset_nbr--; } /* PC x/0/1 x/1/1 x/2/1 */ /* PC Vista 2048 sectors unit */ if(disk_car->arch==&arch_i386) search_now|= (start.sector==1 && fast_mode>1) || (start.sector==1 && start.head<=2) || search_location%(2048*512)==0; else search_now|= (search_location%location_boundary==0); while(try_offset_raid_nbr>0 && try_offset_raid[0]<=search_location) { unsigned int j; if(try_offset_raid[0]==search_location) search_now_raid=1; for(j=0;j<try_offset_raid_nbr-1;j++) try_offset_raid[j]=try_offset_raid[j+1]; try_offset_raid_nbr--; } do { int res=0; partition->part_size=(uint64_t)0; partition->part_offset=search_location; if(res<=0 && test_nbr==0) { if(search_now_raid>0 || fast_mode>1) { /* Search Linux software RAID */ if(disk_car->pread(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, search_location) == 8 *DEFAULT_SECTOR_SIZE) { if(recover_MD(disk_car, (const struct mdp_superblock_s*)buffer_disk, partition, verbose, dump_ind)==0) { const struct mdp_superblock_1 *sb1=(const struct mdp_superblock_1 *)buffer_disk; if(le32(sb1->md_magic)==(unsigned int)MD_SB_MAGIC) { if(le32(sb1->major_version)==0) partition->part_offset-=(uint64_t)MD_NEW_SIZE_SECTORS(partition->part_size/512)*512; else partition->part_offset-=le64(sb1->super_offset)*512; } else { if(be32(sb1->major_version)==0) partition->part_offset-=(uint64_t)MD_NEW_SIZE_SECTORS(partition->part_size/512)*512; else partition->part_offset-=be64(sb1->super_offset)*512; } res=1; } else res=0; } } test_nbr++; } if(res<=0 && test_nbr==1) { if((disk_car->arch==&arch_i386 && ((start.sector==7 && (start.head<=2 || fast_mode>1)) || search_location%(2048*512)==(7-1)*512)) || (disk_car->arch!=&arch_i386 && (search_location%location_boundary==(7-1)*512)) || (disk_car->arch==&arch_gpt&& (search_location%(2048*512)==(7-1)*512)) || (disk_car->arch==&arch_none && search_location==(7-1)*512)) res=search_FAT_backup(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==2) { if((disk_car->arch==&arch_i386 && ((start.sector==13 && (start.head<=2 || fast_mode>1)) || search_location%(2048*512)==(13-1)*disk_car->sector_size)) || (disk_car->arch==&arch_gpt&& (search_location%(2048*512)==(13-1)*512)) || (disk_car->arch!=&arch_i386 && (search_location%location_boundary==(13-1)*disk_car->sector_size))) res=search_EXFAT_backup(buffer_disk, disk_car, partition); test_nbr++; } if(res<=0 && test_nbr==3) { if((disk_car->arch==&arch_i386 && ((start.sector==disk_car->geom.sectors_per_head && (start.head==disk_car->geom.heads_per_cylinder-1 || fast_mode>1)) || search_location%(2048*512)==(2048-1)*512)) || (disk_car->arch==&arch_gpt&& (search_location%(2048*512)==(2048-1)*512)) || (disk_car->arch!=&arch_i386 && search_location%location_boundary==(location_boundary-512) && search_location>0)) res=search_NTFS_backup(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==4) { if((disk_car->arch==&arch_i386 && ((start.sector==disk_car->geom.sectors_per_head && (start.head==disk_car->geom.heads_per_cylinder-1 || fast_mode>1)) || search_location%(2048*512)==(2048-1)*512)) || (disk_car->arch!=&arch_i386 && search_location%location_boundary==(location_boundary-512) && search_location>0)) res=search_HFS_backup(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==5) { int s_log_block_size; /* try backup superblock */ /* It must be in fast_mode>0 because it can hide otherwise other partition type */ /* Block size: 1024, 2048 or 4096 bytes (8192 bytes on Alpha systems) */ /* From e2fsprogs-1.34/lib/ext2fs/initialize.c: set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); */ /* Assumes that TestDisk is not running under Alpha and s_blocks_per_group=8 * block size */ for(s_log_block_size=0;(s_log_block_size<=2)&&(res<=0);s_log_block_size++) { /* sparse superblock feature: The groups chosen are 0, 1 and powers of 3, 5 and 7. */ /* Checking group 3 */ const uint64_t hd_offset=3*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)+(s_log_block_size==0?2*DEFAULT_SECTOR_SIZE:0); if(search_location>=hd_offset) { CHS_t start_ext2; offset2CHS_inline(disk_car,search_location-hd_offset,&start_ext2); if((disk_car->arch==&arch_i386 && start_ext2.sector==1 && (start_ext2.head<=2 || fast_mode>1)) || (disk_car->arch==&arch_i386 && (search_location-hd_offset)%(2048*512)==0) || (disk_car->arch!=&arch_i386 && (search_location-hd_offset)%location_boundary==0)) { if(disk_car->pread(disk_car, buffer_disk, 1024, search_location)==1024) { const struct ext2_super_block *sb=(const struct ext2_super_block*)buffer_disk; if(le16(sb->s_magic)==EXT2_SUPER_MAGIC && le16(sb->s_block_group_nr)>0 && recover_EXT2(disk_car, sb, partition, verbose, dump_ind)==0) res=1; } } } } test_nbr++; } if(res<=0 && test_nbr==6) { if(search_now==0) test_nbr=14; else { if(disk_car->pread(disk_car, buffer_disk0, 16 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 16 * DEFAULT_SECTOR_SIZE) res=search_type_2(buffer_disk0,disk_car,partition,verbose,dump_ind); else res=-1; test_nbr++; } } if(res<=0 && test_nbr==7) { if(res==0) res=search_type_1(buffer_disk0, disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==8) { if(res==0) res=search_type_0(buffer_disk0,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==9) { res=search_type_8(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==10) { /* Try to catch disklabel before BSD FFS partition */ res=search_type_16(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==11) { res=search_type_64(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==12) { /* read to fill the cache */ disk_car->pread(disk_car, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, partition->part_offset + (63 + 16) * 512); /* Try to catch disklabel before BSD FFS partition */ res=search_type_128(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(res<=0 && test_nbr==13) { res=search_type_2048(buffer_disk,disk_car,partition,verbose,dump_ind); test_nbr++; } if(test_nbr>=14) { sector_inc=1; test_nbr=0; } if(res<0) { #ifdef HAVE_NCURSES wmove(stdscr,ANALYSE_Y+1,ANALYSE_X); wclrtoeol(stdscr); wprintw(stdscr,msg_READ_ERROR_AT, start.cylinder,start.head,start.sector,(unsigned long)(partition->part_offset/disk_car->sector_size)); #endif /* Stop reading after the end of the disk */ if(search_location >= disk_car->disk_real_size) search_location = search_location_max; } else if(res>0) { partition->status=STATUS_DELETED; log_partition(disk_car,partition); aff_part_buffer(AFF_PART_BASE, disk_car,partition); #ifdef HAVE_NCURSES screen_buffer_to_interface(); #endif if(disk_car->arch->is_part_known(partition)!=0 && partition->part_size>1 && partition->part_offset>=min_location) { const uint64_t pos_fin=partition->part_offset+partition->part_size-1; if(partition->upart_type!=UP_MD && partition->upart_type!=UP_MD1 && ind_stop==INDSTOP_CONTINUE) { /* Detect Linux md 0.9 software raid */ unsigned int disk_factor; for(disk_factor=6; disk_factor>=1;disk_factor--) { /* disk_factor=1, detect Raid 0/1 */ /* disk_factor>1, detect Raid 5 */ unsigned int help_factor; for(help_factor=0; help_factor<=MD_MAX_CHUNK_SIZE/MD_RESERVED_BYTES+3; help_factor++) { const uint64_t offset=(uint64_t)MD_NEW_SIZE_SECTORS((partition->part_size/disk_factor+help_factor*MD_RESERVED_BYTES-1)/MD_RESERVED_BYTES*MD_RESERVED_BYTES/512)*512; hint_insert(try_offset_raid, partition->part_offset+offset, &try_offset_raid_nbr); } } /* TODO: Detect Linux md 1.0 software raid */ } /* */ if(pos_fin <= search_location_max) { { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); list_part=insert_new_partition(list_part, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } { const uint64_t next_part_offset=partition->part_offset+partition->part_size-1+1; const uint64_t head_size=disk_car->geom.sectors_per_head * disk_car->sector_size; hint_insert(try_offset, next_part_offset, &try_offset_nbr); hint_insert(try_offset, next_part_offset+head_size, &try_offset_nbr); if(next_part_offset%head_size!=0) { hint_insert(try_offset, (next_part_offset+head_size-1)/head_size*head_size, &try_offset_nbr); hint_insert(try_offset, (next_part_offset+head_size-1)/head_size*head_size+head_size, &try_offset_nbr); } } if((fast_mode==0) && (partition->part_offset+partition->part_size-disk_car->sector_size > search_location)) { search_location=partition->part_offset+partition->part_size-disk_car->sector_size; test_nbr=0; sector_inc=1; } } else { { int insert_error=0; partition_t *new_partition=partition_new(NULL); dup_partition_t(new_partition,partition); list_part_bad=insert_new_partition(list_part_bad, new_partition, 0, &insert_error); if(insert_error>0) free(new_partition); } if(verbose>0) log_warning("This partition ends after the disk limits. (start=%llu, size=%llu, end=%llu, disk end=%llu)\n", (unsigned long long)(partition->part_offset/disk_car->sector_size), (unsigned long long)(partition->part_size/disk_car->sector_size), (unsigned long long)(pos_fin/disk_car->sector_size), (unsigned long long)(disk_car->disk_size/disk_car->sector_size)); else log_warning("This partition ends after the disk limits.\n"); } } else { if(verbose>0) { log_warning("Partition not added.\n"); } } partition_reset(partition, disk_car->arch); } } while(sector_inc==0); } if(ind_stop==INDSTOP_SKIP) { ind_stop=INDSTOP_CONTINUE; if(try_offset_nbr>0 && search_location < try_offset[0]) search_location=try_offset[0]; } else if(ind_stop==INDSTOP_STOP) { if(try_offset_nbr>0 && search_location < try_offset[0]) search_location=try_offset[0]; else ind_stop=INDSTOP_QUIT; } else { /* Optimized "search_location+=disk_car->sector_size;" */ uint64_t min=search_location_update(search_location); if(try_offset_nbr>0 && min>try_offset[0]) min=try_offset[0]; if(try_offset_raid_nbr>0 && min>try_offset_raid[0]) min=try_offset_raid[0]; if(min==(uint64_t)-1 || min<=search_location) search_location+=disk_car->sector_size; else search_location=min; } } /* Search for NTFS partition near the supposed partition beginning given by the NTFS backup boot sector */ if(fast_mode>0) search_NTFS_from_backup(disk_car, list_part, verbose, dump_ind, min_location, search_location_max); free(partition); if(ind_stop!=INDSTOP_CONTINUE) log_info("Search for partition aborted\n"); if(list_part_bad!=NULL) { interface_part_bad_log(disk_car,list_part_bad); #ifdef HAVE_NCURSES if(*current_cmd==NULL) interface_part_bad_ncurses(disk_car,list_part_bad); #endif } part_free_list(list_part_bad); free(buffer_disk0); free(buffer_disk); return list_part; }