📄 semantic_check.c
字号:
/* * Copyright 1996-2004 by Hans Reiser, licensing governed by reiserfsprogs/README */#include "fsck.h"static struct key *trunc_links = NULL;static __u32 links_num = 0;int wrong_mode (struct key * key, __u16 * mode, __u64 real_size, int symlink);int wrong_st_blocks(struct key * key, __u32 * blocks, __u32 sd_blocks, __u16 mode, int new_format);int wrong_st_size (struct key * key, unsigned long long max_file_size, int blocksize, __u64 * size, __u64 sd_size, int type);int wrong_first_direct_byte (struct key * key, int blocksize, __u32 * first_direct_byte, __u32 sd_first_direct_byte, __u32 size);void get_object_key (struct reiserfs_de_head * deh, struct key * key, struct key * entry_key, struct item_head * ih);void print_name (char * name, int len);void erase_name (int len);struct path_key{ struct short_key { __u32 k_dir_id; __u32 k_objectid; } key; struct path_key * next, * prev;};struct path_key * head_key = NULL;struct path_key * tail_key = NULL;static int check_path_key(struct key * key){ struct path_key * cur = head_key; while(cur != NULL) { if (!comp_short_keys(&cur->key, key)) { fsck_log("\nsemantic check: The directory %k has 2 names.", key); return LOOP_FOUND; } cur = cur->next; } return 0;}static int add_path_key(struct key * key){ if (check_path_key(key)) return LOOP_FOUND; if (tail_key == NULL) { tail_key = getmem(sizeof(struct path_key)); head_key = tail_key; tail_key->prev = NULL; }else{ tail_key->next = getmem(sizeof(struct path_key)); tail_key->next->prev = tail_key; tail_key = tail_key->next; } copy_short_key (&tail_key->key, key); tail_key->next = NULL; return 0;}void del_path_key(){ if (tail_key == NULL) die("Wrong path_key structure"); if (tail_key->prev == NULL) { freemem(tail_key); tail_key = head_key = NULL; }else{ tail_key = tail_key->prev; freemem(tail_key->next); tail_key->next = NULL; }}/* path is path to stat data. If file will be relocated - new_ih will contain a key file was relocated with */static int check_check_regular_file (struct path * path, void * sd, struct item_head * new_ih){ int is_new_file;// struct key key, sd_key; __u16 mode; __u32 nlink; __u64 real_size, sd_size; __u32 blocks, sd_blocks; /* proper values and value in stat data */ __u32 first_direct_byte, sd_first_direct_byte; struct item_head * ih, sd_ih; int fix_sd; int symlnk = 0; int retval = OK; __u32 tmp_position; ih = get_ih (path); if (new_ih) { /* this objectid is used already */ *new_ih = *ih; pathrelse (path); rewrite_file (new_ih, 1, 1); linked_already(&new_ih->ih_key); one_less_corruption (fs, FIXABLE); sem_pass_stat (fs)->oid_sharing_files_relocated ++; retval = RELOCATED; if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), path) == ITEM_NOT_FOUND) reiserfs_panic ("check_check_regular_file: Could not find a StatData of " "the relocated file %K", &new_ih->ih_key); /* stat data is marked unreachable again due to relocation, fix that */ ih = get_ih (path); sd = get_item (path); } if (get_ih_item_len (ih) == SD_SIZE) is_new_file = 1; else is_new_file = 0; get_sd_nlink (ih, sd, &nlink); get_sd_mode (ih, sd, &mode); get_sd_size (ih, sd, &sd_size); get_sd_blocks (ih, sd, &sd_blocks);/* if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { // check and set nlink first nlink ++; set_sd_nlink (ih, sd, &nlink); mark_buffer_dirty (bh); if (nlink > 1) return OK; }*/ if (!is_new_file) get_sd_first_direct_byte (ih, sd, &sd_first_direct_byte); if (S_ISLNK (mode)) symlnk = 1; sd_ih = *ih;// sd_key = sd_ih.ih_key; pathrelse (path); if (are_file_items_correct (&sd_ih, sd, &real_size, &blocks, 0/* do not mark reachable */, &symlnk) != 1) { one_more_corruption (fs, FATAL); fsck_log ("check_regular_file: The file %K with the corrupted structure found\n", &sd_ih.ih_key); } else { fix_sd = 0; fix_sd += wrong_mode (&sd_ih.ih_key, &mode, real_size, symlnk); if (!is_new_file) fix_sd += wrong_first_direct_byte (&sd_ih.ih_key, fs->fs_blocksize, &first_direct_byte, sd_first_direct_byte, real_size); if (reiserfs_bin_search(&sd_ih.ih_key, trunc_links, links_num, sizeof(sd_ih.ih_key), &tmp_position, comp_short_keys) != POSITION_FOUND) { fix_sd += wrong_st_size (&sd_ih.ih_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1, fs->fs_blocksize, &real_size, sd_size, symlnk ? TYPE_SYMLINK : 0); } else { real_size = sd_size; } fix_sd += wrong_st_blocks (&sd_ih.ih_key, &blocks, sd_blocks, mode, is_new_file); if (fix_sd) { if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { struct buffer_head * bh; /* find stat data and correct it */ set_type_and_offset (KEY_FORMAT_1, &sd_ih.ih_key, SD_OFFSET, TYPE_STAT_DATA); if (reiserfs_search_by_key_4 (fs, &sd_ih.ih_key, path) != ITEM_FOUND) { fsck_log ("check_regular_file: A StatData of the file %K cannot be " "found\n", &sd_ih.ih_key); one_more_corruption (fs, FATAL); return STAT_DATA_NOT_FOUND; } bh = get_bh (path); ih = get_ih (path); sd = get_item (path); set_sd_size (ih, sd, &real_size); set_sd_blocks (ih, sd, &blocks); set_sd_mode (ih, sd, &mode); if (!is_new_file) set_sd_first_direct_byte (ih, sd, &first_direct_byte); mark_buffer_dirty (bh); } else { fsck_check_stat (fs)->fixable_corruptions += fix_sd; } } } return retval;}/* returns buffer, containing found directory item.*/static char * get_next_directory_item ( struct key * key, /* on return this will contain key of next item in the tree */ struct key * parent, struct item_head * ih, __u32 * pos_in_item, int dir_format){ INITIALIZE_PATH (path); char * dir_item; struct key * rdkey; struct buffer_head * bh; struct reiserfs_de_head * deh; int i; int retval;start_again: retval = reiserfs_search_by_entry_key (fs, key, &path); if (retval != POSITION_FOUND && get_offset (key) != DOT_OFFSET) reiserfs_panic ("get_next_directory_item: The current directory %k cannot be found", key); /* leaf containing directory item */ bh = PATH_PLAST_BUFFER (&path); *pos_in_item = path.pos_in_item; *ih = *get_ih (&path); deh = B_I_DEH (bh, ih); /* position was not found for '.' or there is no '..' */ if (retval != POSITION_FOUND || ((get_offset (key) == DOT_OFFSET) && (get_ih_entry_count (ih) < 2 || name_in_entry_length (ih, deh + 1, 1) != 2 || strncmp (name_in_entry (deh + 1, 1), "..", 2)))) { fsck_log ("get_next_directory_item: The %s %k cannot be found in %k", (retval == POSITION_NOT_FOUND) ? "entry" : "directory", key, &ih->ih_key); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { /* add "." and ".." exist */ pathrelse (&path); reiserfs_add_entry (fs, key, ".", name_length (".", dir_format), key, 0); reiserfs_add_entry (fs, key, "..", name_length ("..", dir_format), parent, 0); fsck_log (" - entry was added\n"); goto start_again; } else { one_more_corruption (fs, FIXABLE); fsck_log ("\n"); if (retval == DIRECTORY_NOT_FOUND) return 0; } } /* make sure, that ".." exists as well *//* if (get_offset (key) == DOT_OFFSET) { if (get_ih_entry_count (ih) < 2 || name_in_entry_length (ih, deh + 1, 1) != 2 || strncmp (name_in_entry (deh + 1, 1), "..", 2)) { fsck_log ("get_next_directory_item: \"..\" not found in %H\n", ih); pathrelse (&path); return 0; } }*/ /* mark hidden entries as visible, set "." and ".." correctly */ deh += *pos_in_item; for (i = *pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) {/* int namelen; char * name; name = name_in_entry (deh, i); namelen = name_in_entry_length (ih, deh, i); if (de_hidden (deh)) // handled in check_tree reiserfs_panic ("get_next_directory_item: item %k: hidden entry %d \'%.*s\'\n", key, i, namelen, name);*/ if (get_deh_offset (deh) == DOT_OFFSET) { if (not_of_one_file (&(deh->deh2_dir_id), key)) { /* "." must point to the directory it is in */ //deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*????*/ { fsck_log ("get_next_directory_item: The entry \".\" of the directory %K " "pointes to %K, instead of %K", key, (struct key *)(&(deh->deh2_dir_id)), key); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { set_deh_dirid (deh, get_key_dirid (key)); set_deh_objectid (deh, get_key_objectid (key)); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } else { one_more_corruption (fs, FIXABLE); fsck_log ("\n"); } } } if (get_deh_offset (deh) == DOT_DOT_OFFSET) { /* set ".." so that it points to the correct parent directory */ if (comp_short_keys (&(deh->deh2_dir_id), parent)) { fsck_log ("get_next_directory_item: The entry \"..\" of the directory %K " "pointes to %K, instead of %K", key, (struct key *)(&(deh->deh2_dir_id))); if (fsck_mode (fs) == FSCK_FIX_FIXABLE) { set_deh_dirid (deh, get_key_dirid (parent)); set_deh_objectid (deh, get_key_objectid (parent)); mark_buffer_dirty (bh); fsck_log (" - corrected\n"); } else { one_more_corruption (fs, FIXABLE); fsck_log ("\n"); } } } } /* copy directory item to the temporary buffer */ dir_item = getmem (get_ih_item_len (ih)); memcpy (dir_item, B_I_PITEM (bh, ih), get_ih_item_len (ih)); /* next item key */ if (PATH_LAST_POSITION (&path) == (B_NR_ITEMS (bh) - 1) && (rdkey = uget_rkey (&path))) copy_key (key, rdkey); else { set_key_dirid (key, 0); set_key_objectid (key, 0); } if (fsck_mode (fs) == FSCK_REBUILD) mark_item_reachable (get_ih (&path), bh); pathrelse (&path); return dir_item;}/* semantic pass of --check */static int check_semantic_pass (struct key * key, struct key * parent, int dot_dot, struct item_head * new_ih){ struct path path; void * sd; __u32 nlink; int is_new_dir; struct buffer_head * bh; struct item_head * ih; int retval; char * dir_item; __u32 pos_in_item; struct item_head tmp_ih; struct key next_item_key, entry_key, object_key; __u64 dir_size = 0; __u32 blocks; __u64 sd_size; __u32 sd_blocks; int fix_sd; /*int relocate;*/ int dir_format = 0; __u16 mode; retval = OK; /* start_again: when directory was relocated */ if (!KEY_IS_STAT_DATA_KEY (key)) { fsck_log ("check_semantic_pass: The key %k must be key of a StatData\n", key); one_more_corruption (fs, FATAL); return STAT_DATA_NOT_FOUND; } /* look for stat data of an object */ if (reiserfs_search_by_key_4 (fs, key, &path) == ITEM_NOT_FOUND) { pathrelse (&path); return STAT_DATA_NOT_FOUND; } /* stat data has been found */ ih = get_ih (&path); sd = get_item(&path); get_sd_nlink (ih, sd, &nlink); /* It seems quite difficult to relocate objects on fix-fixable - * rewrite_file calls reiserfs_file_write which can convert tails * to unfm, plus unreachable, was_tail flags, etc. */#if 0 if ((/* relocate = */ should_be_relocated(&ih->ih_key))) { /* if (fsck_mode(fs) == FSCK_CHECK) relocate = 0; */ one_more_corruption(fs, FATAL); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -