1 /*
2
3 File: ext2_sbn.c
4
5 Copyright (C) 1998-2009 Christophe GRENIER <grenier@cgsecurity.org>
6
7 This software is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write the Free Software Foundation, Inc., 51
19 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 */
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #include "types.h"
31 #include "common.h"
32 #include "intrf.h"
33 #include "intrfn.h"
34 #include "fnctdsk.h"
35 #include "log.h"
36 #include "lang.h"
37 #include "ext2.h"
38 #include "ext2_sbn.h"
39
40 // blocksize=1024, 2048, 4096, 65536
41 // blocks per blocksgroup=8*blocksize
42 static const uint64_t group_size[4]={
43 (EXT2_MIN_BLOCK_SIZE<<0)*8*(EXT2_MIN_BLOCK_SIZE<<0),
44 (EXT2_MIN_BLOCK_SIZE<<1)*8*(EXT2_MIN_BLOCK_SIZE<<1),
45 (EXT2_MIN_BLOCK_SIZE<<2)*8*(EXT2_MIN_BLOCK_SIZE<<2),
46 (uint64_t)(EXT2_MIN_BLOCK_SIZE<<6)*8*(EXT2_MIN_BLOCK_SIZE<<6),
47 };
48 static const uint64_t factors[3]={3,5,7};
49
next_sb(const uint64_t hd_offset_old)50 static uint64_t next_sb(const uint64_t hd_offset_old)
51 {
52 uint64_t hd_offset=0;
53 int j;
54 for(j=0; j<4; j++)
55 {
56 int i;
57 const uint64_t offset=(j==0?2*512:0);
58 for(i=0; i<3; i++)
59 {
60 uint64_t val;
61 for(val=1; val * group_size[j] + offset <= hd_offset_old; val*=factors[i])
62 ;
63 if(hd_offset==0 || val * group_size[j] + offset < hd_offset)
64 hd_offset=val* group_size[j] + offset;
65 }
66 }
67 if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<0 && EXT2_MIN_BLOCK_SIZE<<0 < hd_offset)
68 hd_offset=EXT2_MIN_BLOCK_SIZE<<0;
69 else if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<1 && EXT2_MIN_BLOCK_SIZE<<1 < hd_offset)
70 hd_offset=EXT2_MIN_BLOCK_SIZE<<1;
71 else if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<2 && EXT2_MIN_BLOCK_SIZE<<2 < hd_offset)
72 hd_offset=EXT2_MIN_BLOCK_SIZE<<2;
73 else if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<6 && EXT2_MIN_BLOCK_SIZE<<6 < hd_offset)
74 hd_offset=EXT2_MIN_BLOCK_SIZE<<6;
75 return hd_offset;
76 }
77
search_superblock(disk_t * disk_car,partition_t * partition,const int verbose,const int dump_ind)78 list_part_t *search_superblock(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind)
79 {
80 unsigned char *buffer=(unsigned char *)MALLOC(2*0x200);
81 uint64_t hd_offset;
82 int nbr_sb=0;
83 list_part_t *list_part=NULL;
84 int ind_stop=0;
85 #ifdef HAVE_NCURSES
86 unsigned long int old_percent=0;
87 #endif
88 struct ext2_super_block *sb=(struct ext2_super_block *)buffer;
89 partition_t *new_partition=partition_new(disk_car->arch);
90 log_trace("search_superblock\n");
91 #ifdef HAVE_NCURSES
92 aff_copy(stdscr);
93 wmove(stdscr,4,0);
94 wprintw(stdscr,"%s",disk_car->description(disk_car));
95 mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG);
96 wmove(stdscr,6,0);
97 aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
98 wmove(stdscr,22,0);
99 wattrset(stdscr, A_REVERSE);
100 waddstr(stdscr," Stop ");
101 wattroff(stdscr, A_REVERSE);
102 #endif
103 for(hd_offset=0;
104 hd_offset<partition->part_size && nbr_sb<10 && ind_stop==0;
105 hd_offset=next_sb(hd_offset))
106 {
107 #ifdef HAVE_NCURSES
108 const unsigned long int percent=hd_offset*100/partition->part_size;
109 if(percent!=old_percent)
110 {
111 wmove(stdscr,9,0);
112 wclrtoeol(stdscr);
113 wprintw(stdscr, "Search ext2/ext3/ext4 superblock %10lu/%lu %lu%%",
114 (long unsigned)(hd_offset/disk_car->sector_size),
115 (long unsigned)(partition->part_size/disk_car->sector_size),
116 percent);
117 wrefresh(stdscr);
118 ind_stop|=check_enter_key_or_s(stdscr);
119 old_percent=percent;
120 }
121 #endif
122 if(disk_car->pread(disk_car, buffer, 1024, partition->part_offset + hd_offset) == 1024)
123 {
124 /* ext2/ext3/ext4 */
125 if(le16(sb->s_magic)==EXT2_SUPER_MAGIC)
126 {
127 dup_partition_t(new_partition,partition);
128 new_partition->part_offset+=hd_offset;
129 if(recover_EXT2(disk_car,sb,new_partition,verbose,dump_ind)==0)
130 {
131 int insert_error=0;
132 if(hd_offset<=(EXT2_MIN_BLOCK_SIZE<<2))
133 new_partition->part_offset-=hd_offset;
134 if(partition->blocksize==0)
135 {
136 partition->sborg_offset=new_partition->sborg_offset;
137 partition->sb_offset =new_partition->sb_offset;
138 partition->sb_size =new_partition->sb_size;
139 partition->blocksize =new_partition->blocksize;
140 }
141 log_info("Ext2 superblock found at sector %llu (block=%llu, blocksize=%u)\n",
142 (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE,
143 (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)),
144 (unsigned int)EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size));
145 #ifdef HAVE_NCURSES
146 wmove(stdscr,10+nbr_sb,0);
147 wprintw(stdscr,"Ext2 superblock found at sector %llu (block=%llu, blocksize=%u) \n",
148 (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE,
149 (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)),
150 EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size));
151 #endif
152 list_part=insert_new_partition(list_part, new_partition, 1, &insert_error);
153 new_partition=partition_new(disk_car->arch);
154 nbr_sb++;
155 }
156 }
157 }
158 }
159 free(new_partition);
160 free(buffer);
161 return list_part;
162 }
163
164