blob: 64d4775a086b45455a4c9ca11eaf92d3d4c45252 [file] [log] [blame]
Theodore Ts'o1e3472c1997-04-29 14:53:37 +00001/*
2 * swapfs.c --- byte-swap an ext2 filesystem
Theodore Ts'o21c84b71997-04-29 16:15:03 +00003 *
4 * Copyright 1996, 1997 by Theodore Ts'o
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 *
Theodore Ts'o1e3472c1997-04-29 14:53:37 +000011 */
12
13#ifdef HAVE_ERRNO_H
14#include <errno.h>
15#endif
16#include <et/com_err.h>
17#include "e2fsck.h"
18
19struct swap_block_struct {
20 ino_t ino;
21 int isdir;
22 errcode_t errcode;
23 char *dir_buf;
24 struct ext2_inode *inode;
25};
26
27/*
28 * This is a helper function for block_iterate. We mark all of the
29 * indirect and direct blocks as changed, so that block_iterate will
30 * write them out.
31 */
32static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
33 void *private)
34{
35 errcode_t retval;
36
37 struct swap_block_struct *sb = (struct swap_block_struct *) private;
38
39 if (sb->isdir && (blockcnt >= 0) && *block_nr) {
40 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
41 if (retval) {
42 sb->errcode = retval;
43 return BLOCK_ABORT;
44 }
45 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
46 if (retval) {
47 sb->errcode = retval;
48 return BLOCK_ABORT;
49 }
50 }
51 if (blockcnt >= 0) {
52 if (blockcnt < EXT2_NDIR_BLOCKS)
53 return 0;
54 return BLOCK_CHANGED;
55 }
56 if (blockcnt == BLOCK_COUNT_IND) {
57 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
58 return 0;
59 return BLOCK_CHANGED;
60 }
61 if (blockcnt == BLOCK_COUNT_DIND) {
62 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
63 return 0;
64 return BLOCK_CHANGED;
65 }
66 if (blockcnt == BLOCK_COUNT_TIND) {
67 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
68 return 0;
69 return BLOCK_CHANGED;
70 }
71 return BLOCK_CHANGED;
72}
73
74/*
75 * This function is responsible for byte-swapping all of the indirect,
76 * block pointers. It is also responsible for byte-swapping directories.
77 */
78static void swap_inode_blocks(ext2_filsys fs, ino_t ino, char *block_buf,
79 struct ext2_inode *inode)
80{
81 errcode_t retval;
82 struct swap_block_struct sb;
83
84 sb.ino = ino;
85 sb.inode = inode;
86 sb.dir_buf = block_buf + fs->blocksize*3;
87 sb.errcode = 0;
88 sb.isdir = 0;
89 if (LINUX_S_ISDIR(inode->i_mode))
90 sb.isdir = 1;
91
92 retval = ext2fs_block_iterate(fs, ino, 0, block_buf, swap_block, &sb);
93 if (retval) {
94 com_err("swap_inode_blocks", retval,
95 "while calling ext2fs_block_iterate");
96 fatal_error(0);
97 }
98 if (sb.errcode) {
99 com_err("swap_inode_blocks", sb.errcode,
100 "while calling iterator function");
101 fatal_error(0);
102 }
103}
104
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000105static void swap_inodes(e2fsck_t ctx)
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000106{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000107 ext2_filsys fs = ctx->fs;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000108 int i, group;
109 ino_t ino = 1;
110 char *buf, *block_buf;
111 errcode_t retval;
112 struct ext2_inode * inode;
113
114 fs->read_inode = pass1_read_inode;
115 fs->get_blocks = pass1_get_blocks;
116
117
118 buf = malloc(fs->blocksize * fs->inode_blocks_per_group);
119 if (!buf) {
120 com_err("swap_inodes", ENOMEM,
121 "while allocating inode buffer");
122 fatal_error(0);
123 }
124 block_buf = allocate_memory(fs->blocksize * 4,
125 "block interate buffer");
126 for (group = 0; group < fs->group_desc_count; group++) {
127 retval = io_channel_read_blk(fs->io,
128 fs->group_desc[group].bg_inode_table,
129 fs->inode_blocks_per_group, buf);
130 if (retval) {
131 com_err("swap_inodes", retval,
132 "while reading inode table (group %d)",
133 group);
134 fatal_error(0);
135 }
136 inode = (struct ext2_inode *) buf;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000137 for (i=0; i < fs->super->s_inodes_per_group;
138 i++, ino++, inode++) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000139 ctx->stashed_ino = ino;
140 ctx->stashed_inode = inode;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000141
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000142 if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
143 ext2fs_swap_inode(fs, inode, inode, 0);
144
145 /*
146 * Skip deleted files.
147 */
148 if (inode->i_links_count == 0)
149 continue;
150
151 if (LINUX_S_ISDIR(inode->i_mode) ||
152 ((inode->i_block[EXT2_IND_BLOCK] ||
153 inode->i_block[EXT2_DIND_BLOCK] ||
154 inode->i_block[EXT2_TIND_BLOCK]) &&
155 ext2fs_inode_has_valid_blocks(inode)))
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000156 swap_inode_blocks(fs, ino, block_buf, inode);
157
Theodore Ts'o5c576471997-04-29 15:29:49 +0000158 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000159 ext2fs_swap_inode(fs, inode, inode, 1);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000160 }
161 retval = io_channel_write_blk(fs->io,
162 fs->group_desc[group].bg_inode_table,
163 fs->inode_blocks_per_group, buf);
164 if (retval) {
165 com_err("swap_inodes", retval,
166 "while writing inode table (group %d)",
167 group);
168 fatal_error(0);
169 }
170 }
171 free(buf);
172 free(block_buf);
173 fs->read_inode = 0;
174 fs->get_blocks = 0;
175}
176
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000177void swap_filesys(e2fsck_t ctx)
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000178{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000179 ext2_filsys fs = ctx->fs;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000180 struct resource_track rtrack;
181
182 init_resource_track(&rtrack);
183
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000184 if (!(ctx->options & E2F_OPT_PREEN))
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000185 printf("Pass 0: Doing byte-swap of filesystem\n");
186
187#ifdef MTRACE
188 mtrace_print("Byte swap");
189#endif
190
191 if (fs->super->s_mnt_count) {
192 fprintf(stderr, "%s: the filesystem must be freshly "
193 "checked using fsck\n"
194 "and not mounted before trying to "
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000195 "byte-swap it.\n", ctx->device_name);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000196 fatal_error(0);
197 }
Theodore Ts'o5c576471997-04-29 15:29:49 +0000198 if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
199 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
200 EXT2_FLAG_SWAP_BYTES_WRITE);
201 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000202 } else {
Theodore Ts'o5c576471997-04-29 15:29:49 +0000203 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
204 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000205 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000206 swap_inodes(ctx);
Theodore Ts'o5c576471997-04-29 15:29:49 +0000207 if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
208 fs->flags |= EXT2_FLAG_SWAP_BYTES;
209 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
210 EXT2_FLAG_SWAP_BYTES_WRITE);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000211 ext2fs_flush(fs);
212
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000213 if (ctx->options & E2F_OPT_TIME2)
214 print_resource_track("Byte swap", &rtrack);
Theodore Ts'o1e3472c1997-04-29 14:53:37 +0000215}
216
217