1 /*
2
3 File: fatp.c
4
5 Copyright (C) 2006-2007 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
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
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 "list.h"
33 #include "filegen.h"
34 #include "fatp.h"
35 #include "fat.h"
36 #include "fat_common.h"
37 #include "log.h"
38
39 static void fat16_remove_used_space(disk_t *disk_car,const partition_t *partition, alloc_data_t *list_search_space, const unsigned int fat_offset, const unsigned int no_of_cluster, const unsigned int start_data, const unsigned int cluster_size, const unsigned int sector_size);
40 static void fat32_remove_used_space(disk_t *disk_car,const partition_t *partition, alloc_data_t *list_search_space, const unsigned int fat_offset, const unsigned int no_of_cluster, const unsigned int start_data, const unsigned int cluster_size, const unsigned int sector_size);
41
fat12_remove_used_space(disk_t * disk,const partition_t * partition,alloc_data_t * list_search_space,const unsigned int fat_offset,const unsigned int no_of_cluster,const unsigned int start_data,const unsigned int cluster_size,const unsigned int sector_size)42 static void fat12_remove_used_space(disk_t *disk,const partition_t *partition, alloc_data_t *list_search_space, const unsigned int fat_offset, const unsigned int no_of_cluster, const unsigned int start_data, const unsigned int cluster_size, const unsigned int sector_size)
43 {
44 unsigned char *buffer;
45 unsigned int cluster;
46 const uint64_t hd_offset=partition->part_offset+(uint64_t)fat_offset*sector_size;
47 uint64_t start_free=0;
48 uint64_t end_free=0;
49 unsigned long int offset_s_prev=0;
50 log_trace("fat12_remove_used_space\n");
51 buffer=(unsigned char *)MALLOC(2*sector_size);
52 del_search_space(list_search_space, partition->part_offset,
53 partition->part_offset + (uint64_t)start_data * sector_size - 1);
54 for(cluster=2; cluster<=no_of_cluster+1; cluster++)
55 {
56 unsigned long int offset_s,offset_o;
57 unsigned int next_cluster;
58 offset_s=(cluster+cluster/2)/disk->sector_size;
59 offset_o=(cluster+cluster/2)%disk->sector_size;
60 if(offset_s!=offset_s_prev || cluster==2)
61 {
62 offset_s_prev=offset_s;
63 if((unsigned)disk->pread(disk, buffer, 2*sector_size, hd_offset + offset_s * disk->sector_size) != 2*sector_size)
64 {
65 /* Consider these FAT sectors points to free clusters */
66 }
67 }
68 if((cluster&1)!=0)
69 next_cluster=le16((*((uint16_t*)&buffer[offset_o])))>>4;
70 else
71 next_cluster=le16(*((uint16_t*)&buffer[offset_o]))&0x0FFF;
72 if(next_cluster!=0)
73 {
74 /* Not free */
75 if(end_free+1==partition->part_offset+(start_data+(uint64_t)(cluster-2)*cluster_size)*sector_size)
76 end_free+=cluster_size*sector_size;
77 else
78 {
79 if(start_free != end_free)
80 del_search_space(list_search_space, start_free, end_free);
81 start_free=partition->part_offset+(start_data+(uint64_t)(cluster-2)*cluster_size)*sector_size;
82 end_free=start_free+(uint64_t)cluster_size*sector_size-1;
83 }
84 }
85 }
86 free(buffer);
87 if(start_free != end_free)
88 del_search_space(list_search_space, start_free, end_free);
89 }
90
fat16_remove_used_space(disk_t * disk_car,const partition_t * partition,alloc_data_t * list_search_space,const unsigned int fat_offset,const unsigned int no_of_cluster,const unsigned int start_data,const unsigned int cluster_size,const unsigned int sector_size)91 static void fat16_remove_used_space(disk_t *disk_car,const partition_t *partition, alloc_data_t *list_search_space, const unsigned int fat_offset, const unsigned int no_of_cluster, const unsigned int start_data, const unsigned int cluster_size, const unsigned int sector_size)
92 {
93 unsigned char *buffer;
94 const uint16_t *p16;
95 unsigned int prev_cluster;
96 uint64_t hd_offset=partition->part_offset+(uint64_t)fat_offset*sector_size;
97 uint64_t start_free=0;
98 uint64_t end_free=0;
99 log_trace("fat16_remove_used_space\n");
100 buffer=(unsigned char *)MALLOC(sector_size);
101 p16=(const uint16_t*)buffer;
102 del_search_space(list_search_space, partition->part_offset,
103 partition->part_offset + (uint64_t)start_data * sector_size - 1);
104 for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++)
105 {
106 unsigned int offset_o;
107 offset_o=prev_cluster%(sector_size/2);
108 if((offset_o==0)||(prev_cluster==2))
109 {
110 if((unsigned)disk_car->pread(disk_car, buffer, sector_size, hd_offset) != sector_size)
111 {
112 /* Consider these FAT sectors points to free clusters */
113 }
114 hd_offset+=sector_size;
115 }
116 if(le16(p16[offset_o])!=0)
117 {
118 /* Not free */
119 if(end_free+1==partition->part_offset+(start_data+(uint64_t)(prev_cluster-2)*cluster_size)*sector_size)
120 end_free+=cluster_size*sector_size;
121 else
122 {
123 if(start_free != end_free)
124 del_search_space(list_search_space, start_free, end_free);
125 start_free=partition->part_offset+(start_data+(uint64_t)(prev_cluster-2)*cluster_size)*sector_size;
126 end_free=start_free+(uint64_t)cluster_size*sector_size-1;
127 }
128 }
129 }
130 free(buffer);
131 if(start_free != end_free)
132 del_search_space(list_search_space, start_free, end_free);
133 }
134
fat32_remove_used_space(disk_t * disk_car,const partition_t * partition,alloc_data_t * list_search_space,const unsigned int fat_offset,const unsigned int no_of_cluster,const unsigned int start_data,const unsigned int cluster_size,const unsigned int sector_size)135 static void fat32_remove_used_space(disk_t *disk_car,const partition_t *partition, alloc_data_t *list_search_space, const unsigned int fat_offset, const unsigned int no_of_cluster, const unsigned int start_data, const unsigned int cluster_size, const unsigned int sector_size)
136 {
137 unsigned char *buffer;
138 uint32_t *p32;
139 unsigned int prev_cluster;
140 uint64_t hd_offset=partition->part_offset+(uint64_t)fat_offset*sector_size;
141 uint64_t start_free=0;
142 uint64_t end_free=0;
143 log_trace("fat32_remove_used_space\n");
144 buffer=(unsigned char *)MALLOC(sector_size);
145 p32=(uint32_t*)buffer;
146 del_search_space(list_search_space, partition->part_offset,
147 partition->part_offset + (uint64_t)start_data * sector_size - 1);
148 for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++)
149 {
150 unsigned long int cluster;
151 unsigned int offset_o;
152 offset_o=prev_cluster%(sector_size/4);
153 if((offset_o==0)||(prev_cluster==2))
154 {
155 if((unsigned)disk_car->pread(disk_car, buffer, sector_size, hd_offset) != sector_size)
156 {
157 /* Consider these FAT sectors points to free clusters */
158 }
159 hd_offset+=sector_size;
160 }
161 cluster=le32(p32[offset_o]) & 0xFFFFFFF;
162 if(cluster!=0)
163 {
164 /* Not free */
165 if(end_free+1==partition->part_offset+(uint64_t)(start_data+(prev_cluster-2)*cluster_size)*sector_size)
166 end_free+=cluster_size*sector_size;
167 else
168 {
169 if(start_free != end_free)
170 del_search_space(list_search_space, start_free, end_free);
171 start_free=partition->part_offset+(start_data+(uint64_t)(prev_cluster-2)*cluster_size)*sector_size;
172 end_free=start_free+(uint64_t)cluster_size*sector_size-1;
173 }
174 }
175 }
176 free(buffer);
177 if(start_free != end_free)
178 del_search_space(list_search_space, start_free, end_free);
179 }
180
fat_remove_used_space(disk_t * disk_car,const partition_t * partition,alloc_data_t * list_search_space)181 unsigned int fat_remove_used_space(disk_t *disk_car, const partition_t *partition, alloc_data_t *list_search_space)
182 {
183 unsigned long int fat_length;
184 unsigned long int start_fat1;
185 unsigned long int part_size;
186 unsigned int no_of_cluster;
187 unsigned int start_data;
188 unsigned char *buffer;
189 unsigned int res;
190 unsigned int sector_size;
191 const struct fat_boot_sector *fat_header;
192 buffer=(unsigned char *)MALLOC(3*disk_car->sector_size);
193 fat_header=(const struct fat_boot_sector *)buffer;
194 if((unsigned)disk_car->pread(disk_car, buffer, 3 * disk_car->sector_size, partition->part_offset) != 3 * disk_car->sector_size)
195 {
196 free(buffer);
197 return 0;
198 }
199 sector_size=fat_sector_size(fat_header);
200 if(sector_size==0)
201 {
202 free(buffer);
203 return 0;
204 }
205 fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
206 part_size=(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect));
207 start_fat1=le16(fat_header->reserved);
208 start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+sector_size-1)/sector_size;
209 no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster;
210 if(partition->upart_type==UP_FAT12)
211 fat12_remove_used_space(disk_car,partition, list_search_space, start_fat1, no_of_cluster, start_data, fat_header->sectors_per_cluster,sector_size);
212 else if(partition->upart_type==UP_FAT16)
213 fat16_remove_used_space(disk_car,partition, list_search_space, start_fat1, no_of_cluster, start_data, fat_header->sectors_per_cluster,sector_size);
214 else if(partition->upart_type==UP_FAT32)
215 fat32_remove_used_space(disk_car,partition, list_search_space, start_fat1, no_of_cluster, start_data, fat_header->sectors_per_cluster,sector_size);
216 res=fat_header->sectors_per_cluster * sector_size;
217 free(buffer);
218 return res;
219 }
220