summaryrefslogtreecommitdiffstats
path: root/src/bsd.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/bsd.c
First version in git
Diffstat (limited to 'src/bsd.c')
-rw-r--r--src/bsd.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/src/bsd.c b/src/bsd.c
new file mode 100644
index 0000000..bd8759a
--- /dev/null
+++ b/src/bsd.c
@@ -0,0 +1,185 @@
+/*
+
+ File: bsd.c
+
+ Copyright (C) 1998-2006 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
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include "types.h"
+#include "common.h"
+#include "bsd.h"
+#include "intrf.h"
+#include "fnctdsk.h"
+#include "log.h"
+
+int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose, const unsigned int max_partitions)
+{
+ unsigned char *buffer;
+ buffer=(unsigned char*)MALLOC(BSD_DISKLABEL_SIZE);
+ if(disk_car->read(disk_car,BSD_DISKLABEL_SIZE, buffer, partition->part_offset+0x200))
+ {
+ free(buffer);
+ return 1;
+ }
+ if(test_BSD(disk_car,(const struct disklabel*)buffer,partition,verbose,0,max_partitions))
+ {
+ free(buffer);
+ return 1;
+ }
+ set_part_name(partition,((const struct disklabel*)buffer)->d_packname,16);
+ if(check_volume_name(partition->fsname,16))
+ partition->fsname[0]='\0';
+ free(buffer);
+ return 0;
+}
+
+int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind, const unsigned int max_partitions)
+{
+ if((le32(bsd_header->d_magic) == DISKMAGIC)&&
+ (le32(bsd_header->d_magic2)==DISKMAGIC))
+ {
+ unsigned int i;
+ const uint16_t* cp;
+ uint16_t crc;
+ if(verbose)
+ log_info("\nBSD offset %lu, nbr_part %u, CHS=(%u,%u,%u) ",
+ (long unsigned)(partition->part_offset/disk_car->sector_size),
+ (unsigned int)le16(bsd_header->d_npartitions),
+ (unsigned int)le32(bsd_header->d_ncylinders),
+ (unsigned int)le32(bsd_header->d_ntracks),
+ (unsigned int)le32(bsd_header->d_nsectors));
+ if(le16(bsd_header->d_npartitions) > max_partitions)
+ return 1;
+ crc=0;
+ for(cp=(const uint16_t*)bsd_header;
+ cp<(const uint16_t*)&bsd_header->d_partitions[le16(bsd_header->d_npartitions)];cp++)
+ crc^=*cp;
+ if(crc==0)
+ {
+ if(verbose>0)
+ {
+ log_info("CRC Ok\n");
+ }
+ }
+ else
+ log_error("Bad CRC! CRC must be xor'd by %04X\n",crc);
+ for(i=0;i<le16(bsd_header->d_npartitions);i++)
+ {
+ if(bsd_header->d_partitions[i].p_fstype>0)
+ {
+ if(verbose>0)
+ {
+ /* UFS UFS2 SWAP */
+ log_info("BSD %c: ", 'a'+i);
+ switch(bsd_header->d_partitions[i].p_fstype)
+ {
+ case TST_FS_SWAP:
+ log_info("swap");
+ break;
+ case TST_FS_BSDFFS:
+ log_info("4.2BSD fast filesystem");
+ break;
+ case TST_FS_BSDLFS:
+ log_info("4.4BSD log-structured filesystem");
+ break;
+ default:
+ log_info("type %02X", bsd_header->d_partitions[i].p_fstype);
+ break;
+ }
+ log_info(", offset %9u, size %9u ",
+ (unsigned int)le32(bsd_header->d_partitions[i].p_offset),
+ (unsigned int)le32(bsd_header->d_partitions[i].p_size));
+ log_CHS_from_LBA(disk_car,le32(bsd_header->d_partitions[i].p_offset));
+ log_info(" -> ");
+ log_CHS_from_LBA(disk_car,le32(bsd_header->d_partitions[i].p_offset)+le32(bsd_header->d_partitions[i].p_size)-1);
+ log_info("\n");
+ }
+ }
+ }
+ if(crc)
+ return 1;
+ if(max_partitions==BSD_MAXPARTITIONS)
+ partition->upart_type=UP_FREEBSD;
+ else
+ partition->upart_type=UP_OPENBSD;
+ if(dump_ind!=0)
+ {
+ dump_log(bsd_header,DEFAULT_SECTOR_SIZE);
+ }
+ return 0;
+ }
+ return 1;
+}
+
+int recover_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind)
+{
+ int i;
+ int i_max_p_offset=-1;
+ if(test_BSD(disk_car,bsd_header,partition,verbose,dump_ind,BSD_MAXPARTITIONS)==0)
+ {
+ for(i=0;i<BSD_MAXPARTITIONS;i++)
+ {
+ if(bsd_header->d_partitions[i].p_fstype>0)
+ {
+ if(i_max_p_offset==-1 || le32(bsd_header->d_partitions[i].p_offset)>le32(bsd_header->d_partitions[i_max_p_offset].p_offset))
+ i_max_p_offset=i;
+ }
+ }
+ if(i_max_p_offset>=0)
+ partition->part_size=(uint64_t)(le32(bsd_header->d_partitions[i_max_p_offset].p_size) +
+ le32(bsd_header->d_partitions[i_max_p_offset].p_offset) - 1) * disk_car->sector_size - partition->part_offset;
+ else
+ partition->part_size=0;
+ partition->part_type_i386=P_FREEBSD;
+ set_part_name(partition,bsd_header->d_packname,16);
+ if(check_volume_name(partition->fsname,16))
+ partition->fsname[0]='\0';
+ partition->info[0]='\0';
+ return 0;
+ }
+ if(test_BSD(disk_car,bsd_header,partition,verbose,dump_ind,OPENBSD_MAXPARTITIONS)==0)
+ {
+ for(i=0;i<OPENBSD_MAXPARTITIONS;i++)
+ {
+ if(bsd_header->d_partitions[i].p_fstype>0)
+ {
+ if(i_max_p_offset==-1 || le32(bsd_header->d_partitions[i].p_offset)>le32(bsd_header->d_partitions[i_max_p_offset].p_offset))
+ i_max_p_offset=i;
+ }
+ }
+ if(i_max_p_offset>=0)
+ partition->part_size=(uint64_t)(le32(bsd_header->d_partitions[i_max_p_offset].p_size) +
+ le32(bsd_header->d_partitions[i_max_p_offset].p_offset) - 1) * disk_car->sector_size - partition->part_offset;
+ else
+ partition->part_size=0;
+ partition->part_type_i386=P_OPENBSD;
+ set_part_name(partition,bsd_header->d_packname,16);
+ if(check_volume_name(partition->fsname,16))
+ partition->fsname[0]='\0';
+ partition->info[0]='\0';
+ return 0;
+ }
+ return 1;
+}