1 /*
2
3 File: xfs.c
4
5 Copyright (C) 2004-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
27 #include <stdio.h>
28 #ifdef HAVE_STDLIB_H
29 #include <stdlib.h>
30 #endif
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #endif
34 #include "types.h"
35 #include "common.h"
36 #include "xfs.h"
37 #include "fnctdsk.h"
38 #include "log.h"
39 #include "guid_cpy.h"
40
41 static void set_xfs_info(const struct xfs_sb *sb, partition_t *partition);
42 static int test_xfs(const disk_t *disk_car, const struct xfs_sb *sb, const partition_t *partition, const int verbose);
43
check_xfs(disk_t * disk_car,partition_t * partition,const int verbose)44 int check_xfs(disk_t *disk_car,partition_t *partition,const int verbose)
45 {
46 unsigned char *buffer=(unsigned char*)MALLOC(XFS_SUPERBLOCK_SIZE);
47 if(disk_car->pread(disk_car, buffer, XFS_SUPERBLOCK_SIZE, partition->part_offset) != XFS_SUPERBLOCK_SIZE)
48 {
49 free(buffer);
50 return 1;
51 }
52 if(test_xfs(disk_car, (struct xfs_sb*)buffer, partition, verbose)!=0)
53 {
54 free(buffer);
55 return 1;
56 }
57 set_xfs_info((struct xfs_sb*)buffer, partition);
58 free(buffer);
59 return 0;
60 }
61
test_xfs(const disk_t * disk_car,const struct xfs_sb * sb,const partition_t * partition,const int verbose)62 static int test_xfs(const disk_t *disk_car, const struct xfs_sb *sb, const partition_t *partition, const int verbose)
63 {
64 if(sb->sb_magicnum!=be32(XFS_SB_MAGIC) ||
65 (uint16_t)be16(sb->sb_sectsize) != (1U << sb->sb_sectlog) ||
66 (uint32_t)be32(sb->sb_blocksize) != (1U << sb->sb_blocklog) ||
67 (uint16_t)be16(sb->sb_inodesize) != (1U << sb->sb_inodelog))
68 return 1;
69 switch(be16(sb->sb_versionnum) & XFS_SB_VERSION_NUMBITS)
70 {
71 case XFS_SB_VERSION_1:
72 case XFS_SB_VERSION_2:
73 case XFS_SB_VERSION_3:
74 case XFS_SB_VERSION_4:
75 case XFS_SB_VERSION_5:
76 break;
77 default:
78 log_error("Unknown XFS version 0x%x\n",be16(sb->sb_versionnum)& XFS_SB_VERSION_NUMBITS);
79 break;
80 }
81 if(verbose>0)
82 log_info("\nXFS Marker at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
83 return 0;
84 }
85
recover_xfs(disk_t * disk_car,const struct xfs_sb * sb,partition_t * partition,const int verbose,const int dump_ind)86 int recover_xfs(disk_t *disk_car, const struct xfs_sb *sb,partition_t *partition,const int verbose, const int dump_ind)
87 {
88 if(test_xfs(disk_car, sb, partition, verbose)!=0)
89 return 1;
90 if(verbose>0 || dump_ind!=0)
91 {
92 log_info("\nrecover_xfs\n");
93 if(dump_ind!=0)
94 {
95 dump_log(sb,DEFAULT_SECTOR_SIZE);
96 }
97 }
98 set_xfs_info(sb, partition);
99 partition->part_size = (uint64_t)be64(sb->sb_dblocks) * be32(sb->sb_blocksize);
100 partition->part_type_i386=P_LINUX;
101 partition->part_type_mac=PMAC_LINUX;
102 partition->part_type_sun=PSUN_LINUX;
103 partition->part_type_gpt=GPT_ENT_TYPE_LINUX_DATA;
104 guid_cpy(&partition->part_uuid, (const efi_guid_t *)&sb->sb_uuid);
105 return 0;
106 }
107
set_xfs_info(const struct xfs_sb * sb,partition_t * partition)108 static void set_xfs_info(const struct xfs_sb *sb, partition_t *partition)
109 {
110 partition->blocksize=be32(sb->sb_blocksize);
111 partition->fsname[0]='\0';
112 partition->info[0]='\0';
113 switch(be16(sb->sb_versionnum) & XFS_SB_VERSION_NUMBITS)
114 {
115 case XFS_SB_VERSION_1:
116 partition->upart_type = UP_XFS;
117 snprintf(partition->info, sizeof(partition->info),
118 "XFS <=6.1, blocksize=%u", partition->blocksize);
119 break;
120 case XFS_SB_VERSION_2:
121 partition->upart_type = UP_XFS2;
122 snprintf(partition->info, sizeof(partition->info),
123 "XFS 6.2 - attributes, blocksize=%u", partition->blocksize);
124 break;
125 case XFS_SB_VERSION_3:
126 partition->upart_type = UP_XFS3;
127 snprintf(partition->info, sizeof(partition->info),
128 "XFS 6.2 - new inode version, blocksize=%u", partition->blocksize);
129 break;
130 case XFS_SB_VERSION_4:
131 partition->upart_type = UP_XFS4;
132 snprintf(partition->info, sizeof(partition->info),
133 "XFS 6.2+ - bitmap version, blocksize=%u", partition->blocksize);
134 break;
135 case XFS_SB_VERSION_5:
136 partition->upart_type = UP_XFS5;
137 snprintf(partition->info, sizeof(partition->info),
138 "XFS CRC enabled, blocksize=%u", partition->blocksize);
139 break;
140 default:
141 snprintf(partition->info, sizeof(partition->info),
142 "XFS unknown version %u\n", be16(sb->sb_versionnum)& XFS_SB_VERSION_NUMBITS);
143 break;
144 }
145 set_part_name(partition,sb->sb_fname,12);
146 }
147