1 /*
2 
3     File: btrfs.c
4 
5     Copyright (C) 2011 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 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #include "types.h"
34 #include "common.h"
35 #include "btrfs.h"
36 #include "fnctdsk.h"
37 #include "log.h"
38 #include "guid_cpy.h"
39 
40 static int test_btrfs(const struct btrfs_super_block *sb);
41 
set_btrfs_info(const struct btrfs_super_block * sb,partition_t * partition)42 static void set_btrfs_info(const struct btrfs_super_block *sb, partition_t *partition)
43 {
44   partition->upart_type=UP_BTRFS;
45   partition->blocksize=le32(sb->dev_item.sector_size);
46   set_part_name(partition, sb->label, sizeof(sb->label));
47   snprintf(partition->info, sizeof(partition->info), "btrfs blocksize=%u", partition->blocksize);
48   if(le64(sb->bytenr)!=partition->part_offset + BTRFS_SUPER_INFO_OFFSET)
49   {
50     strcat(partition->info," Backup superblock");
51   }
52   /* last mounted => date */
53 }
54 
check_btrfs(disk_t * disk_car,partition_t * partition)55 int check_btrfs(disk_t *disk_car,partition_t *partition)
56 {
57   unsigned char *buffer=(unsigned char*)MALLOC(BTRFS_SUPER_INFO_SIZE);
58   if(disk_car->pread(disk_car, buffer, BTRFS_SUPER_INFO_SIZE, partition->part_offset + BTRFS_SUPER_INFO_OFFSET) != BTRFS_SUPER_INFO_SIZE)
59   {
60     free(buffer);
61     return 1;
62   }
63   if(test_btrfs((struct btrfs_super_block*)buffer)!=0)
64   {
65     free(buffer);
66     return 1;
67   }
68   set_btrfs_info((struct btrfs_super_block*)buffer, partition);
69   free(buffer);
70   return 0;
71 }
72 
73 /*
74 Primary superblock is at 1024 (SUPERBLOCK_OFFSET)
75 Group 0 begin at s_first_data_block
76 */
recover_btrfs(disk_t * disk,const struct btrfs_super_block * sb,partition_t * partition,const int verbose,const int dump_ind)77 int recover_btrfs(disk_t *disk, const struct btrfs_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
78 {
79   if(test_btrfs(sb)!=0)
80     return 1;
81   if(dump_ind!=0)
82   {
83     if(partition!=NULL && disk!=NULL)
84       log_info("\nbtrfs magic value at %u/%u/%u\n",
85 	  offset2cylinder(disk,partition->part_offset),
86 	  offset2head(disk,partition->part_offset),
87 	  offset2sector(disk,partition->part_offset));
88     dump_log(sb, BTRFS_SUPER_INFO_SIZE);
89   }
90   if(partition==NULL)
91     return 0;
92   set_btrfs_info(sb, partition);
93   partition->part_type_i386=P_LINUX;
94   partition->part_type_mac=PMAC_LINUX;
95   partition->part_type_sun=PSUN_LINUX;
96   partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA;
97   partition->part_size=(uint64_t)le64(sb->dev_item.total_bytes);
98   guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->fsid);
99   if(verbose>0)
100   {
101     log_info("\n");
102   }
103   partition->sborg_offset=BTRFS_SUPER_INFO_OFFSET;
104   partition->sb_size=BTRFS_SUPER_INFO_SIZE;
105   if(verbose>0)
106   {
107     if(disk==NULL)
108       log_info("recover_btrfs: part_size %lu\n", (long unsigned)(partition->part_size / le32(sb->dev_item.sector_size)));
109     else
110       log_info("recover_btrfs: part_size %lu\n", (long unsigned)(partition->part_size / disk->sector_size));
111   }
112   return 0;
113 }
114 
test_btrfs(const struct btrfs_super_block * sb)115 static int test_btrfs(const struct btrfs_super_block *sb)
116 {
117   if(memcmp(&sb->magic, BTRFS_MAGIC, 8)!=0)
118     return 1;
119   if(le32(sb->dev_item.sector_size)==0)
120     return 1;
121   return 0;
122 }
123