📄 fsys_reiserfs.c
字号:
#ifdef REISERDEBUG printf ("search_stat:\n key %d:%d:0:0\n", dir_id, objectid);#endif /* REISERDEBUG */ depth = INFO->tree_depth; cache = ROOT; while (depth > DISK_LEAF_NODE_LEVEL) { struct key *key; nr_item = BLOCKHEAD (cache)->blk_nr_item; key = KEY (cache); for (i = 0; i < nr_item; i++) { if (key->k_dir_id > dir_id || (key->k_dir_id == dir_id && (key->k_objectid > objectid || (key->k_objectid == objectid && (key->u.v1.k_offset | key->u.v1.k_uniqueness) > 0)))) break; key++; } #ifdef REISERDEBUG printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);#endif /* REISERDEBUG */ INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1; cache = read_tree_node (DC (cache)[i].dc_block_number, --depth); if (! cache) return 0; } /* cache == LEAF */ nr_item = BLOCKHEAD (LEAF)->blk_nr_item; ih = ITEMHEAD; for (i = 0; i < nr_item; i++) { if (ih->ih_key.k_dir_id == dir_id && ih->ih_key.k_objectid == objectid && ih->ih_key.u.v1.k_offset == 0 && ih->ih_key.u.v1.k_uniqueness == 0) {#ifdef REISERDEBUG printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);#endif /* REISERDEBUG */ INFO->current_ih = ih; INFO->current_item = &LEAF[ih->ih_item_location]; return 1; } ih++; } errnum = ERR_FSYS_CORRUPT; return 0;}intreiserfs_read (char *buf, int len){ unsigned int blocksize; unsigned int offset; unsigned int to_read; char *prev_buf = buf; #ifdef REISERDEBUG printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n", filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);#endif /* REISERDEBUG */ if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1) { search_stat (INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid); goto get_next_key; } while (! errnum) { if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid) break; offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1; blocksize = INFO->current_ih->ih_item_len; #ifdef REISERDEBUG printf (" loop: filepos=%d len=%d, offset=%d blocksize=%d\n", filepos, len, offset, blocksize);#endif /* REISERDEBUG */ if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT) && offset < blocksize) {#ifdef REISERDEBUG printf ("direct_read: offset=%d, blocksize=%d\n", offset, blocksize);#endif /* REISERDEBUG */ to_read = blocksize - offset; if (to_read > len) to_read = len; if (disk_read_hook != NULL) { disk_read_func = disk_read_hook; block_read (INFO->blocks[DISK_LEAF_NODE_LEVEL], (INFO->current_item - LEAF + offset), to_read, buf); disk_read_func = NULL; } else memcpy (buf, INFO->current_item + offset, to_read); goto update_buf_len; } else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT)) { blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;#ifdef REISERDEBUG printf ("indirect_read: offset=%d, blocksize=%d\n", offset, blocksize);#endif /* REISERDEBUG */ while (offset < blocksize) { __u32 blocknr = ((__u32 *) INFO->current_item) [offset >> INFO->fullblocksize_shift]; int blk_offset = offset & (INFO->blocksize-1); to_read = INFO->blocksize - blk_offset; if (to_read > len) to_read = len; disk_read_func = disk_read_hook; /* Journal is only for meta data. Data blocks can be read * directly without using block_read */ devread (blocknr << INFO->blocksize_shift, blk_offset, to_read, buf); disk_read_func = NULL; update_buf_len: len -= to_read; buf += to_read; offset += to_read; filepos += to_read; if (len == 0) goto done; } } get_next_key: next_key (); } done: return errnum ? 0 : buf - prev_buf;}/* preconditions: reiserfs_mount already executed, therefore * INFO block is valid * returns: 0 if error, nonzero iff we were able to find the file successfully * postconditions: on a nonzero return, INFO->fileinfo contains the info * of the file we were trying to look up, filepos is 0 and filemax is * the size of the file. */intreiserfs_dir (char *dirname){ struct reiserfs_de_head *de_head; char *rest, ch; __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;#ifndef STAGE1_5 int do_possibilities = 0;#endif /* ! STAGE1_5 */ char linkbuf[PATH_MAX]; /* buffer for following symbolic links */ int link_count = 0; int mode; dir_id = REISERFS_ROOT_PARENT_OBJECTID; objectid = REISERFS_ROOT_OBJECTID; while (1) {#ifdef REISERDEBUG printf ("dirname=%s\n", dirname);#endif /* REISERDEBUG */ /* Search for the stat info first. */ if (! search_stat (dir_id, objectid)) return 0; #ifdef REISERDEBUG printf ("sd_mode=%x sd_size=%d\n", ((struct stat_data *) INFO->current_item)->sd_mode, ((struct stat_data *) INFO->current_item)->sd_size);#endif /* REISERDEBUG */ mode = ((struct stat_data *) INFO->current_item)->sd_mode; /* If we've got a symbolic link, then chase it. */ if (S_ISLNK (mode)) { int len; if (++link_count > MAX_LINK_COUNT) { errnum = ERR_SYMLINK_LOOP; return 0; } /* Get the symlink size. */ filemax = ((struct stat_data *) INFO->current_item)->sd_size; /* Find out how long our remaining name is. */ len = 0; while (dirname[len] && !isspace (dirname[len])) len++; if (filemax + len > sizeof (linkbuf) - 1) { errnum = ERR_FILELENGTH; return 0; } /* Copy the remaining name to the end of the symlink data. Note that DIRNAME and LINKBUF may overlap! */ grub_memmove (linkbuf + filemax, dirname, len+1); INFO->fileinfo.k_dir_id = dir_id; INFO->fileinfo.k_objectid = objectid; filepos = 0; if (! next_key () || reiserfs_read (linkbuf, filemax) != filemax) { if (! errnum) errnum = ERR_FSYS_CORRUPT; return 0; }#ifdef REISERDEBUG printf ("symlink=%s\n", linkbuf);#endif /* REISERDEBUG */ dirname = linkbuf; if (*dirname == '/') { /* It's an absolute link, so look it up in root. */ dir_id = REISERFS_ROOT_PARENT_OBJECTID; objectid = REISERFS_ROOT_OBJECTID; } else { /* Relative, so look it up in our parent directory. */ dir_id = parent_dir_id; objectid = parent_objectid; } /* Now lookup the new name. */ continue; } /* if we have a real file (and we're not just printing possibilities), then this is where we want to exit */ if (! *dirname || isspace (*dirname)) { if (! S_ISREG (mode)) { errnum = ERR_BAD_FILETYPE; return 0; } filepos = 0; filemax = ((struct stat_data *) INFO->current_item)->sd_size; /* If this is a new stat data and size is > 4GB set filemax to * maximum */ if (INFO->current_ih->ih_version == ITEM_VERSION_2 && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0) filemax = 0xffffffff; INFO->fileinfo.k_dir_id = dir_id; INFO->fileinfo.k_objectid = objectid; return next_key (); } /* continue with the file/directory name interpretation */ while (*dirname == '/') dirname++; if (! S_ISDIR (mode)) { errnum = ERR_BAD_FILETYPE; return 0; } for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++); *rest = 0; # ifndef STAGE1_5 if (print_possibilities && ch != '/') do_possibilities = 1;# endif /* ! STAGE1_5 */ while (1) { char *name_end; int num_entries; if (! next_key ()) return 0;#ifdef REISERDEBUG printf ("ih: key %d:%d:%d:%d version:%d\n", INFO->current_ih->ih_key.k_dir_id, INFO->current_ih->ih_key.k_objectid, INFO->current_ih->ih_key.u.v1.k_offset, INFO->current_ih->ih_key.u.v1.k_uniqueness, INFO->current_ih->ih_version);#endif /* REISERDEBUG */ if (INFO->current_ih->ih_key.k_objectid != objectid) break; name_end = INFO->current_item + INFO->current_ih->ih_item_len; de_head = (struct reiserfs_de_head *) INFO->current_item; num_entries = INFO->current_ih->u.ih_entry_count; while (num_entries > 0) { char *filename = INFO->current_item + de_head->deh_location; char tmp = *name_end; if ((de_head->deh_state & DEH_Visible)) { int cmp; /* Directory names in ReiserFS are not null * terminated. We write a temporary 0 behind it. * NOTE: that this may overwrite the first block in * the tree cache. That doesn't hurt as long as we * don't call next_key () in between. */ *name_end = 0; cmp = substring (dirname, filename); *name_end = tmp;# ifndef STAGE1_5 if (do_possibilities) { if (cmp <= 0) { if (print_possibilities > 0) print_possibilities = -print_possibilities; *name_end = 0; print_a_completion (filename); *name_end = tmp; } } else# endif /* ! STAGE1_5 */ if (cmp == 0) goto found; } /* The beginning of this name marks the end of the next name. */ name_end = filename; de_head++; num_entries--; } } # ifndef STAGE1_5 if (print_possibilities < 0) return 1;# endif /* ! STAGE1_5 */ errnum = ERR_FILE_NOT_FOUND; *rest = ch; return 0; found: *rest = ch; dirname = rest; parent_dir_id = dir_id; parent_objectid = objectid; dir_id = de_head->deh_dir_id; objectid = de_head->deh_objectid; }}intreiserfs_embed (int *start_sector, int needed_sectors){ struct reiserfs_super_block super; int num_sectors; if (! devread (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0, sizeof (struct reiserfs_super_block), (char *) &super)) return 0; *start_sector = 1; /* reserve first sector for stage1 */ if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0 || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0 || substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) <= 0) && (/* check that this is not a super block copy inside * the journal log */ super.s_journal_block * super.s_blocksize > REISERFS_DISK_OFFSET_IN_BYTES)) num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; else num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1; return (needed_sectors <= num_sectors);}#endif /* FSYS_REISERFS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -