Whamcloud - gitweb
Fix various gcc -Wall complaints.
[tools/e2fsprogs.git] / e2fsck / swapfs.c
1 /*
2  * swapfs.c --- byte-swap an ext2 filesystem
3  *
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  * 
11  */
12
13 #ifdef HAVE_ERRNO_H
14 #include <errno.h>
15 #endif
16 #include <et/com_err.h>
17 #include "e2fsck.h"
18
19 #ifdef ENABLE_SWAPFS
20
21 struct swap_block_struct {
22         ext2_ino_t      ino;
23         int             isdir;
24         errcode_t       errcode;
25         char            *dir_buf;
26         struct ext2_inode *inode;
27 };
28
29 /*
30  * This is a helper function for block_iterate.  We mark all of the
31  * indirect and direct blocks as changed, so that block_iterate will
32  * write them out.
33  */
34 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
35                       void *priv_data)
36 {
37         errcode_t       retval;
38         
39         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
40
41         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
42                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
43                 if (retval) {
44                         sb->errcode = retval;
45                         return BLOCK_ABORT;
46                 }
47                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
48                 if (retval) {
49                         sb->errcode = retval;
50                         return BLOCK_ABORT;
51                 }
52         }
53         if (blockcnt >= 0) {
54                 if (blockcnt < EXT2_NDIR_BLOCKS)
55                         return 0;
56                 return BLOCK_CHANGED;
57         }
58         if (blockcnt == BLOCK_COUNT_IND) {
59                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
60                         return 0;
61                 return BLOCK_CHANGED;
62         }
63         if (blockcnt == BLOCK_COUNT_DIND) {
64                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
65                         return 0;
66                 return BLOCK_CHANGED;
67         }
68         if (blockcnt == BLOCK_COUNT_TIND) {
69                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
70                         return 0;
71                 return BLOCK_CHANGED;
72         }
73         return BLOCK_CHANGED;
74 }
75
76 /*
77  * This function is responsible for byte-swapping all of the indirect,
78  * block pointers.  It is also responsible for byte-swapping directories.
79  */
80 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
81                               struct ext2_inode *inode)
82 {
83         errcode_t                       retval;
84         struct swap_block_struct        sb;
85
86         sb.ino = ino;
87         sb.inode = inode;
88         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
89         sb.errcode = 0;
90         sb.isdir = 0;
91         if (LINUX_S_ISDIR(inode->i_mode))
92                 sb.isdir = 1;
93
94         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
95                                       swap_block, &sb);
96         if (retval) {
97                 com_err("swap_inode_blocks", retval,
98                         _("while calling ext2fs_block_iterate"));
99                 ctx->flags |= E2F_FLAG_ABORT;
100                 return;
101         }
102         if (sb.errcode) {
103                 com_err("swap_inode_blocks", sb.errcode,
104                         _("while calling iterator function"));
105                 ctx->flags |= E2F_FLAG_ABORT;
106                 return;
107         }
108 }
109
110 static void swap_inodes(e2fsck_t ctx)
111 {
112         ext2_filsys fs = ctx->fs;
113         int                     i, group;
114         ext2_ino_t              ino = 1;
115         char                    *buf, *block_buf;
116         errcode_t               retval;
117         struct ext2_inode *     inode;
118
119         e2fsck_use_inode_shortcuts(ctx, 1);
120         
121         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
122                                 (void **) &buf);
123         if (retval) {
124                 com_err("swap_inodes", retval,
125                         _("while allocating inode buffer"));
126                 ctx->flags |= E2F_FLAG_ABORT;
127                 return;
128         }
129         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
130                                                     "block interate buffer");
131         for (group = 0; group < fs->group_desc_count; group++) {
132                 retval = io_channel_read_blk(fs->io,
133                       fs->group_desc[group].bg_inode_table,
134                       fs->inode_blocks_per_group, buf);
135                 if (retval) {
136                         com_err("swap_inodes", retval,
137                                 _("while reading inode table (group %d)"),
138                                 group);
139                         ctx->flags |= E2F_FLAG_ABORT;
140                         return;
141                 }
142                 inode = (struct ext2_inode *) buf;
143                 for (i=0; i < fs->super->s_inodes_per_group;
144                      i++, ino++, inode++) {
145                         ctx->stashed_ino = ino;
146                         ctx->stashed_inode = inode;
147                         
148                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
149                                 ext2fs_swap_inode(fs, inode, inode, 0);
150                         
151                         /*
152                          * Skip deleted files.
153                          */
154                         if (inode->i_links_count == 0)
155                                 continue;
156                         
157                         if (LINUX_S_ISDIR(inode->i_mode) ||
158                             ((inode->i_block[EXT2_IND_BLOCK] ||
159                               inode->i_block[EXT2_DIND_BLOCK] ||
160                               inode->i_block[EXT2_TIND_BLOCK]) &&
161                              ext2fs_inode_has_valid_blocks(inode)))
162                                 swap_inode_blocks(ctx, ino, block_buf, inode);
163
164                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
165                                 return;
166                         
167                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
168                                 ext2fs_swap_inode(fs, inode, inode, 1);
169                 }
170                 retval = io_channel_write_blk(fs->io,
171                       fs->group_desc[group].bg_inode_table,
172                       fs->inode_blocks_per_group, buf);
173                 if (retval) {
174                         com_err("swap_inodes", retval,
175                                 _("while writing inode table (group %d)"),
176                                 group);
177                         ctx->flags |= E2F_FLAG_ABORT;
178                         return;
179                 }
180         }
181         ext2fs_free_mem((void **) &buf);
182         ext2fs_free_mem((void **) &block_buf);
183         e2fsck_use_inode_shortcuts(ctx, 0);
184 }
185
186 void swap_filesys(e2fsck_t ctx)
187 {
188         ext2_filsys fs = ctx->fs;
189 #ifdef RESOURCE_TRACK
190         struct resource_track   rtrack;
191
192         init_resource_track(&rtrack);
193 #endif
194
195         if (!(ctx->options & E2F_OPT_PREEN))
196                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
197         
198 #ifdef MTRACE
199         mtrace_print("Byte swap");
200 #endif
201
202         if (fs->super->s_mnt_count) {
203                 fprintf(stderr, _("%s: the filesystem must be freshly "
204                         "checked using fsck\n"
205                         "and not mounted before trying to "
206                         "byte-swap it.\n"), ctx->device_name);
207                 ctx->flags |= E2F_FLAG_ABORT;
208                 return;
209         }
210         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
211                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
212                                EXT2_FLAG_SWAP_BYTES_WRITE);
213                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
214         } else {
215                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
216                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
217         }
218         swap_inodes(ctx);
219         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
220                 return;
221         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
222                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
223         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
224                        EXT2_FLAG_SWAP_BYTES_WRITE);
225         ext2fs_flush(fs);
226         
227 #ifdef RESOURCE_TRACK
228         if (ctx->options & E2F_OPT_TIME2)
229                 print_resource_track(_("Byte swap"), &rtrack);
230 #endif
231 }
232
233 #endif