paul@212 | 1 | /* |
paul@212 | 2 | * swapfs.c --- swap ext2 filesystem data structures |
paul@212 | 3 | * |
paul@212 | 4 | * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. |
paul@212 | 5 | * |
paul@212 | 6 | * %Begin-Header% |
paul@212 | 7 | * This file may be redistributed under the terms of the GNU Library |
paul@212 | 8 | * General Public License, version 2. |
paul@212 | 9 | * %End-Header% |
paul@212 | 10 | */ |
paul@212 | 11 | |
paul@212 | 12 | #include "config.h" |
paul@212 | 13 | #include <stdio.h> |
paul@212 | 14 | #if HAVE_UNISTD_H |
paul@212 | 15 | #include <unistd.h> |
paul@212 | 16 | #endif |
paul@212 | 17 | #include <string.h> |
paul@212 | 18 | #include <time.h> |
paul@212 | 19 | |
paul@212 | 20 | #include "ext2_fs.h" |
paul@212 | 21 | #include "ext2fs.h" |
paul@212 | 22 | #include "ext2fsP.h" |
paul@212 | 23 | #include <ext2fs/ext2_ext_attr.h> |
paul@212 | 24 | |
paul@212 | 25 | void ext2fs_swap_super(struct ext2_super_block * sb) |
paul@212 | 26 | { |
paul@212 | 27 | int i; |
paul@212 | 28 | |
paul@212 | 29 | sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); |
paul@212 | 30 | sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); |
paul@212 | 31 | sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); |
paul@212 | 32 | sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count); |
paul@212 | 33 | sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count); |
paul@212 | 34 | sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block); |
paul@212 | 35 | sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size); |
paul@212 | 36 | sb->s_log_cluster_size = ext2fs_swab32(sb->s_log_cluster_size); |
paul@212 | 37 | sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group); |
paul@212 | 38 | sb->s_clusters_per_group = ext2fs_swab32(sb->s_clusters_per_group); |
paul@212 | 39 | sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group); |
paul@212 | 40 | sb->s_mtime = ext2fs_swab32(sb->s_mtime); |
paul@212 | 41 | sb->s_wtime = ext2fs_swab32(sb->s_wtime); |
paul@212 | 42 | sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count); |
paul@212 | 43 | sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count); |
paul@212 | 44 | sb->s_magic = ext2fs_swab16(sb->s_magic); |
paul@212 | 45 | sb->s_state = ext2fs_swab16(sb->s_state); |
paul@212 | 46 | sb->s_errors = ext2fs_swab16(sb->s_errors); |
paul@212 | 47 | sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level); |
paul@212 | 48 | sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck); |
paul@212 | 49 | sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval); |
paul@212 | 50 | sb->s_creator_os = ext2fs_swab32(sb->s_creator_os); |
paul@212 | 51 | sb->s_rev_level = ext2fs_swab32(sb->s_rev_level); |
paul@212 | 52 | sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid); |
paul@212 | 53 | sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid); |
paul@212 | 54 | sb->s_first_ino = ext2fs_swab32(sb->s_first_ino); |
paul@212 | 55 | sb->s_inode_size = ext2fs_swab16(sb->s_inode_size); |
paul@212 | 56 | sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr); |
paul@212 | 57 | sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat); |
paul@212 | 58 | sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat); |
paul@212 | 59 | sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat); |
paul@212 | 60 | /* sb->s_uuid is __u8 and does not need swabbing */ |
paul@212 | 61 | /* sb->s_volume_name is char and does not need swabbing */ |
paul@212 | 62 | /* sb->s_last_mounted is char and does not need swabbing */ |
paul@212 | 63 | sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap); |
paul@212 | 64 | /* sb->s_prealloc_blocks is __u8 and does not need swabbing */ |
paul@212 | 65 | /* sb->s_prealloc_dir_blocks is __u8 and does not need swabbing */ |
paul@212 | 66 | sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks); |
paul@212 | 67 | /* sb->s_journal_uuid is __u8 and does not need swabbing */ |
paul@212 | 68 | sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); |
paul@212 | 69 | sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); |
paul@212 | 70 | sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); |
paul@212 | 71 | for (i = 0; i < 4; i++) |
paul@212 | 72 | sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); |
paul@212 | 73 | /* sb->s_def_hash_version is __u8 and does not need swabbing */ |
paul@212 | 74 | /* sb->s_jnl_backup_type is __u8 and does not need swabbing */ |
paul@212 | 75 | sb->s_desc_size = ext2fs_swab16(sb->s_desc_size); |
paul@212 | 76 | sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts); |
paul@212 | 77 | sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); |
paul@212 | 78 | sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time); |
paul@212 | 79 | /* if journal backup is for a valid extent-based journal... */ |
paul@212 | 80 | if (ext2fs_extent_header_verify(sb->s_jnl_blocks, |
paul@212 | 81 | sizeof(sb->s_jnl_blocks)) == 0) { |
paul@212 | 82 | /* ... swap only the journal i_size and i_size_high, |
paul@212 | 83 | * and the extent data is not swapped on read */ |
paul@212 | 84 | i = 15; |
paul@212 | 85 | } else { |
paul@212 | 86 | /* direct/indirect journal: swap it all */ |
paul@212 | 87 | i = 0; |
paul@212 | 88 | } |
paul@212 | 89 | for (; i < 17; i++) |
paul@212 | 90 | sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); |
paul@212 | 91 | sb->s_blocks_count_hi = ext2fs_swab32(sb->s_blocks_count_hi); |
paul@212 | 92 | sb->s_r_blocks_count_hi = ext2fs_swab32(sb->s_r_blocks_count_hi); |
paul@212 | 93 | sb->s_free_blocks_hi = ext2fs_swab32(sb->s_free_blocks_hi); |
paul@212 | 94 | sb->s_min_extra_isize = ext2fs_swab16(sb->s_min_extra_isize); |
paul@212 | 95 | sb->s_want_extra_isize = ext2fs_swab16(sb->s_want_extra_isize); |
paul@212 | 96 | sb->s_flags = ext2fs_swab32(sb->s_flags); |
paul@212 | 97 | sb->s_raid_stride = ext2fs_swab16(sb->s_raid_stride); |
paul@212 | 98 | sb->s_mmp_update_interval = ext2fs_swab16(sb->s_mmp_update_interval); |
paul@212 | 99 | sb->s_mmp_block = ext2fs_swab64(sb->s_mmp_block); |
paul@212 | 100 | sb->s_raid_stripe_width = ext2fs_swab32(sb->s_raid_stripe_width); |
paul@212 | 101 | /* sb->s_log_groups_per_flex is __u8 and does not need swabbing */ |
paul@212 | 102 | /* sb->s_checksum_type is __u8 and does not need swabbing */ |
paul@212 | 103 | /* sb->s_encryption_level is __u8 and does not need swabbing */ |
paul@212 | 104 | /* sb->s_reserved_pad is __u8 and does not need swabbing */ |
paul@212 | 105 | sb->s_kbytes_written = ext2fs_swab64(sb->s_kbytes_written); |
paul@212 | 106 | sb->s_snapshot_inum = ext2fs_swab32(sb->s_snapshot_inum); |
paul@212 | 107 | sb->s_snapshot_id = ext2fs_swab32(sb->s_snapshot_id); |
paul@212 | 108 | sb->s_snapshot_r_blocks_count = |
paul@212 | 109 | ext2fs_swab64(sb->s_snapshot_r_blocks_count); |
paul@212 | 110 | sb->s_snapshot_list = ext2fs_swab32(sb->s_snapshot_list); |
paul@212 | 111 | sb->s_error_count = ext2fs_swab32(sb->s_error_count); |
paul@212 | 112 | sb->s_first_error_time = ext2fs_swab32(sb->s_first_error_time); |
paul@212 | 113 | sb->s_first_error_ino = ext2fs_swab32(sb->s_first_error_ino); |
paul@212 | 114 | sb->s_first_error_block = ext2fs_swab64(sb->s_first_error_block); |
paul@212 | 115 | /* sb->s_first_error_func is __u8 and does not need swabbing */ |
paul@212 | 116 | sb->s_last_error_time = ext2fs_swab32(sb->s_last_error_time); |
paul@212 | 117 | sb->s_last_error_ino = ext2fs_swab32(sb->s_last_error_ino); |
paul@212 | 118 | sb->s_last_error_block = ext2fs_swab64(sb->s_last_error_block); |
paul@212 | 119 | /* sb->s_last_error_func is __u8 and does not need swabbing */ |
paul@212 | 120 | /* sb->s_mount_opts is __u8 and does not need swabbing */ |
paul@212 | 121 | sb->s_usr_quota_inum = ext2fs_swab32(sb->s_usr_quota_inum); |
paul@212 | 122 | sb->s_grp_quota_inum = ext2fs_swab32(sb->s_grp_quota_inum); |
paul@212 | 123 | sb->s_overhead_clusters = ext2fs_swab32(sb->s_overhead_clusters); |
paul@212 | 124 | sb->s_backup_bgs[0] = ext2fs_swab32(sb->s_backup_bgs[0]); |
paul@212 | 125 | sb->s_backup_bgs[1] = ext2fs_swab32(sb->s_backup_bgs[1]); |
paul@212 | 126 | /* sb->s_encrypt_algos is __u8 and does not need swabbing */ |
paul@212 | 127 | /* sb->s_encrypt_pw_salt is __u8 and does not need swabbing */ |
paul@212 | 128 | sb->s_lpf_ino = ext2fs_swab32(sb->s_lpf_ino); |
paul@212 | 129 | sb->s_prj_quota_inum = ext2fs_swab32(sb->s_prj_quota_inum); |
paul@212 | 130 | sb->s_checksum_seed = ext2fs_swab32(sb->s_checksum_seed); |
paul@212 | 131 | /* s_*_time_hi are __u8 and does not need swabbing */ |
paul@212 | 132 | sb->s_encoding = ext2fs_swab16(sb->s_encoding); |
paul@212 | 133 | sb->s_encoding_flags = ext2fs_swab16(sb->s_encoding_flags); |
paul@212 | 134 | /* catch when new fields are used from s_reserved */ |
paul@212 | 135 | EXT2FS_BUILD_BUG_ON(sizeof(sb->s_reserved) != 95 * sizeof(__le32)); |
paul@212 | 136 | sb->s_checksum = ext2fs_swab32(sb->s_checksum); |
paul@212 | 137 | } |
paul@212 | 138 | |
paul@212 | 139 | void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp) |
paul@212 | 140 | { |
paul@212 | 141 | struct ext4_group_desc *gdp4 = (struct ext4_group_desc *)gdp; |
paul@212 | 142 | |
paul@212 | 143 | /* Do the 32-bit parts first */ |
paul@212 | 144 | gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap); |
paul@212 | 145 | gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap); |
paul@212 | 146 | gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table); |
paul@212 | 147 | gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count); |
paul@212 | 148 | gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count); |
paul@212 | 149 | gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); |
paul@212 | 150 | gdp->bg_flags = ext2fs_swab16(gdp->bg_flags); |
paul@212 | 151 | gdp->bg_exclude_bitmap_lo = ext2fs_swab32(gdp->bg_exclude_bitmap_lo); |
paul@212 | 152 | gdp->bg_block_bitmap_csum_lo = |
paul@212 | 153 | ext2fs_swab16(gdp->bg_block_bitmap_csum_lo); |
paul@212 | 154 | gdp->bg_inode_bitmap_csum_lo = |
paul@212 | 155 | ext2fs_swab16(gdp->bg_inode_bitmap_csum_lo); |
paul@212 | 156 | gdp->bg_itable_unused = ext2fs_swab16(gdp->bg_itable_unused); |
paul@212 | 157 | gdp->bg_checksum = ext2fs_swab16(gdp->bg_checksum); |
paul@212 | 158 | /* If we're 32-bit, we're done */ |
paul@212 | 159 | if (fs == NULL || EXT2_DESC_SIZE(fs->super) < EXT2_MIN_DESC_SIZE_64BIT) |
paul@212 | 160 | return; |
paul@212 | 161 | |
paul@212 | 162 | /* Swap the 64-bit parts */ |
paul@212 | 163 | gdp4->bg_block_bitmap_hi = ext2fs_swab32(gdp4->bg_block_bitmap_hi); |
paul@212 | 164 | gdp4->bg_inode_bitmap_hi = ext2fs_swab32(gdp4->bg_inode_bitmap_hi); |
paul@212 | 165 | gdp4->bg_inode_table_hi = ext2fs_swab32(gdp4->bg_inode_table_hi); |
paul@212 | 166 | gdp4->bg_free_blocks_count_hi = |
paul@212 | 167 | ext2fs_swab16(gdp4->bg_free_blocks_count_hi); |
paul@212 | 168 | gdp4->bg_free_inodes_count_hi = |
paul@212 | 169 | ext2fs_swab16(gdp4->bg_free_inodes_count_hi); |
paul@212 | 170 | gdp4->bg_used_dirs_count_hi = |
paul@212 | 171 | ext2fs_swab16(gdp4->bg_used_dirs_count_hi); |
paul@212 | 172 | gdp4->bg_itable_unused_hi = ext2fs_swab16(gdp4->bg_itable_unused_hi); |
paul@212 | 173 | gdp4->bg_exclude_bitmap_hi = ext2fs_swab16(gdp4->bg_exclude_bitmap_hi); |
paul@212 | 174 | gdp4->bg_block_bitmap_csum_hi = |
paul@212 | 175 | ext2fs_swab16(gdp4->bg_block_bitmap_csum_hi); |
paul@212 | 176 | gdp4->bg_inode_bitmap_csum_hi = |
paul@212 | 177 | ext2fs_swab16(gdp4->bg_inode_bitmap_csum_hi); |
paul@212 | 178 | EXT2FS_BUILD_BUG_ON(sizeof(gdp4->bg_reserved) != sizeof(__u32)); |
paul@212 | 179 | } |
paul@212 | 180 | |
paul@212 | 181 | void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) |
paul@212 | 182 | { |
paul@212 | 183 | ext2fs_swap_group_desc2(0, gdp); |
paul@212 | 184 | } |
paul@212 | 185 | |
paul@212 | 186 | |
paul@212 | 187 | void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header, |
paul@212 | 188 | struct ext2_ext_attr_header *from_header) |
paul@212 | 189 | { |
paul@212 | 190 | int n; |
paul@212 | 191 | |
paul@212 | 192 | to_header->h_magic = ext2fs_swab32(from_header->h_magic); |
paul@212 | 193 | to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); |
paul@212 | 194 | to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); |
paul@212 | 195 | to_header->h_hash = ext2fs_swab32(from_header->h_hash); |
paul@212 | 196 | to_header->h_checksum = ext2fs_swab32(from_header->h_checksum); |
paul@212 | 197 | for (n = 0; n < 3; n++) |
paul@212 | 198 | to_header->h_reserved[n] = |
paul@212 | 199 | ext2fs_swab32(from_header->h_reserved[n]); |
paul@212 | 200 | } |
paul@212 | 201 | |
paul@212 | 202 | void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry, |
paul@212 | 203 | struct ext2_ext_attr_entry *from_entry) |
paul@212 | 204 | { |
paul@212 | 205 | to_entry->e_value_offs = ext2fs_swab16(from_entry->e_value_offs); |
paul@212 | 206 | to_entry->e_value_inum = ext2fs_swab32(from_entry->e_value_inum); |
paul@212 | 207 | to_entry->e_value_size = ext2fs_swab32(from_entry->e_value_size); |
paul@212 | 208 | to_entry->e_hash = ext2fs_swab32(from_entry->e_hash); |
paul@212 | 209 | } |
paul@212 | 210 | |
paul@212 | 211 | void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) |
paul@212 | 212 | { |
paul@212 | 213 | struct ext2_ext_attr_header *from_header = |
paul@212 | 214 | (struct ext2_ext_attr_header *)from; |
paul@212 | 215 | struct ext2_ext_attr_header *to_header = |
paul@212 | 216 | (struct ext2_ext_attr_header *)to; |
paul@212 | 217 | struct ext2_ext_attr_entry *from_entry, *to_entry; |
paul@212 | 218 | char *from_end = (char *)from_header + bufsize; |
paul@212 | 219 | |
paul@212 | 220 | if (to_header != from_header) |
paul@212 | 221 | memcpy(to_header, from_header, bufsize); |
paul@212 | 222 | |
paul@212 | 223 | if (has_header) { |
paul@212 | 224 | ext2fs_swap_ext_attr_header(to_header, from_header); |
paul@212 | 225 | |
paul@212 | 226 | from_entry = (struct ext2_ext_attr_entry *)(from_header+1); |
paul@212 | 227 | to_entry = (struct ext2_ext_attr_entry *)(to_header+1); |
paul@212 | 228 | } else { |
paul@212 | 229 | from_entry = (struct ext2_ext_attr_entry *)from_header; |
paul@212 | 230 | to_entry = (struct ext2_ext_attr_entry *)to_header; |
paul@212 | 231 | } |
paul@212 | 232 | |
paul@212 | 233 | while ((char *)from_entry < from_end && |
paul@212 | 234 | (char *)EXT2_EXT_ATTR_NEXT(from_entry) <= from_end && |
paul@212 | 235 | *(__u32 *)from_entry) { |
paul@212 | 236 | ext2fs_swap_ext_attr_entry(to_entry, from_entry); |
paul@212 | 237 | from_entry = EXT2_EXT_ATTR_NEXT(from_entry); |
paul@212 | 238 | to_entry = EXT2_EXT_ATTR_NEXT(to_entry); |
paul@212 | 239 | } |
paul@212 | 240 | } |
paul@212 | 241 | |
paul@212 | 242 | void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, |
paul@212 | 243 | struct ext2_inode_large *f, int hostorder, |
paul@212 | 244 | int bufsize) |
paul@212 | 245 | { |
paul@212 | 246 | unsigned i, extra_isize, attr_magic; |
paul@212 | 247 | int has_extents, has_inline_data, islnk, fast_symlink; |
paul@212 | 248 | unsigned int inode_size; |
paul@212 | 249 | __u32 *eaf, *eat; |
paul@212 | 250 | |
paul@212 | 251 | /* |
paul@212 | 252 | * Note that t and f may point to the same address. That's why |
paul@212 | 253 | * if (hostorder) condition is executed before swab calls and |
paul@212 | 254 | * if (!hostorder) afterwards. |
paul@212 | 255 | */ |
paul@212 | 256 | if (hostorder) { |
paul@212 | 257 | islnk = LINUX_S_ISLNK(f->i_mode); |
paul@212 | 258 | fast_symlink = ext2fs_is_fast_symlink(EXT2_INODE(f)); |
paul@212 | 259 | has_extents = (f->i_flags & EXT4_EXTENTS_FL) != 0; |
paul@212 | 260 | has_inline_data = (f->i_flags & EXT4_INLINE_DATA_FL) != 0; |
paul@212 | 261 | } |
paul@212 | 262 | |
paul@212 | 263 | t->i_mode = ext2fs_swab16(f->i_mode); |
paul@212 | 264 | t->i_uid = ext2fs_swab16(f->i_uid); |
paul@212 | 265 | t->i_size = ext2fs_swab32(f->i_size); |
paul@212 | 266 | t->i_atime = ext2fs_swab32(f->i_atime); |
paul@212 | 267 | t->i_ctime = ext2fs_swab32(f->i_ctime); |
paul@212 | 268 | t->i_mtime = ext2fs_swab32(f->i_mtime); |
paul@212 | 269 | t->i_dtime = ext2fs_swab32(f->i_dtime); |
paul@212 | 270 | t->i_gid = ext2fs_swab16(f->i_gid); |
paul@212 | 271 | t->i_links_count = ext2fs_swab16(f->i_links_count); |
paul@212 | 272 | t->i_file_acl = ext2fs_swab32(f->i_file_acl); |
paul@212 | 273 | t->i_blocks = ext2fs_swab32(f->i_blocks); |
paul@212 | 274 | t->i_flags = ext2fs_swab32(f->i_flags); |
paul@212 | 275 | t->i_size_high = ext2fs_swab32(f->i_size_high); |
paul@212 | 276 | |
paul@212 | 277 | if (!hostorder) { |
paul@212 | 278 | islnk = LINUX_S_ISLNK(t->i_mode); |
paul@212 | 279 | fast_symlink = ext2fs_is_fast_symlink(EXT2_INODE(t)); |
paul@212 | 280 | has_extents = (t->i_flags & EXT4_EXTENTS_FL) != 0; |
paul@212 | 281 | has_inline_data = (t->i_flags & EXT4_INLINE_DATA_FL) != 0; |
paul@212 | 282 | } |
paul@212 | 283 | |
paul@212 | 284 | /* |
paul@212 | 285 | * Extent data and inline data are swapped on access, not here |
paul@212 | 286 | */ |
paul@212 | 287 | if (!has_extents && !has_inline_data && (!islnk || !fast_symlink)) { |
paul@212 | 288 | for (i = 0; i < EXT2_N_BLOCKS; i++) |
paul@212 | 289 | t->i_block[i] = ext2fs_swab32(f->i_block[i]); |
paul@212 | 290 | } else if (t != f) { |
paul@212 | 291 | for (i = 0; i < EXT2_N_BLOCKS; i++) |
paul@212 | 292 | t->i_block[i] = f->i_block[i]; |
paul@212 | 293 | } |
paul@212 | 294 | t->i_generation = ext2fs_swab32(f->i_generation); |
paul@212 | 295 | t->i_faddr = ext2fs_swab32(f->i_faddr); |
paul@212 | 296 | |
paul@212 | 297 | switch (fs->super->s_creator_os) { |
paul@212 | 298 | case EXT2_OS_LINUX: |
paul@212 | 299 | t->osd1.linux1.l_i_version = |
paul@212 | 300 | ext2fs_swab32(f->osd1.linux1.l_i_version); |
paul@212 | 301 | t->osd2.linux2.l_i_blocks_hi = |
paul@212 | 302 | ext2fs_swab16(f->osd2.linux2.l_i_blocks_hi); |
paul@212 | 303 | t->osd2.linux2.l_i_file_acl_high = |
paul@212 | 304 | ext2fs_swab16(f->osd2.linux2.l_i_file_acl_high); |
paul@212 | 305 | t->osd2.linux2.l_i_uid_high = |
paul@212 | 306 | ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); |
paul@212 | 307 | t->osd2.linux2.l_i_gid_high = |
paul@212 | 308 | ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); |
paul@212 | 309 | t->osd2.linux2.l_i_checksum_lo = |
paul@212 | 310 | ext2fs_swab16(f->osd2.linux2.l_i_checksum_lo); |
paul@212 | 311 | break; |
paul@212 | 312 | case EXT2_OS_HURD: |
paul@212 | 313 | t->osd1.hurd1.h_i_translator = |
paul@212 | 314 | ext2fs_swab32 (f->osd1.hurd1.h_i_translator); |
paul@212 | 315 | t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; |
paul@212 | 316 | t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; |
paul@212 | 317 | t->osd2.hurd2.h_i_mode_high = |
paul@212 | 318 | ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); |
paul@212 | 319 | t->osd2.hurd2.h_i_uid_high = |
paul@212 | 320 | ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); |
paul@212 | 321 | t->osd2.hurd2.h_i_gid_high = |
paul@212 | 322 | ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); |
paul@212 | 323 | t->osd2.hurd2.h_i_author = |
paul@212 | 324 | ext2fs_swab32 (f->osd2.hurd2.h_i_author); |
paul@212 | 325 | break; |
paul@212 | 326 | default: |
paul@212 | 327 | break; |
paul@212 | 328 | } |
paul@212 | 329 | |
paul@212 | 330 | if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) |
paul@212 | 331 | return; /* no i_extra_isize field */ |
paul@212 | 332 | |
paul@212 | 333 | if (hostorder) |
paul@212 | 334 | extra_isize = f->i_extra_isize; |
paul@212 | 335 | t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); |
paul@212 | 336 | if (!hostorder) |
paul@212 | 337 | extra_isize = t->i_extra_isize; |
paul@212 | 338 | if (extra_isize > EXT2_INODE_SIZE(fs->super) - |
paul@212 | 339 | sizeof(struct ext2_inode)) { |
paul@212 | 340 | /* this is error case: i_extra_size is too large */ |
paul@212 | 341 | return; |
paul@212 | 342 | } |
paul@212 | 343 | if (extra_isize & 3) |
paul@212 | 344 | return; /* Illegal inode extra_isize */ |
paul@212 | 345 | |
paul@212 | 346 | inode_size = EXT2_GOOD_OLD_INODE_SIZE + extra_isize; |
paul@212 | 347 | if (inode_includes(inode_size, i_checksum_hi)) |
paul@212 | 348 | t->i_checksum_hi = ext2fs_swab16(f->i_checksum_hi); |
paul@212 | 349 | if (inode_includes(inode_size, i_ctime_extra)) |
paul@212 | 350 | t->i_ctime_extra = ext2fs_swab32(f->i_ctime_extra); |
paul@212 | 351 | if (inode_includes(inode_size, i_mtime_extra)) |
paul@212 | 352 | t->i_mtime_extra = ext2fs_swab32(f->i_mtime_extra); |
paul@212 | 353 | if (inode_includes(inode_size, i_atime_extra)) |
paul@212 | 354 | t->i_atime_extra = ext2fs_swab32(f->i_atime_extra); |
paul@212 | 355 | if (inode_includes(inode_size, i_crtime)) |
paul@212 | 356 | t->i_crtime = ext2fs_swab32(f->i_crtime); |
paul@212 | 357 | if (inode_includes(inode_size, i_crtime_extra)) |
paul@212 | 358 | t->i_crtime_extra = ext2fs_swab32(f->i_crtime_extra); |
paul@212 | 359 | if (inode_includes(inode_size, i_version_hi)) |
paul@212 | 360 | t->i_version_hi = ext2fs_swab32(f->i_version_hi); |
paul@212 | 361 | if (inode_includes(inode_size, i_projid)) |
paul@212 | 362 | t->i_projid = ext2fs_swab32(f->i_projid); |
paul@212 | 363 | /* catch new static fields added after i_projid */ |
paul@212 | 364 | EXT2FS_BUILD_BUG_ON(sizeof(struct ext2_inode_large) != 160); |
paul@212 | 365 | |
paul@212 | 366 | i = sizeof(struct ext2_inode) + extra_isize + sizeof(__u32); |
paul@212 | 367 | if (bufsize < (int) i) |
paul@212 | 368 | return; /* no space for EA magic */ |
paul@212 | 369 | |
paul@212 | 370 | eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + |
paul@212 | 371 | extra_isize); |
paul@212 | 372 | |
paul@212 | 373 | attr_magic = *eaf; |
paul@212 | 374 | if (!hostorder) |
paul@212 | 375 | attr_magic = ext2fs_swab32(attr_magic); |
paul@212 | 376 | |
paul@212 | 377 | if (attr_magic != EXT2_EXT_ATTR_MAGIC) |
paul@212 | 378 | return; /* it seems no magic here */ |
paul@212 | 379 | |
paul@212 | 380 | eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + |
paul@212 | 381 | extra_isize); |
paul@212 | 382 | *eat = ext2fs_swab32(*eaf); |
paul@212 | 383 | |
paul@212 | 384 | /* convert EA(s) */ |
paul@212 | 385 | ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), |
paul@212 | 386 | bufsize - sizeof(struct ext2_inode) - |
paul@212 | 387 | extra_isize - sizeof(__u32), 0); |
paul@212 | 388 | |
paul@212 | 389 | } |
paul@212 | 390 | |
paul@212 | 391 | void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, |
paul@212 | 392 | struct ext2_inode *f, int hostorder) |
paul@212 | 393 | { |
paul@212 | 394 | ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, |
paul@212 | 395 | (struct ext2_inode_large *) f, hostorder, |
paul@212 | 396 | sizeof(struct ext2_inode)); |
paul@212 | 397 | } |
paul@212 | 398 | |
paul@212 | 399 | void ext2fs_swap_mmp(struct mmp_struct *mmp) |
paul@212 | 400 | { |
paul@212 | 401 | mmp->mmp_magic = ext2fs_swab32(mmp->mmp_magic); |
paul@212 | 402 | mmp->mmp_seq = ext2fs_swab32(mmp->mmp_seq); |
paul@212 | 403 | mmp->mmp_time = ext2fs_swab64(mmp->mmp_time); |
paul@212 | 404 | mmp->mmp_check_interval = ext2fs_swab16(mmp->mmp_check_interval); |
paul@212 | 405 | mmp->mmp_checksum = ext2fs_swab32(mmp->mmp_checksum); |
paul@212 | 406 | } |
paul@212 | 407 | |
paul@212 | 408 | errcode_t ext2fs_dirent_swab_in(ext2_filsys fs, char *buf, int flags) |
paul@212 | 409 | { |
paul@212 | 410 | return ext2fs_dirent_swab_in2(fs, buf, fs->blocksize, flags); |
paul@212 | 411 | } |
paul@212 | 412 | |
paul@212 | 413 | errcode_t ext2fs_dirent_swab_in2(ext2_filsys fs, char *buf, |
paul@212 | 414 | size_t size, int flags) |
paul@212 | 415 | { |
paul@212 | 416 | errcode_t retval; |
paul@212 | 417 | char *p, *end; |
paul@212 | 418 | struct ext2_dir_entry *dirent; |
paul@212 | 419 | unsigned int name_len, rec_len, left; |
paul@212 | 420 | |
paul@212 | 421 | p = (char *) buf; |
paul@212 | 422 | end = (char *) buf + size; |
paul@212 | 423 | left = size; |
paul@212 | 424 | while (p < end-8) { |
paul@212 | 425 | dirent = (struct ext2_dir_entry *) p; |
paul@212 | 426 | dirent->inode = ext2fs_swab32(dirent->inode); |
paul@212 | 427 | dirent->rec_len = ext2fs_swab16(dirent->rec_len); |
paul@212 | 428 | dirent->name_len = ext2fs_swab16(dirent->name_len); |
paul@212 | 429 | name_len = dirent->name_len; |
paul@212 | 430 | if (flags & EXT2_DIRBLOCK_V2_STRUCT) |
paul@212 | 431 | dirent->name_len = ext2fs_swab16(dirent->name_len); |
paul@212 | 432 | retval = ext2fs_get_rec_len(fs, dirent, &rec_len); |
paul@212 | 433 | if (retval) |
paul@212 | 434 | return retval; |
paul@212 | 435 | if ((rec_len < 8) || (rec_len % 4)) { |
paul@212 | 436 | rec_len = 8; |
paul@212 | 437 | retval = EXT2_ET_DIR_CORRUPTED; |
paul@212 | 438 | } else if (((name_len & 0xFF) + 8) > rec_len) |
paul@212 | 439 | retval = EXT2_ET_DIR_CORRUPTED; |
paul@212 | 440 | if (rec_len > left) |
paul@212 | 441 | return EXT2_ET_DIR_CORRUPTED; |
paul@212 | 442 | left -= rec_len; |
paul@212 | 443 | p += rec_len; |
paul@212 | 444 | } |
paul@212 | 445 | |
paul@212 | 446 | return 0; |
paul@212 | 447 | } |
paul@212 | 448 | |
paul@212 | 449 | errcode_t ext2fs_dirent_swab_out(ext2_filsys fs, char *buf, int flags) |
paul@212 | 450 | { |
paul@212 | 451 | return ext2fs_dirent_swab_out2(fs, buf, fs->blocksize, flags); |
paul@212 | 452 | } |
paul@212 | 453 | |
paul@212 | 454 | errcode_t ext2fs_dirent_swab_out2(ext2_filsys fs, char *buf, |
paul@212 | 455 | size_t size, int flags) |
paul@212 | 456 | { |
paul@212 | 457 | errcode_t retval; |
paul@212 | 458 | char *p, *end; |
paul@212 | 459 | unsigned int rec_len; |
paul@212 | 460 | struct ext2_dir_entry *dirent; |
paul@212 | 461 | |
paul@212 | 462 | p = buf; |
paul@212 | 463 | end = buf + size; |
paul@212 | 464 | while (p < end) { |
paul@212 | 465 | dirent = (struct ext2_dir_entry *) p; |
paul@212 | 466 | retval = ext2fs_get_rec_len(fs, dirent, &rec_len); |
paul@212 | 467 | if (retval) |
paul@212 | 468 | return retval; |
paul@212 | 469 | if ((rec_len < 8) || |
paul@212 | 470 | (rec_len % 4)) { |
paul@212 | 471 | ext2fs_free_mem(&buf); |
paul@212 | 472 | return EXT2_ET_DIR_CORRUPTED; |
paul@212 | 473 | } |
paul@212 | 474 | p += rec_len; |
paul@212 | 475 | dirent->inode = ext2fs_swab32(dirent->inode); |
paul@212 | 476 | dirent->rec_len = ext2fs_swab16(dirent->rec_len); |
paul@212 | 477 | dirent->name_len = ext2fs_swab16(dirent->name_len); |
paul@212 | 478 | if (rec_len > size) |
paul@212 | 479 | return EXT2_ET_DIR_CORRUPTED; |
paul@212 | 480 | size -= rec_len; |
paul@212 | 481 | |
paul@212 | 482 | if (flags & EXT2_DIRBLOCK_V2_STRUCT) |
paul@212 | 483 | dirent->name_len = ext2fs_swab16(dirent->name_len); |
paul@212 | 484 | } |
paul@212 | 485 | |
paul@212 | 486 | return 0; |
paul@212 | 487 | } |