📄 semantic_rebuild.c
字号:
/* * Copyright 1996-2004 by Hans Reiser, licensing governed by * reiserfsprogs/README */#include "fsck.h"int screen_width;int screen_curr_pos;char *screen_savebuffer;int screen_savebuffer_len;#define MIN(a, b) (((a)>(b))?(b):(a))/* semantic pass progress */void print_name (char * name, int len){ int i; if (fsck_quiet (fs)) return; if ( len + screen_curr_pos + 1 > screen_savebuffer_len) { char *t; t = expandmem(screen_savebuffer, screen_savebuffer_len + 1, len + screen_curr_pos - screen_savebuffer_len + 1); if (!t) { fsck_progress("\nOut of memory\n"); return; // ???? } screen_savebuffer = t; screen_savebuffer_len = len + screen_curr_pos + 1; } strcat(screen_savebuffer,"/"); strncat(screen_savebuffer,name,len); i = screen_curr_pos; screen_curr_pos += len+1; for ( ; i<screen_curr_pos; i++) if ( screen_savebuffer[i] < 32 ) screen_savebuffer[i] = '?'; screen_savebuffer[screen_curr_pos]=0; if ( screen_width < screen_curr_pos ) { printf("\r... %.*s",screen_width - 4, screen_savebuffer + ( screen_curr_pos - (screen_width - 4))); } else printf("/%.*s", len, screen_savebuffer + screen_curr_pos - len); fflush (stdout);}void erase_name (int len){ int i; if (fsck_quiet (fs)) return; if ( screen_curr_pos < screen_width ) { screen_curr_pos-=len+1; screen_savebuffer[screen_curr_pos]=0; for (i = 0; i<=len; i++) printf("\b"); for (i = 0; i<=len+1; i++) printf(" "); for (i = 0; i<=len+1; i++) printf("\b"); } else { screen_curr_pos-=len+1; if (screen_curr_pos < 0 ) die("%s: Get out of buffer's data!\n", __FUNCTION__); screen_savebuffer[screen_curr_pos]=0; printf("\r"); if (screen_curr_pos >= screen_width ) { int t_preface=MIN(screen_curr_pos-screen_width,4); printf("%.*s%.*s", t_preface, "... ", screen_width-t_preface - 1, screen_savebuffer + ( screen_curr_pos - (screen_width - t_preface)) + 1); } else { int space_used=printf("%s", screen_savebuffer); for ( i=space_used; i < screen_width; i++) printf(" "); for ( i=space_used; i < screen_width; i++) printf("\b"); } } fflush (stdout);}/* *size is "real" file size, sd_size - size from stat data */int wrong_st_size (struct key * key, unsigned long long max_file_size, int blocksize, __u64 * size, __u64 sd_size, int type){ if (sd_size <= max_file_size) { if (sd_size == *size) return 0; if (type == TYPE_DIRENTRY) { /* directory size must match to the sum of length of its entries */ fsck_log ("vpf-10650: The directory %K has the wrong size in the StatData " "(%Lu)%s(%Lu)\n", key, sd_size, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *size); return 1; } if (sd_size > *size) { /* size in stat data can be bigger than size calculated by items */ if (fsck_adjust_file_size (fs) || type == TYPE_SYMLINK) { /* but it -o is given - fix that */ fsck_log ("vpf-10660: The file %K has too big size in the StatData " "(%Lu)%s(%Lu)\n", key, sd_size, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *size); sem_pass_stat (fs)->fixed_sizes ++; return 1; } *size = sd_size; return 0; } if (!(*size % blocksize)) { /* last item is indirect */ if (((sd_size & ~(blocksize - 1)) == (*size - blocksize)) && sd_size % blocksize) { /* size in stat data is correct */ *size = sd_size; return 0; } } else { /* last item is a direct one */ if (!(*size % 8)) { if (((sd_size & ~7) == (*size - 8)) && sd_size % 8) { /* size in stat data is correct */ *size = sd_size; return 0; } } } } fsck_log ("vpf-10670: The file %K has the wrong size in the StatData (%Lu)%s(%Lu)\n", key, sd_size, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *size); sem_pass_stat (fs)->fixed_sizes ++; return 1;}/* sd_blocks is 32 bit only *//* old stat data shares sd_block and sd_dev - do not wipe sd_rdev out *//* we should fix it as following:|------------------------------------------------------------------|| | 3.6 | 3.5 ||---------------------------------------------------| || | blocks | r_dev|generation | blocks/r_dev ||------------------------------------------------------------------|| fifo, sockets | 0 | generation | 0 || chr/blk_dev | 0 | maj:min | maj:min || file, dir, link | blocks | generation | blocks ||------------------------------------------------------------------|*/int wrong_st_blocks (struct key * key, __u32 * blocks, __u32 sd_blocks, __u16 mode, int new_format){ int ret = 0; if (S_ISREG (mode) || S_ISLNK (mode) || S_ISDIR (mode)) { if ((!S_ISLNK(mode) && *blocks != sd_blocks) || (S_ISLNK(mode) && *blocks != sd_blocks && (ROUND_UP(*blocks) != sd_blocks))) { fsck_log ("vpf-10680: The %s %K has the wrong block count in the StatData " "(%u)%s(%u)\n", S_ISDIR (mode) ? "directory" : S_ISREG (mode) ? "file" : "link", key, sd_blocks, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", *blocks); ret = 1; } } else if (new_format || (S_ISFIFO (mode) || S_ISSOCK (mode))) { if (sd_blocks != 0) { fsck_log ("vpf-10690: The object %K has the wrong block count in the StatData " "(%u)%s(%u)\n", key, sd_blocks, fsck_mode(fs) == FSCK_CHECK ? ", should be " : " - corrected to ", 0); *blocks = 0; ret = 1; } } return ret;}/*int wrong_st_rdev (struct key * key, __u32 * sd_rdev, __u16 mode, int new_format){ int ret = 0; if (!new_format) return 0; if (!S_ISCHR (mode) && !S_ISBLK (mode)) { if (*sd_rdev != 0) { fsck_log ("%s %K has wrong sd_rdev %u, has to be 0\n", S_ISDIR (mode) ? "dir" : "file", key, *sd_rdev); *sd_rdev = 0; ret = 1; } } return ret;}*//* only regular files and symlinks may have items but stat data. Symlink should have body */int wrong_mode (struct key * key, __u16 * mode, __u64 real_size, int symlink){ int retval = 0; if (S_ISLNK (*mode) && !symlink) { fsck_log ("The file %K (%M) is too big to be the symlink%s regfile\n", key, *mode, fsck_mode(fs) == FSCK_CHECK ? ", should be the" : " - corrected " "to the"); *mode &= ~S_IFMT; *mode |= S_IFREG; retval = 1; } if (ftypelet (*mode) != '?') { /* mode looks reasonable */ if (S_ISREG (*mode) || S_ISLNK (*mode)) return retval; /* device, pipe, socket have no items */ if (!real_size) return retval; } /* there are items, so change file mode to regular file. Otherwise - file bodies do not get deleted */ if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("The object %K has wrong mode (%M)\n", key, *mode); } else { fsck_log("The object %K has wrong mode (%M) - corrected to %M\n", key, *mode, (S_IFREG | 0600)); } *mode = (S_IFREG | 0600); return 1;}/* key is a key of last file item */int wrong_first_direct_byte (struct key * key, int blocksize, __u32 * first_direct_byte, __u32 sd_first_direct_byte, __u32 size){ if (!size || is_indirect_key (key)) { /* there is no direct item */ *first_direct_byte = NO_BYTES_IN_DIRECT_ITEM; if (sd_first_direct_byte != NO_BYTES_IN_DIRECT_ITEM) { if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - should be (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } else { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - corrected to (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } return 1; } return 0; } /* there is direct item */ *first_direct_byte = (get_offset (key) & ~(blocksize - 1)) + 1; if (*first_direct_byte != sd_first_direct_byte) { if (fsck_mode(fs) == FSCK_CHECK) { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - should be (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } else { fsck_log ("The file %K: The wrong info about the tail in the StatData, " "first_direct_byte (%d) - corrected to (%d)\n", key, sd_first_direct_byte, *first_direct_byte); } return 1; } return 0;}/* delete all items (but directory ones) with the same key 'ih' has (including stat data of not a directory) and put them back at the other place */void relocate_dir (struct item_head * ih, int change_ih){ struct key key; struct key * rkey; struct path path; struct item_head * path_ih; struct si * si; __u32 new_objectid; /* starting with the leftmost one - look for all items of file, store them and delete */ key = ih->ih_key; set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA); si = 0; while (1) { reiserfs_search_by_key_4 (fs, &key, &path); if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) { rkey = uget_rkey (&path); if (rkey && !not_of_one_file (&key, rkey)) { /* file continues in the right neighbor */ key = *rkey; pathrelse (&path); continue; } /* there is no more items of a directory */ pathrelse (&path); break; } if (is_stat_data_ih (get_ih(&path))) fix_obviously_wrong_sd_mode (&path); path_ih = get_ih (&path); if (not_of_one_file (&key, &(path_ih->ih_key))) { /* there are no more item with this key */ pathrelse (&path); break; } /* ok, item found, but make sure that it is not a directory one */ if ((is_stat_data_ih (path_ih) && not_a_directory (get_item (&path))) || is_direct_ih (path_ih) || is_indirect_ih (path_ih)) { /* item of not a directory found. Leave it in the tree. FIXME: should not happen */ key = path_ih->ih_key; set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1); pathrelse (&path); continue; } /* directory stat data ro directory item */ si = save_and_delete_file_item (si, &path); } if (!si) { fsck_log ("relocate_dir: WARNING: No one item of the directory %K found\n", &key); return; } /* get new objectid for relocation or get objectid with which file was relocated already */ new_objectid = objectid_for_relocation (&ih->ih_key); set_key_objectid (&ih->ih_key, new_objectid); /* put all items removed back into tree */ while (si) { fsck_log ("relocate_dir: Moving %k to ", &si->si_ih.ih_key); set_key_objectid (&si->si_ih.ih_key, new_objectid); fsck_log ("%k\n", &si->si_ih.ih_key); if (get_offset (&(si->si_ih.ih_key)) == DOT_OFFSET) { /* fix "." entry to point to a directtory properly */ struct reiserfs_de_head * deh; deh = (struct reiserfs_de_head *)si->si_dnm_data; set_deh_objectid (deh, new_objectid); } insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/); si = remove_saved_item (si); }}/* path is path to stat data. If file will be relocated - new_ih will contain a key file was relocated with */int rebuild_check_regular_file (struct path * path, void * sd, struct item_head * new_ih){ int is_new_file;// struct key sd_key; __u16 mode; __u32 nlink; __u64 real_size, saved_size; __u32 blocks, saved_blocks; /* proper values and value in stat data */ __u32 first_direct_byte, saved_first_direct_byte; struct buffer_head * bh; struct item_head * ih, sd_ih; int fix_sd; int symlnk = 0; int retval; retval = OK; /* stat data of a file */ ih = get_ih (path); bh = get_bh (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); 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 ("%s: Could not find the StatData of the relocated file %k", __FUNCTION__, &(new_ih->ih_key)); /* stat data is marked unreachable again due to relocation, fix that */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -