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