blob: 50865c14f5982683de4e89663a72ba8108cad26b [file] [log] [blame]
Theodore Ts'o3839e651997-04-26 13:21:57 +00001/*
2 * pass1b.c --- Pass #1b of e2fsck
3 *
4 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are
5 * only invoked if pass 1 discovered blocks which are in use by more
6 * than one inode.
7 *
8 * Pass1B scans the data blocks of all the inodes again, generating a
9 * complete list of duplicate blocks and which inodes have claimed
10 * them.
11 *
12 * Pass1C does a tree-traversal of the filesystem, to determine the
13 * parent directories of these inodes. This step is necessary so that
14 * e2fsck can print out the pathnames of affected inodes.
15 *
16 * Pass1D is a reconciliation pass. For each inode with duplicate
17 * blocks, the user is prompted if s/he would like to clone the file
18 * (so that the file gets a fresh copy of the duplicated blocks) or
19 * simply to delete the file.
20 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +000021 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
22 *
23 * %Begin-Header%
24 * This file may be redistributed under the terms of the GNU Public
25 * License.
26 * %End-Header%
Theodore Ts'o3839e651997-04-26 13:21:57 +000027 *
28 */
29
30#include <time.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000031#ifdef HAVE_ERRNO_H
32#include <errno.h>
33#endif
Theodore Ts'o3839e651997-04-26 13:21:57 +000034
35#include <et/com_err.h>
36#include "e2fsck.h"
37
Theodore Ts'o21c84b71997-04-29 16:15:03 +000038#include "problem.h"
39
Theodore Ts'o3839e651997-04-26 13:21:57 +000040/*
41 * This is structure is allocated for each time that a block is
42 * claimed by more than one file. So if a particular block is claimed
43 * by 3 files, then three copies of this structure will be allocated,
44 * one for each conflict.
45 *
46 * The linked list structure is as follows:
47 *
48 * dup_blk --> block #34 --> block #35 --> block #47
49 * inode #12 inode #14 inode #17
50 * num_bad = 3 num_bad = 2 num_bad = 2
51 * | | |
52 * V V V
53 * block #34 block #35 block #47
54 * inode #14 inode #15 inode #23
55 * |
56 * V
57 * block #34
58 * inode #15
59 *
60 * The num_bad field indicates how many inodes are sharing a
61 * particular block, and is only stored in the first element of the
62 * linked list for a particular block. As the block conflicts are
63 * resolved, num_bad is decremented; when it reaches 1, then we no
64 * longer need to worry about that block.
65 */
66struct dup_block {
67 blk_t block; /* Block number */
68 ino_t ino; /* Inode number */
69 int num_bad;
70 /* Pointer to next dup record with different block */
71 struct dup_block *next_block;
72 /* Pointer to next dup record with different inode */
73 struct dup_block *next_inode;
74};
75
76/*
77 * This structure stores information about a particular inode which
78 * is sharing blocks with other inodes. This information is collected
79 * to display to the user, so that the user knows what files he or she
80 * is dealing with, when trying to decide how to resolve the conflict
81 * of multiply-claimed blocks.
82 */
83struct dup_inode {
Theodore Ts'o21c84b71997-04-29 16:15:03 +000084 ino_t ino, dir;
85 int num_dupblocks;
86 struct ext2_inode inode;
Theodore Ts'o3839e651997-04-26 13:21:57 +000087 struct dup_inode *next;
88};
89
Theodore Ts'o3839e651997-04-26 13:21:57 +000090static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr,
91 int blockcnt, void *private);
92static void delete_file(ext2_filsys fs, struct dup_inode *dp,
93 char *block_buf);
94static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf);
95static void pass1b(ext2_filsys fs, char *block_buf);
96static void pass1c(ext2_filsys fs, char *block_buf);
97static void pass1d(ext2_filsys fs, char *block_buf);
98
99static struct dup_block *dup_blk = 0;
100static struct dup_inode *dup_ino = 0;
101static int dup_inode_count = 0;
102
Theodore Ts'of3db3561997-04-26 13:34:30 +0000103static ext2fs_inode_bitmap inode_dup_map;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000104
105/*
106 * Main procedure for handling duplicate blocks
107 */
108void pass1_dupblocks(ext2_filsys fs, char *block_buf)
109{
110 errcode_t retval;
111 struct dup_block *p, *q, *next_p, *next_q;
112 struct dup_inode *r, *next_r;
113
Theodore Ts'of3db3561997-04-26 13:34:30 +0000114 retval = ext2fs_allocate_inode_bitmap(fs,
115 "multiply claimed inode map", &inode_dup_map);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000116 if (retval) {
117 com_err("ext2fs_allocate_inode_bitmap", retval,
118 "while allocating inode_dup_map");
119 fatal_error(0);
120 }
121
122 pass1b(fs, block_buf);
123 pass1c(fs, block_buf);
124 pass1d(fs, block_buf);
125
126 /*
127 * Time to free all of the accumulated data structures that we
128 * don't need anymore.
129 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000130 ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000131 ext2fs_free_block_bitmap(block_dup_map); block_dup_map = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000132 for (p = dup_blk; p; p = next_p) {
133 next_p = p->next_block;
134 for (q = p; q; q = next_q) {
135 next_q = q->next_inode;
136 free(q);
137 }
138 }
139 for (r = dup_ino; r; r = next_r) {
140 next_r = r->next;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000141 free(r);
142 }
143}
144
145/*
146 * Scan the inodes looking for inodes that contain duplicate blocks.
147 */
148struct process_block_struct {
149 ino_t ino;
150 int dup_blocks;
151};
152
153void pass1b(ext2_filsys fs, char *block_buf)
154{
155 ino_t ino;
156 struct ext2_inode inode;
157 ext2_inode_scan scan;
158 errcode_t retval;
159 struct process_block_struct pb;
160 struct dup_inode *dp;
161
162 printf("Duplicate blocks found... invoking duplicate block passes.\n");
163 printf("Pass 1B: Rescan for duplicate/bad blocks\n");
164 retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan);
165 if (retval) {
166 com_err(program_name, retval, "while opening inode scan");
167 fatal_error(0);
168 }
169 retval = ext2fs_get_next_inode(scan, &ino, &inode);
170 if (retval) {
171 com_err(program_name, retval, "while starting inode scan");
172 fatal_error(0);
173 }
174 stashed_inode = &inode;
175 while (ino) {
176 stashed_ino = ino;
177 if ((ino != EXT2_BAD_INO) &&
Theodore Ts'of3db3561997-04-26 13:34:30 +0000178 (!ext2fs_test_inode_bitmap(inode_used_map, ino) ||
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000179 !ext2fs_inode_has_valid_blocks(&inode)))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000180 goto next;
181
182 pb.ino = ino;
183 pb.dup_blocks = 0;
184 retval = ext2fs_block_iterate(fs, ino, 0, block_buf,
185 process_pass1b_block, &pb);
186 if (pb.dup_blocks) {
187 if (ino != EXT2_BAD_INO)
188 printf("\n");
189 dp = allocate_memory(sizeof(struct dup_inode),
190 "duplicate inode record");
191 dp->ino = ino;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000192 dp->dir = 0;
193 dp->inode = inode;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000194 dp->num_dupblocks = pb.dup_blocks;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000195 dp->next = dup_ino;
196 dup_ino = dp;
197 if (ino != EXT2_BAD_INO)
198 dup_inode_count++;
199 }
200 if (retval)
201 com_err(program_name, retval,
202 "while calling ext2fs_block_iterate in pass1b");
203
204 next:
205 retval = ext2fs_get_next_inode(scan, &ino, &inode);
206 if (retval) {
207 com_err(program_name, retval,
208 "while doing inode scan");
209 fatal_error(0);
210 }
211 }
212 ext2fs_close_inode_scan(scan);
213 fs->get_blocks = 0;
214 fs->check_directory = 0;
215}
216
217int process_pass1b_block(ext2_filsys fs,
218 blk_t *block_nr,
219 int blockcnt,
220 void *private)
221{
222 struct process_block_struct *p;
223 struct dup_block *dp, *q, *r;
224 int i;
225
226 if (!*block_nr)
227 return 0;
228 p = (struct process_block_struct *) private;
229
Theodore Ts'of3db3561997-04-26 13:34:30 +0000230 if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000231 /* OK, this is a duplicate block */
232 if (p->ino != EXT2_BAD_INO) {
233 if (!p->dup_blocks)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000234 printf("Duplicate/bad block(s) in inode %lu:",
Theodore Ts'o3839e651997-04-26 13:21:57 +0000235 p->ino);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000236 printf(" %u", *block_nr);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000237 }
238 p->dup_blocks++;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000239 ext2fs_mark_block_bitmap(block_dup_map, *block_nr);
240 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000241 dp = allocate_memory(sizeof(struct dup_block),
242 "duplicate block record");
243 dp->block = *block_nr;
244 dp->ino = p->ino;
245 dp->num_bad = 0;
246 q = dup_blk;
247 while (q) {
248 if (q->block == *block_nr)
249 break;
250 q = q->next_block;
251 }
252 if (q) {
253 dp->next_inode = q->next_inode;
254 q->next_inode = dp;
255 } else {
256 dp->next_block = dup_blk;
257 dup_blk = dp;
258 }
259 }
260 /*
261 * Set the num_bad field
262 */
263 for (q = dup_blk; q; q = q->next_block) {
264 i = 0;
265 for (r = q; r; r = r->next_inode)
266 i++;
267 q->num_bad = i;
268 }
269 return 0;
270}
271
272/*
Theodore Ts'o3839e651997-04-26 13:21:57 +0000273 * Pass 1c: Scan directories for inodes with duplicate blocks. This
274 * is used so that we can print pathnames when prompting the user for
275 * what to do.
276 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000277struct search_dir_struct {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000278 int count;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000279 ino_t first_inode;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000280 ino_t max_inode;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000281};
282
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000283static int search_dirent_proc(ino_t dir, int entry,
284 struct ext2_dir_entry *dirent,
285 int offset, int blocksize,
286 char *buf, void *private)
287{
288 struct search_dir_struct *sd = private;
289 struct dup_inode *p;
290
Theodore Ts'o521e3681997-04-29 17:48:10 +0000291 if (dirent->inode > sd->max_inode)
292 /* Should abort this inode, but not everything */
293 return 0;
294
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000295 if (!dirent->inode || (entry < DIRENT_OTHER_FILE) ||
296 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
297 return 0;
298
299 for (p = dup_ino; p; p = p->next) {
300 if ((p->ino >= sd->first_inode) &&
301 (p->ino == dirent->inode))
302 break;
303 }
304
305 if (!p || p->dir)
306 return 0;
307
308 p->dir = dir;
309 sd->count--;
310
311 return(sd->count ? 0 : DIRENT_ABORT);
312}
313
314
Theodore Ts'o3839e651997-04-26 13:21:57 +0000315void pass1c(ext2_filsys fs, char *block_buf)
316{
Theodore Ts'o3839e651997-04-26 13:21:57 +0000317 struct dup_inode *p;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000318 int inodes_left = dup_inode_count;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000319 struct search_dir_struct sd;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000320
321 printf("Pass 1C: Scan directories for inodes with dup blocks.\n");
322
323 /*
324 * First check to see if any of the inodes with dup blocks is
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000325 * a special inode. (Note that the bad block inode isn't
326 * counted.)
Theodore Ts'o3839e651997-04-26 13:21:57 +0000327 */
328 for (p = dup_ino; p; p = p->next) {
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000329 if ((p->ino < EXT2_FIRST_INODE(fs->super)) &&
330 (p->ino != EXT2_BAD_INO))
Theodore Ts'o3839e651997-04-26 13:21:57 +0000331 inodes_left--;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000332 }
333
334 /*
335 * Search through all directories to translate inodes to names
336 * (by searching for the containing directory for that inode.)
337 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000338 sd.count = inodes_left;
339 sd.first_inode = EXT2_FIRST_INODE(fs->super);
Theodore Ts'o521e3681997-04-29 17:48:10 +0000340 sd.max_inode = fs->super->s_inodes_count;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000341 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
342 search_dirent_proc, &sd);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000343}
344
345static void pass1d(ext2_filsys fs, char *block_buf)
346{
347 struct dup_inode *p, *s;
348 struct dup_block *q, *r;
349 ino_t *shared;
350 int shared_len;
351 int i;
352 errcode_t retval;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000353 int file_ok;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000354 int meta_data = 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000355 struct problem_context pctx;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000356
357 printf("Pass 1D: Reconciling duplicate blocks\n");
358 read_bitmaps(fs);
359
360 printf("(There are %d inodes containing duplicate/bad blocks.)\n\n",
361 dup_inode_count);
362 shared = allocate_memory(sizeof(ino_t) * dup_inode_count,
363 "Shared inode list");
364 for (p = dup_ino; p; p = p->next) {
365 shared_len = 0;
366 file_ok = 1;
367 if (p->ino == EXT2_BAD_INO)
368 continue;
369
370 /*
371 * Search through the duplicate records to see which
372 * inodes share blocks with this one
373 */
374 for (q = dup_blk; q; q = q->next_block) {
375 /*
376 * See if this block is used by this inode.
377 * If it isn't, continue.
378 */
379 for (r = q; r; r = r->next_inode)
380 if (r->ino == p->ino)
381 break;
382 if (!r)
383 continue;
384 if (q->num_bad > 1)
385 file_ok = 0;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000386 if (ext2fs_test_block_bitmap(block_illegal_map,
387 q->block)) {
388 file_ok = 0;
389 meta_data = 1;
390 }
391
Theodore Ts'o3839e651997-04-26 13:21:57 +0000392 /*
393 * Add all inodes used by this block to the
394 * shared[] --- which is a unique list, so
395 * if an inode is already in shared[], don't
396 * add it again.
397 */
398 for (r = q; r; r = r->next_inode) {
399 if (r->ino == p->ino)
400 continue;
401 for (i = 0; i < shared_len; i++)
402 if (shared[i] == r->ino)
403 break;
404 if (i == shared_len) {
405 shared[shared_len++] = r->ino;
406 }
407 }
408 }
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000409
410 /*
411 * Report the inode that we are working on
412 */
413 clear_problem_context(&pctx);
414 pctx.inode = &p->inode;
415 pctx.ino = p->ino;
416 pctx.dir = p->dir;
417 pctx.blkcount = p->num_dupblocks;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000418 pctx.num = meta_data ? shared_len+1 : shared_len;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000419 fix_problem(fs, PR_1B_DUP_FILE, &pctx);
420 pctx.blkcount = 0;
421 pctx.num = 0;
422
Theodore Ts'o521e3681997-04-29 17:48:10 +0000423 if (meta_data)
424 fix_problem(fs, PR_1B_SHARE_METADATA, &pctx);
425
Theodore Ts'o3839e651997-04-26 13:21:57 +0000426 for (i = 0; i < shared_len; i++) {
427 for (s = dup_ino; s; s = s->next)
428 if (s->ino == shared[i])
429 break;
430 if (!s)
431 continue;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000432 /*
433 * Report the inode that we are sharing with
434 */
435 pctx.inode = &s->inode;
436 pctx.ino = s->ino;
437 pctx.dir = s->dir;
438 fix_problem(fs, PR_1B_DUP_FILE_LIST, &pctx);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000439 }
440 if (file_ok) {
441 printf("Duplicated blocks already reassigned or cloned.\n\n");
442 continue;
443 }
444
445 if (ask("Clone duplicate/bad blocks", 1)) {
446 retval = clone_file(fs, p, block_buf);
447 if (retval)
448 printf("Couldn't clone file: %s\n",
449 error_message(retval));
450 else {
451 printf("\n");
452 continue;
453 }
454 }
455 if (ask("Delete file", 1))
456 delete_file(fs, p, block_buf);
457 else
458 ext2fs_unmark_valid(fs);
459 printf("\n");
460 }
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000461 free(shared);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000462}
463
464static int delete_file_block(ext2_filsys fs,
465 blk_t *block_nr,
466 int blockcnt,
467 void *private)
468{
469 struct dup_block *p;
470
471 if (!*block_nr)
472 return 0;
473
Theodore Ts'of3db3561997-04-26 13:34:30 +0000474 if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000475 for (p = dup_blk; p; p = p->next_block)
476 if (p->block == *block_nr)
477 break;
478 if (p) {
479 p->num_bad--;
480 if (p->num_bad == 1)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000481 ext2fs_unmark_block_bitmap(block_dup_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000482 *block_nr);
483 } else
484 com_err("delete_file_block", 0,
485 "internal error; can't find dup_blk for %d\n",
486 *block_nr);
487 } else {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000488 ext2fs_unmark_block_bitmap(block_found_map, *block_nr);
489 ext2fs_unmark_block_bitmap(fs->block_map, *block_nr);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000490 }
491
492 return 0;
493}
494
495static void delete_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
496{
497 errcode_t retval;
498 struct process_block_struct pb;
499 struct ext2_inode inode;
500
501 pb.ino = dp->ino;
502 pb.dup_blocks = dp->num_dupblocks;
503
504 retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
505 delete_file_block, &pb);
506 if (retval)
507 com_err("delete_file", retval,
508 "while calling ext2fs_block_iterate for inode %d",
509 dp->ino);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000510 ext2fs_unmark_inode_bitmap(inode_used_map, dp->ino);
511 ext2fs_unmark_inode_bitmap(inode_dir_map, dp->ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000512 if (inode_bad_map)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000513 ext2fs_unmark_inode_bitmap(inode_bad_map, dp->ino);
514 ext2fs_unmark_inode_bitmap(fs->inode_map, dp->ino);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000515 ext2fs_mark_ib_dirty(fs);
516 ext2fs_mark_bb_dirty(fs);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000517 e2fsck_read_inode(fs, dp->ino, &inode, "delete_file");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000518 inode.i_links_count = 0;
519 inode.i_dtime = time(0);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000520 e2fsck_write_inode(fs, dp->ino, &inode, "delete_file");
Theodore Ts'o3839e651997-04-26 13:21:57 +0000521}
522
523struct clone_struct {
524 errcode_t errcode;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000525 ino_t dir;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000526 char *buf;
527};
528
529static int clone_file_block(ext2_filsys fs,
530 blk_t *block_nr,
531 int blockcnt,
532 void *private)
533{
534 struct dup_block *p;
535 blk_t new_block;
536 errcode_t retval;
537 struct clone_struct *cs = (struct clone_struct *) private;
538
539 if (!*block_nr)
540 return 0;
541
Theodore Ts'of3db3561997-04-26 13:34:30 +0000542 if (ext2fs_test_block_bitmap(block_dup_map, *block_nr)) {
Theodore Ts'o3839e651997-04-26 13:21:57 +0000543 for (p = dup_blk; p; p = p->next_block)
544 if (p->block == *block_nr)
545 break;
546 if (p) {
547 retval = ext2fs_new_block(fs, 0, block_found_map,
548 &new_block);
549 if (retval) {
550 cs->errcode = retval;
551 return BLOCK_ABORT;
552 }
Theodore Ts'o521e3681997-04-29 17:48:10 +0000553 if (cs->dir) {
554 retval = ext2fs_set_dir_block(fs->dblist,
555 cs->dir, new_block, blockcnt);
556 if (retval) {
557 cs->errcode = retval;
558 return BLOCK_ABORT;
559 }
560 }
Theodore Ts'o3839e651997-04-26 13:21:57 +0000561 retval = io_channel_read_blk(fs->io, *block_nr, 1,
562 cs->buf);
563 if (retval) {
564 cs->errcode = retval;
565 return BLOCK_ABORT;
566 }
567 retval = io_channel_write_blk(fs->io, new_block, 1,
568 cs->buf);
569 if (retval) {
570 cs->errcode = retval;
571 return BLOCK_ABORT;
572 }
573 p->num_bad--;
574 if (p->num_bad == 1)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000575 ext2fs_unmark_block_bitmap(block_dup_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000576 *block_nr);
577 *block_nr = new_block;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000578 ext2fs_mark_block_bitmap(block_found_map,
Theodore Ts'o3839e651997-04-26 13:21:57 +0000579 new_block);
Theodore Ts'of3db3561997-04-26 13:34:30 +0000580 ext2fs_mark_block_bitmap(fs->block_map, new_block);
Theodore Ts'o3839e651997-04-26 13:21:57 +0000581 return BLOCK_CHANGED;
582 } else
583 com_err("clone_file_block", 0,
584 "internal error; can't find dup_blk for %d\n",
585 *block_nr);
586 }
587 return 0;
588}
589
590static int clone_file(ext2_filsys fs, struct dup_inode *dp, char* block_buf)
591{
592 errcode_t retval;
593 struct clone_struct cs;
594
595 cs.errcode = 0;
596 cs.buf = malloc(fs->blocksize);
Theodore Ts'o521e3681997-04-29 17:48:10 +0000597 cs.dir = 0;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000598 if (!cs.buf)
599 return ENOMEM;
Theodore Ts'o521e3681997-04-29 17:48:10 +0000600
601 if (ext2fs_test_inode_bitmap(inode_dir_map, dp->ino))
602 cs.dir = dp->ino;
Theodore Ts'o3839e651997-04-26 13:21:57 +0000603
604 retval = ext2fs_block_iterate(fs, dp->ino, 0, block_buf,
605 clone_file_block, &cs);
606 ext2fs_mark_bb_dirty(fs);
607 free(cs.buf);
608 if (retval) {
609 com_err("clone_file", retval,
610 "while calling ext2fs_block_iterate for inode %d",
611 dp->ino);
612 return retval;
613 }
614 if (cs.errcode) {
615 com_err("clone_file", retval,
616 "returned from clone_file_block");
617 return retval;
618 }
619 return 0;
620}
621
622
623
624
625