summaryrefslogtreecommitdiffstats
path: root/src/fatp.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2007-10-29 22:38:52 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2007-10-29 22:38:52 +0100
commit9928d99936105b4653d2d1b8ca74dc3ffba5c71e (patch)
tree06aa4f5e9f0055027c6fb54dd47a8414cf2fba32 /src/fatp.c
First version in git
Diffstat (limited to 'src/fatp.c')
-rw-r--r--src/fatp.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/fatp.c b/src/fatp.c
new file mode 100644
index 0000000..f1cc6ca
--- /dev/null
+++ b/src/fatp.c
@@ -0,0 +1,162 @@
+/*
+
+ File: fatp.c
+
+ Copyright (C) 2006-2007 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
+#include "types.h"
+#include "common.h"
+#include "list.h"
+#include "filegen.h"
+#include "fatp.h"
+#include "fat.h"
+#include "log.h"
+
+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);
+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);
+
+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)
+{
+ unsigned char *buffer;
+ const uint16_t *p16;
+ unsigned int prev_cluster;
+ uint64_t hd_offset=partition->part_offset+(uint64_t)fat_offset*sector_size;
+ uint64_t start_free=0;
+ uint64_t end_free=0;
+ log_trace("fat16_remove_used_space\n");
+ buffer=(unsigned char *)MALLOC(sector_size);
+ p16=(const uint16_t*)buffer;
+ del_search_space(list_search_space, partition->part_offset,
+ partition->part_offset+(uint64_t)(start_data*sector_size));
+ for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++)
+ {
+ unsigned int offset_s,offset_o;
+ offset_s=prev_cluster/(sector_size/2);
+ offset_o=prev_cluster%(sector_size/2);
+ if((offset_o==0)||(prev_cluster==2))
+ {
+ if(disk_car->read(disk_car, sector_size, buffer, hd_offset)!=0)
+ {
+ /* Consider these FAT sectors points to free clusters */
+ }
+ hd_offset+=sector_size;
+ }
+ if(le16(p16[offset_o])!=0)
+ {
+ /* Not free */
+ if(end_free+1==partition->part_offset+(uint64_t)(start_data+(prev_cluster-2)*cluster_size)*sector_size)
+ end_free+=cluster_size*sector_size;
+ else
+ {
+ if(start_free != end_free)
+ del_search_space(list_search_space, start_free, end_free);
+ start_free=partition->part_offset+(uint64_t)(start_data+(prev_cluster-2)*cluster_size)*sector_size;
+ end_free=start_free+(uint64_t)cluster_size*sector_size-1;
+ }
+ }
+ }
+ free(buffer);
+ if(start_free != end_free)
+ del_search_space(list_search_space, start_free, end_free);
+}
+
+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)
+{
+ unsigned char *buffer;
+ uint32_t *p32;
+ unsigned int prev_cluster;
+ uint64_t hd_offset=partition->part_offset+(uint64_t)fat_offset*sector_size;
+ uint64_t start_free=0;
+ uint64_t end_free=0;
+ log_trace("fat32_remove_used_space\n");
+ buffer=(unsigned char *)MALLOC(sector_size);
+ p32=(uint32_t*)buffer;
+ for(prev_cluster=2;prev_cluster<=no_of_cluster+1;prev_cluster++)
+ {
+ unsigned long int cluster;
+ unsigned int offset_s,offset_o;
+ offset_s=prev_cluster/(sector_size/4);
+ offset_o=prev_cluster%(sector_size/4);
+ if((offset_o==0)||(prev_cluster==2))
+ {
+ if(disk_car->read(disk_car,sector_size, buffer, hd_offset)!=0)
+ {
+ /* Consider these FAT sectors points to free clusters */
+ }
+ hd_offset+=sector_size;
+ }
+ cluster=le32(p32[offset_o]) & 0xFFFFFFF;
+ if(cluster!=0)
+ {
+ /* Not free */
+ if(end_free+1==partition->part_offset+(uint64_t)(start_data+(prev_cluster-2)*cluster_size)*sector_size)
+ end_free+=cluster_size*sector_size;
+ else
+ {
+ if(start_free != end_free)
+ del_search_space(list_search_space, start_free, end_free);
+ start_free=partition->part_offset+(uint64_t)(start_data+(prev_cluster-2)*cluster_size)*sector_size;
+ end_free=partition->part_offset+(uint64_t)(start_data+(prev_cluster-2+1)*cluster_size)*sector_size-1;
+ }
+ }
+ }
+ free(buffer);
+ if(start_free != end_free)
+ del_search_space(list_search_space, start_free, end_free);
+}
+
+unsigned int fat_remove_used_space(disk_t *disk_car, const partition_t *partition, alloc_data_t *list_search_space)
+{
+ unsigned long int fat_length;
+ unsigned long int start_fat1;
+ unsigned long int part_size;
+ unsigned int no_of_cluster;
+ unsigned int start_data;
+ unsigned char *buffer;
+ unsigned int res;
+ unsigned int sector_size;
+ const struct fat_boot_sector *fat_header;
+ buffer=MALLOC(3*disk_car->sector_size);
+ fat_header=(const struct fat_boot_sector *)buffer;
+ if(disk_car->read(disk_car,3*disk_car->sector_size, buffer, partition->part_offset)!=0)
+ {
+ free(buffer);
+ return 0;
+ }
+ sector_size=fat_sector_size(fat_header);
+ fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
+ part_size=(sectors(fat_header)>0?sectors(fat_header):le32(fat_header->total_sect));
+ start_fat1=le16(fat_header->reserved);
+ start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+sector_size-1)/sector_size;
+ no_of_cluster=(part_size-start_data)/fat_header->cluster_size;
+ if(partition->upart_type==UP_FAT16)
+ fat16_remove_used_space(disk_car,partition, list_search_space, start_fat1, no_of_cluster, start_data, fat_header->cluster_size,sector_size);
+ else if(partition->upart_type==UP_FAT32)
+ fat32_remove_used_space(disk_car,partition, list_search_space, start_fat1, no_of_cluster, start_data, fat_header->cluster_size,sector_size);
+ res=fat_header->cluster_size * sector_size;
+ free(buffer);
+ return res;
+}