]>
Commit | Line | Data |
---|---|---|
50e1e10f TT |
1 | /* |
2 | * swapfs.c --- swap ext2 filesystem data structures | |
efc6f628 | 3 | * |
8132d840 | 4 | * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. |
19c78dc0 TT |
5 | * |
6 | * %Begin-Header% | |
543547a5 TT |
7 | * This file may be redistributed under the terms of the GNU Library |
8 | * General Public License, version 2. | |
19c78dc0 | 9 | * %End-Header% |
50e1e10f TT |
10 | */ |
11 | ||
12 | #include <stdio.h> | |
4cbe8af4 | 13 | #if HAVE_UNISTD_H |
50e1e10f | 14 | #include <unistd.h> |
4cbe8af4 | 15 | #endif |
7331196a | 16 | #include <string.h> |
50e1e10f TT |
17 | #include <time.h> |
18 | ||
b5abe6fa | 19 | #include "ext2_fs.h" |
50e1e10f | 20 | #include "ext2fs.h" |
7331196a | 21 | #include <ext2fs/ext2_ext_attr.h> |
50e1e10f | 22 | |
a5dda054 | 23 | #ifdef WORDS_BIGENDIAN |
e5b38a5f | 24 | void ext2fs_swap_super(struct ext2_super_block * sb) |
50e1e10f | 25 | { |
8132d840 | 26 | int i; |
e5b38a5f TT |
27 | sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); |
28 | sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); | |
29 | sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); | |
30 | sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count); | |
31 | sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count); | |
32 | sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block); | |
33 | sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size); | |
412376ef | 34 | sb->s_log_cluster_size = ext2fs_swab32(sb->s_log_cluster_size); |
e5b38a5f | 35 | sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group); |
412376ef | 36 | sb->s_clusters_per_group = ext2fs_swab32(sb->s_clusters_per_group); |
e5b38a5f TT |
37 | sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group); |
38 | sb->s_mtime = ext2fs_swab32(sb->s_mtime); | |
39 | sb->s_wtime = ext2fs_swab32(sb->s_wtime); | |
40 | sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count); | |
41 | sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count); | |
42 | sb->s_magic = ext2fs_swab16(sb->s_magic); | |
43 | sb->s_state = ext2fs_swab16(sb->s_state); | |
44 | sb->s_errors = ext2fs_swab16(sb->s_errors); | |
45 | sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level); | |
46 | sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck); | |
47 | sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval); | |
48 | sb->s_creator_os = ext2fs_swab32(sb->s_creator_os); | |
49 | sb->s_rev_level = ext2fs_swab32(sb->s_rev_level); | |
50 | sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid); | |
51 | sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid); | |
52 | sb->s_first_ino = ext2fs_swab32(sb->s_first_ino); | |
53 | sb->s_inode_size = ext2fs_swab16(sb->s_inode_size); | |
54 | sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr); | |
55 | sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat); | |
56 | sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat); | |
57 | sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat); | |
58 | sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap); | |
5d28e3be | 59 | sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks); |
e5b38a5f TT |
60 | sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); |
61 | sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); | |
62 | sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); | |
8061d2c1 | 63 | sb->s_desc_size = ext2fs_swab16(sb->s_desc_size); |
1ba7a2f2 | 64 | sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts); |
c046ac7f | 65 | sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); |
1ba7a2f2 | 66 | sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time); |
6b3ce987 TT |
67 | sb->s_blocks_count_hi = ext2fs_swab32(sb->s_blocks_count_hi); |
68 | sb->s_r_blocks_count_hi = ext2fs_swab32(sb->s_r_blocks_count_hi); | |
69 | sb->s_free_blocks_hi = ext2fs_swab32(sb->s_free_blocks_hi); | |
70 | sb->s_min_extra_isize = ext2fs_swab16(sb->s_min_extra_isize); | |
71 | sb->s_want_extra_isize = ext2fs_swab16(sb->s_want_extra_isize); | |
f77704e4 | 72 | sb->s_flags = ext2fs_swab32(sb->s_flags); |
b7c5b403 | 73 | sb->s_kbytes_written = ext2fs_swab64(sb->s_kbytes_written); |
f5448c19 | 74 | sb->s_snapshot_inum = ext2fs_swab32(sb->s_snapshot_inum); |
ccc7cf03 | 75 | sb->s_snapshot_id = ext2fs_swab32(sb->s_snapshot_id); |
f5448c19 TT |
76 | sb->s_snapshot_r_blocks_count = |
77 | ext2fs_swab64(sb->s_snapshot_r_blocks_count); | |
78 | sb->s_snapshot_list = ext2fs_swab32(sb->s_snapshot_list); | |
0edcc270 AK |
79 | sb->s_usr_quota_inum = ext2fs_swab32(sb->s_usr_quota_inum); |
80 | sb->s_grp_quota_inum = ext2fs_swab32(sb->s_grp_quota_inum); | |
89efc88e TT |
81 | sb->s_overhead_blocks = ext2fs_swab32(sb->s_overhead_blocks); |
82 | sb->s_checksum = ext2fs_swab32(sb->s_checksum); | |
f5448c19 | 83 | |
8132d840 TT |
84 | for (i=0; i < 4; i++) |
85 | sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); | |
6eb229dc ES |
86 | |
87 | /* if journal backup is for a valid extent-based journal... */ | |
931b58e1 AD |
88 | if (ext2fs_extent_header_verify(sb->s_jnl_blocks, |
89 | sizeof(sb->s_jnl_blocks)) == 0) { | |
90 | /* ... swap only the journal i_size and i_size_high, | |
91 | * and the extent data is not swapped on read */ | |
92 | i = 15; | |
93 | } else { | |
94 | /* direct/indirect journal: swap it all */ | |
95 | i = 0; | |
6eb229dc | 96 | } |
931b58e1 | 97 | for (; i < 17; i++) |
1ba7a2f2 | 98 | sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); |
50e1e10f TT |
99 | } |
100 | ||
cf828f1a | 101 | void ext2fs_swap_group_desc2(ext2_filsys fs, struct ext2_group_desc *gdp) |
50e1e10f | 102 | { |
cf828f1a | 103 | /* Do the 32-bit parts first */ |
50e1e10f TT |
104 | gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap); |
105 | gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap); | |
106 | gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table); | |
107 | gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count); | |
108 | gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count); | |
109 | gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); | |
f5fa2007 | 110 | gdp->bg_flags = ext2fs_swab16(gdp->bg_flags); |
89efc88e TT |
111 | gdp->bg_exclude_bitmap_lo = ext2fs_swab32(gdp->bg_exclude_bitmap_lo); |
112 | gdp->bg_block_bitmap_csum_lo = | |
113 | ext2fs_swab16(gdp->bg_block_bitmap_csum_lo); | |
114 | gdp->bg_inode_bitmap_csum_lo = | |
115 | ext2fs_swab16(gdp->bg_inode_bitmap_csum_lo); | |
8815fb8a TT |
116 | gdp->bg_itable_unused = ext2fs_swab16(gdp->bg_itable_unused); |
117 | gdp->bg_checksum = ext2fs_swab16(gdp->bg_checksum); | |
cf828f1a | 118 | /* If we're 32-bit, we're done */ |
ccc7cf03 TT |
119 | if (fs && (!fs->super->s_desc_size || |
120 | (fs->super->s_desc_size < EXT2_MIN_DESC_SIZE_64BIT))) | |
cf828f1a TT |
121 | return; |
122 | ||
123 | /* Swap the 64-bit parts */ | |
124 | struct ext4_group_desc *gdp4 = (struct ext4_group_desc *) gdp; | |
125 | gdp4->bg_block_bitmap_hi = ext2fs_swab32(gdp4->bg_block_bitmap_hi); | |
126 | gdp4->bg_inode_bitmap_hi = ext2fs_swab32(gdp4->bg_inode_bitmap_hi); | |
127 | gdp4->bg_inode_table_hi = ext2fs_swab32(gdp4->bg_inode_table_hi); | |
128 | gdp4->bg_free_blocks_count_hi = | |
129 | ext2fs_swab16(gdp4->bg_free_blocks_count_hi); | |
130 | gdp4->bg_free_inodes_count_hi = | |
131 | ext2fs_swab16(gdp4->bg_free_inodes_count_hi); | |
132 | gdp4->bg_used_dirs_count_hi = | |
133 | ext2fs_swab16(gdp4->bg_used_dirs_count_hi); | |
134 | gdp4->bg_itable_unused_hi = ext2fs_swab16(gdp4->bg_itable_unused_hi); | |
89efc88e TT |
135 | gdp->bg_exclude_bitmap_hi = ext2fs_swab16(gdp->bg_exclude_bitmap_hi); |
136 | gdp->bg_block_bitmap_csum_hi = | |
137 | ext2fs_swab16(gdp->bg_block_bitmap_csum_hi); | |
138 | gdp->bg_inode_bitmap_csum_hi = | |
139 | ext2fs_swab16(gdp->bg_inode_bitmap_csum_hi); | |
50e1e10f TT |
140 | } |
141 | ||
cf828f1a TT |
142 | void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) |
143 | { | |
144 | return ext2fs_swap_group_desc2(0, gdp); | |
145 | } | |
146 | ||
147 | ||
fefaef39 AD |
148 | void ext2fs_swap_ext_attr_header(struct ext2_ext_attr_header *to_header, |
149 | struct ext2_ext_attr_header *from_header) | |
150 | { | |
151 | int n; | |
152 | ||
153 | to_header->h_magic = ext2fs_swab32(from_header->h_magic); | |
154 | to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); | |
155 | to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); | |
156 | to_header->h_hash = ext2fs_swab32(from_header->h_hash); | |
157 | for (n = 0; n < 4; n++) | |
158 | to_header->h_reserved[n] = | |
159 | ext2fs_swab32(from_header->h_reserved[n]); | |
160 | } | |
161 | ||
162 | void ext2fs_swap_ext_attr_entry(struct ext2_ext_attr_entry *to_entry, | |
163 | struct ext2_ext_attr_entry *from_entry) | |
164 | { | |
165 | to_entry->e_value_offs = ext2fs_swab16(from_entry->e_value_offs); | |
166 | to_entry->e_value_block = ext2fs_swab32(from_entry->e_value_block); | |
167 | to_entry->e_value_size = ext2fs_swab32(from_entry->e_value_size); | |
168 | to_entry->e_hash = ext2fs_swab32(from_entry->e_hash); | |
169 | } | |
170 | ||
7331196a TT |
171 | void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) |
172 | { | |
173 | struct ext2_ext_attr_header *from_header = | |
174 | (struct ext2_ext_attr_header *)from; | |
175 | struct ext2_ext_attr_header *to_header = | |
176 | (struct ext2_ext_attr_header *)to; | |
177 | struct ext2_ext_attr_entry *from_entry, *to_entry; | |
178 | char *from_end = (char *)from_header + bufsize; | |
7331196a TT |
179 | |
180 | if (to_header != from_header) | |
181 | memcpy(to_header, from_header, bufsize); | |
182 | ||
7331196a | 183 | if (has_header) { |
fefaef39 AD |
184 | ext2fs_swap_ext_attr_header(to_header, from_header); |
185 | ||
7331196a TT |
186 | from_entry = (struct ext2_ext_attr_entry *)(from_header+1); |
187 | to_entry = (struct ext2_ext_attr_entry *)(to_header+1); | |
fefaef39 AD |
188 | } else { |
189 | from_entry = (struct ext2_ext_attr_entry *)from_header; | |
190 | to_entry = (struct ext2_ext_attr_entry *)to_header; | |
7331196a TT |
191 | } |
192 | ||
193 | while ((char *)from_entry < from_end && *(__u32 *)from_entry) { | |
fefaef39 | 194 | ext2fs_swap_ext_attr_entry(to_entry, from_entry); |
7331196a TT |
195 | from_entry = EXT2_EXT_ATTR_NEXT(from_entry); |
196 | to_entry = EXT2_EXT_ATTR_NEXT(to_entry); | |
197 | } | |
198 | } | |
199 | ||
200 | void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, | |
201 | struct ext2_inode_large *f, int hostorder, | |
202 | int bufsize) | |
1e3472c5 | 203 | { |
82e54188 | 204 | unsigned i, has_data_blocks, extra_isize, attr_magic; |
fb6627a3 | 205 | int has_extents = 0; |
1e3472c5 | 206 | int islnk = 0; |
7331196a TT |
207 | __u32 *eaf, *eat; |
208 | ||
1e3472c5 TT |
209 | if (hostorder && LINUX_S_ISLNK(f->i_mode)) |
210 | islnk = 1; | |
211 | t->i_mode = ext2fs_swab16(f->i_mode); | |
212 | if (!hostorder && LINUX_S_ISLNK(t->i_mode)) | |
213 | islnk = 1; | |
214 | t->i_uid = ext2fs_swab16(f->i_uid); | |
215 | t->i_size = ext2fs_swab32(f->i_size); | |
216 | t->i_atime = ext2fs_swab32(f->i_atime); | |
217 | t->i_ctime = ext2fs_swab32(f->i_ctime); | |
218 | t->i_mtime = ext2fs_swab32(f->i_mtime); | |
219 | t->i_dtime = ext2fs_swab32(f->i_dtime); | |
220 | t->i_gid = ext2fs_swab16(f->i_gid); | |
221 | t->i_links_count = ext2fs_swab16(f->i_links_count); | |
db9097ca | 222 | t->i_file_acl = ext2fs_swab32(f->i_file_acl); |
3f4c46e3 | 223 | if (hostorder) |
efc6f628 | 224 | has_data_blocks = ext2fs_inode_data_blocks(fs, |
3f4c46e3 | 225 | (struct ext2_inode *) f); |
1e3472c5 | 226 | t->i_blocks = ext2fs_swab32(f->i_blocks); |
3f4c46e3 | 227 | if (!hostorder) |
efc6f628 | 228 | has_data_blocks = ext2fs_inode_data_blocks(fs, |
3f4c46e3 | 229 | (struct ext2_inode *) t); |
4ce3b774 | 230 | if (hostorder && (f->i_flags & EXT4_EXTENTS_FL)) |
fb6627a3 | 231 | has_extents = 1; |
1e3472c5 | 232 | t->i_flags = ext2fs_swab32(f->i_flags); |
fb6627a3 ES |
233 | if (!hostorder && (t->i_flags & EXT4_EXTENTS_FL)) |
234 | has_extents = 1; | |
1ba7a2f2 | 235 | t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); |
fb6627a3 ES |
236 | /* extent data are swapped on access, not here */ |
237 | if (!has_extents && (!islnk || has_data_blocks)) { | |
1e3472c5 TT |
238 | for (i = 0; i < EXT2_N_BLOCKS; i++) |
239 | t->i_block[i] = ext2fs_swab32(f->i_block[i]); | |
240 | } else if (t != f) { | |
241 | for (i = 0; i < EXT2_N_BLOCKS; i++) | |
242 | t->i_block[i] = f->i_block[i]; | |
243 | } | |
e72a9ba3 | 244 | t->i_generation = ext2fs_swab32(f->i_generation); |
1e3472c5 | 245 | t->i_faddr = ext2fs_swab32(f->i_faddr); |
50e1e10f | 246 | |
1e3472c5 TT |
247 | switch (fs->super->s_creator_os) { |
248 | case EXT2_OS_LINUX: | |
d362a3fb TT |
249 | t->osd1.linux1.l_i_version = |
250 | ext2fs_swab32(f->osd1.linux1.l_i_version); | |
efc6f628 | 251 | t->osd2.linux2.l_i_blocks_hi = |
5d17119d | 252 | ext2fs_swab16(f->osd2.linux2.l_i_blocks_hi); |
2ea504bd AK |
253 | t->osd2.linux2.l_i_file_acl_high = |
254 | ext2fs_swab16(f->osd2.linux2.l_i_file_acl_high); | |
80e808fc TT |
255 | t->osd2.linux2.l_i_uid_high = |
256 | ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); | |
257 | t->osd2.linux2.l_i_gid_high = | |
258 | ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); | |
89efc88e TT |
259 | t->osd2.linux2.l_i_checksum = |
260 | ext2fs_swab32(f->osd2.linux2.checksum); | |
1e3472c5 TT |
261 | break; |
262 | case EXT2_OS_HURD: | |
263 | t->osd1.hurd1.h_i_translator = | |
264 | ext2fs_swab32 (f->osd1.hurd1.h_i_translator); | |
265 | t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; | |
266 | t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; | |
267 | t->osd2.hurd2.h_i_mode_high = | |
268 | ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); | |
269 | t->osd2.hurd2.h_i_uid_high = | |
270 | ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); | |
271 | t->osd2.hurd2.h_i_gid_high = | |
272 | ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); | |
273 | t->osd2.hurd2.h_i_author = | |
274 | ext2fs_swab32 (f->osd2.hurd2.h_i_author); | |
275 | break; | |
c9548bc3 | 276 | default: |
1e3472c5 TT |
277 | break; |
278 | } | |
7331196a TT |
279 | |
280 | if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) | |
281 | return; /* no i_extra_isize field */ | |
282 | ||
c844010c TT |
283 | if (hostorder) |
284 | extra_isize = f->i_extra_isize; | |
7331196a | 285 | t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); |
c844010c TT |
286 | if (!hostorder) |
287 | extra_isize = t->i_extra_isize; | |
288 | if (extra_isize > EXT2_INODE_SIZE(fs->super) - | |
7331196a TT |
289 | sizeof(struct ext2_inode)) { |
290 | /* this is error case: i_extra_size is too large */ | |
291 | return; | |
292 | } | |
293 | ||
c844010c | 294 | i = sizeof(struct ext2_inode) + extra_isize + sizeof(__u32); |
7331196a TT |
295 | if (bufsize < (int) i) |
296 | return; /* no space for EA magic */ | |
297 | ||
298 | eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + | |
c844010c | 299 | extra_isize); |
7331196a | 300 | |
82e54188 ES |
301 | attr_magic = *eaf; |
302 | if (!hostorder) | |
303 | attr_magic = ext2fs_swab32(attr_magic); | |
304 | ||
305 | if (attr_magic != EXT2_EXT_ATTR_MAGIC) | |
7331196a TT |
306 | return; /* it seems no magic here */ |
307 | ||
308 | eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + | |
c844010c | 309 | extra_isize); |
7331196a TT |
310 | *eat = ext2fs_swab32(*eaf); |
311 | ||
312 | /* convert EA(s) */ | |
313 | ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), | |
314 | bufsize - sizeof(struct ext2_inode) - | |
c844010c | 315 | extra_isize - sizeof(__u32), 0); |
7331196a | 316 | |
1e3472c5 | 317 | } |
7331196a TT |
318 | |
319 | void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, | |
320 | struct ext2_inode *f, int hostorder) | |
321 | { | |
322 | ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, | |
323 | (struct ext2_inode_large *) f, hostorder, | |
324 | sizeof(struct ext2_inode)); | |
325 | } | |
326 | ||
5df55d7f | 327 | #endif |