📄 ufile.c
字号:
/* * Copyright 1996-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */#include "fsck.h"static int do_items_have_the_same_type (struct item_head * ih, struct key * key){ return (get_type (&ih->ih_key) == get_type (key)) ? 1 : 0;}static int are_items_in_the_same_node (struct path * path){ return (PATH_LAST_POSITION (path) < B_NR_ITEMS (PATH_PLAST_BUFFER (path)) - 1) ? 1 : 0;}static void cut_last_unfm_pointer (struct path * path, struct item_head * ih){ set_ih_free_space(ih, 0); if (I_UNFM_NUM (ih) == 1) reiserfsck_delete_item (path, 0); else reiserfsck_cut_from_item (path, -((int)UNFM_P_SIZE));}/* if this is not a symlink - make it of_this_size; otherwise find a size and return it in symlink_size;*/static unsigned long indirect_to_direct (struct path * path, __u64 len, int symlink){ struct buffer_head * bh = PATH_PLAST_BUFFER (path); struct item_head * ih = PATH_PITEM_HEAD (path); __u32 unfm_ptr; struct buffer_head * unfm_bh = 0; struct item_head ins_ih; char * buf; char bad_drct[fs->fs_blocksize]; /* direct item to insert */ memset (&ins_ih, 0, sizeof (ins_ih)); if (symlink) { set_ih_key_format (&ins_ih, KEY_FORMAT_1); } else { set_ih_key_format (&ins_ih, get_ih_key_format (ih)); } set_key_dirid (&ins_ih.ih_key, get_key_dirid (&ih->ih_key)); set_key_objectid (&ins_ih.ih_key, get_key_objectid (&ih->ih_key)); set_type_and_offset (get_ih_key_format (&ins_ih), &ins_ih.ih_key, get_offset (&ih->ih_key) + (I_UNFM_NUM (ih) - 1) * bh->b_size, TYPE_DIRECT); // we do not know what length this item should be unfm_ptr = d32_get ((__u32 *)get_item (path), I_UNFM_NUM (ih) - 1); if (unfm_ptr && (unfm_bh = bread (bh->b_dev, unfm_ptr, bh->b_size))) { /* we can read the block */ buf = unfm_bh->b_data; } else { /* we cannot read the block */ if (unfm_ptr) fsck_log ("indirect_to_direct: Reading of the block (%lu), pointed to by the file %K, failed\n", unfm_ptr, &ih->ih_key); memset (bad_drct, 0, fs->fs_blocksize); buf = bad_drct; }/* if (len > MAX_DIRECT_ITEM_LEN (fs->fs_blocksize)) { fsck_log ("indirect_to_direct: canot create such a long item %d (%K), " "Cutting it down to %d byte\n", len, &ih->ih_key, MAX_DIRECT_ITEM_LEN (fs->fs_blocksize) - 8); len = MAX_DIRECT_ITEM_LEN (fs->fs_blocksize) - 8; } if (!len) { buf = bad_link; len = strlen (bad_link); }*/ set_ih_item_len (&ins_ih, (get_ih_key_format (ih) == KEY_FORMAT_2) ? ROUND_UP(len) : len); set_ih_free_space (&ins_ih, MAX_US_INT); mark_ih_become_tail(ih); mark_buffer_dirty(bh); // last last unformatted node pointer path->pos_in_item = I_UNFM_NUM (ih) - 1; cut_last_unfm_pointer (path, ih); /* insert direct item */ if (reiserfs_search_by_key_4 (fs, &(ins_ih.ih_key), path) == ITEM_FOUND) reiserfs_panic ("indirect_to_direct: The direct item %k should not exist yet.", &(ins_ih.ih_key)); reiserfsck_insert_item (path, &ins_ih, (const char *)(buf)); brelse (unfm_bh); /* put to stat data offset of first byte in direct item */ return get_offset (&ins_ih.ih_key); //offset;}/* start_key is the key after which N items need to be deleted save_here is a pointer where deleted items need to be saved if save is set. start_key is the first undeleted item. return whether we are sure there is nothing else of this file */int delete_N_items_after_key(struct key * start_key, struct si ** save_here, int skip_dir_items, int n_to_delete) { struct path path;// struct key key = *start_key; struct key * rkey; int count = 0; while (1) { reiserfs_search_by_key_4 (fs, start_key, &path); if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) { rkey = uget_rkey (&path); if (rkey && !not_of_one_file (start_key, rkey)) { /* file continues in the right neighbor */ copy_key (start_key, rkey); pathrelse (&path); continue; } /* there is no more items with this key */ pathrelse (&path); return 1; } if (is_stat_data_ih (get_ih(&path))) fix_obviously_wrong_sd_mode (&path); rkey = &(get_ih (&path))->ih_key; if (not_of_one_file (start_key, rkey)) { /* there are no more item with this key */ pathrelse (&path); return 1; } copy_key (start_key, rkey); /* ok, item found, but make sure that it is not a directory one */ if ((is_stat_data_key (rkey) && !not_a_directory (get_item (&path))) || (is_direntry_key (rkey))) { if (skip_dir_items) { /* item of directory found. Leave it in the tree */ set_offset (KEY_FORMAT_1, start_key, get_offset (start_key) + 1); pathrelse (&path); continue; } else { reiserfs_panic ("delete_N_items_after_key: No directory item of %K are " "expected", start_key); } } if (save_here != NULL) *save_here = save_and_delete_file_item (*save_here, &path); else reiserfsck_delete_item (&path, 0); count++; if (count == n_to_delete) break; pathrelse (&path); } return 0;}/* returns 1 when file looks correct, -1 if directory items appeared there, 0 - only holes in the file found *//* when it returns, key->k_offset is offset of the last item of file *//* sd_size is zero if we do not need to convert any indirect to direct */int are_file_items_correct (struct item_head * sd_ih, void * sd, __u64 * size, __u32 * blocks, int mark_passed_items, int * symlink){ struct path path; struct item_head * ih; struct key * next_key, * key; __u32 sd_first_direct_byte = 0; __u64 sd_size; unsigned int i; int retval, was_tail = 0; int had_direct = 0; int key_version = get_ih_key_format (sd_ih); int next_is_another_object = 0; __u64 last_unfm_offset = 0; int will_convert = 0; int should_convert; should_convert = (fsck_mode (fs) != FSCK_REBUILD) || mark_passed_items; key = &sd_ih->ih_key; get_sd_size (sd_ih, sd, &sd_size); if (key_version == KEY_FORMAT_1) get_sd_first_direct_byte (sd_ih, sd, &sd_first_direct_byte); set_offset (key_version, key, 1); set_type (key_version, key, TYPE_DIRECT); /* correct size and st_blocks */ *size = 0; *blocks = 0; path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET; do { retval = usearch_by_position (fs, key, key_version, &path); if (retval == POSITION_FOUND && path.pos_in_item != 0) die ("are_file_items_correct: All bytes we look for must be first items byte (position 0)."); switch (retval) { case POSITION_FOUND:/**/ ih = PATH_PITEM_HEAD (&path); if (ih_was_tail (ih)) { was_tail = 1; } set_type (key_version, key, get_type (&ih->ih_key)); if (mark_passed_items == 1) { mark_item_reachable (ih, PATH_PLAST_BUFFER (&path)); } // does not change path next_key = reiserfs_next_key(&path); if (next_key == 0 || not_of_one_file (key, next_key) || (!is_indirect_key (next_key) && !is_direct_key(next_key))) { next_is_another_object = 1; will_convert = (is_indirect_ih (ih) && sd_size && (I_UNFM_NUM (ih) > 0)); if (will_convert) { last_unfm_offset = get_offset (key) + fs->fs_blocksize * (I_UNFM_NUM (ih) - 1); /* if symlink or [ 1. sd_size points somewhere into last unfm block 2. one item of the file was direct before for 3_6 || FDB points to the tail correctly for 3_5 3. we can have a tail in the file of a such size ] */ will_convert = will_convert && (sd_size >= last_unfm_offset) && (sd_size < last_unfm_offset + fs->fs_blocksize) && !STORE_TAIL_IN_UNFM (sd_size, sd_size - last_unfm_offset + 1, fs->fs_blocksize); will_convert = will_convert && (*symlink || ((key_version == KEY_FORMAT_1) && (sd_first_direct_byte == last_unfm_offset)) || ((key_version == KEY_FORMAT_2) && was_tail)); } } if (should_convert) { *symlink = *symlink && (will_convert || is_direct_key(&ih->ih_key)); if (!(*symlink) && key_version != get_ih_key_format (ih)) { if (fsck_mode(fs) == FSCK_CHECK) { fsck_log("are_file_items_correct: vpf-10250: block %lu, item (%d): The item format (%H)"\ " is not equal to SD format (%d)\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, key_version); one_more_corruption (fs, FIXABLE); } else { fsck_log("are_file_items_correct: vpf-10280: block %lu, item (%d): The item format (%H)"\ " is not equal to SD format (%d) - fixed.\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, key_version); set_type_and_offset (key_version, &ih->ih_key, get_offset (&ih->ih_key), get_type (&ih->ih_key)); set_ih_key_format(ih, key_version); mark_buffer_dirty(get_bh(&path)); } } if (*symlink && is_direct_key(&ih->ih_key)) { /* symlink. Check that it is of KEY_FORMAT_1 */ if (fsck_mode(fs) == FSCK_CHECK) { if ((get_ih_key_format(ih) != KEY_FORMAT_1) || (key_format(&ih->ih_key) != KEY_FORMAT_1)) { fsck_log("are_file_items_correct: vpf-10732: block %lu, item (%d): The symlink format (%H)"\ " is not equal to 3.5 format (%d)\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, KEY_FORMAT_1); one_more_corruption (fs, FIXABLE); } } else { if ((get_ih_key_format(ih) != KEY_FORMAT_1) || (key_format(&ih->ih_key) != KEY_FORMAT_1)) { fsck_log("are_file_items_correct: vpf-10732: block %lu, item (%d): The symlink format (%H)"\ " is not equal to 3.5 format (%d)\n", get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, KEY_FORMAT_1); set_type_and_offset(KEY_FORMAT_1, &ih->ih_key, get_offset(&ih->ih_key), get_type(&ih->ih_key)); set_ih_key_format(ih, KEY_FORMAT_1); mark_buffer_dirty(get_bh(&path)); } } } if (will_convert) *size = sd_size; else *size = get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize) - 1; if (get_type (&ih->ih_key) == TYPE_INDIRECT) { if (*symlink) /* symlinks must be calculated as dirs */ *blocks = dir_size2st_blocks (*size); else for (i = 0; i < I_UNFM_NUM (ih); i ++) { __u32 * ind = (__u32 *)get_item(&path); if (d32_get(ind, i) != 0) *blocks += (fs->fs_blocksize >> 9); } } else if (get_type (&ih->ih_key) == TYPE_DIRECT) { if (*symlink) /* symlinks must be calculated as dirs */ *blocks = dir_size2st_blocks (*size); else if (!had_direct) *blocks += (fs->fs_blocksize >> 9); /* calculate only the first direct byte */ had_direct++; } } if (next_is_another_object) { /* next item does not exists or is of another object, therefore all items of file are correct */ if (will_convert) { if (fsck_mode (fs) == FSCK_CHECK) { /* here it can be symlink only */ fsck_log ("are_file_items_correct: The indirect item should be converted back" " to direct %K\n", &ih->ih_key); one_more_corruption (fs, FIXABLE); pathrelse (&path); } else { __u32 * ind = (__u32 *)get_item(&path); /* DEBUG message. fsck_log ("are_file_items_correct: The indirect item is converted back to direct %K\n", &ih->ih_key); */ if (d32_get(ind, I_UNFM_NUM (ih) - 1) == 0) *blocks += (fs->fs_blocksize >> 9); /* path is released here. */ sd_first_direct_byte = indirect_to_direct (&path, sd_size - last_unfm_offset + 1, *symlink); /* last item of the file is direct item */ set_offset (key_version, key, sd_first_direct_byte); set_type (key_version, key, TYPE_DIRECT); } } else pathrelse (&path); return 1; } /* next item is item of this file */ if (get_offset (&ih->ih_key) + get_bytes_number(ih, fs->fs_blocksize) != get_offset (next_key)) { /* next item has incorrect offset (hole or overlapping) */ pathrelse (&path); return 0; } if (do_items_have_the_same_type (ih, next_key) == 1 && are_items_in_the_same_node (&path) == 1) { /* two indirect items or two direct items in the same leaf. FIXME: Second will be deleted */ pathrelse (&path); return 0; } /* items are of different types or are in different nodes *//* if (get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize) != get_offset (next_key)) { // indirect item free space is not set properly if (!is_indirect_ih (ih) ) //|| get_ih_free_space(ih) == 0) fsck_log ("are_file_items_correct: " "item must be indirect and must have invalid free space (%H)", ih); if (fsck_mode (fs) == FSCK_REBUILD) { set_ih_free_space(ih, 0); mark_buffer_dirty (PATH_PLAST_BUFFER (&path)); } }*/ /* next item exists */ set_type_and_offset(key_version, key, get_offset (next_key), get_type(next_key)); if (comp_keys (key, next_key)) reiserfs_panic ("are_file_items_correct: Internal tree is in inconsistent state, " "the current item key %K and the next key %K must match", key, next_key); pathrelse (&path); break; case POSITION_NOT_FOUND: /* We always must have next key found. Exception is first byte. It does not have to exist */ if (get_offset (key) != 1) reiserfs_panic ("are_file_items_correct: Position (offset == %llu) in the middle of" "the file %K was not found.", get_offset(key), key); pathrelse (&path); return 0; case FILE_NOT_FOUND: if (get_offset (key) != 1) reiserfs_panic ("are_file_items_correct: File %K must be found as we found its StatData.", key); pathrelse (&path); return 1; case DIRECTORY_FOUND: pathrelse (&path); return -1; } } while (1); die ("are_file_items_correct: Cannot reach here"); return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -