📄 reiserfs.c
字号:
#endif /* REISERDEBUG */ if (key_nr == nr_item) /* This is the last item in this block, set the next_key_nr to 0 */ INFO->next_key_nr[depth] = 0; cache = read_tree_node (dc_block_number(&(DC (cache)[key_nr])), --depth); if (! cache) return 0; } while (depth > DISK_LEAF_NODE_LEVEL); ih = ITEMHEAD; } found: INFO->current_ih = ih; INFO->current_item = &LEAF[__le16_to_cpu(ih->ih_item_location)];#ifdef REISERDEBUG printf (" new ih: key %d:%d:%d:%d version:%d\n", __le32_to_cpu(INFO->current_ih->ih_key.k_dir_id), __le32_to_cpu(INFO->current_ih->ih_key.k_objectid), __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset), __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness), __le16_to_cpu(INFO->current_ih->ih_version));#endif /* REISERDEBUG */ return 1;}/* preconditions: reiserfs_mount already executed, therefore * INFO block is valid * returns: 0 if error (errnum is set), * nonzero iff we were able to find the key successfully. * postconditions: on a nonzero return, the current_ih and * current_item fields describe the key that equals the * searched key. INFO->next_key contains the next key after * the searched key. * side effects: messes around with the cache. */static intsearch_stat (__u32 dir_id, __u32 objectid){ char *cache; int depth; int nr_item; int i; struct item_head *ih;#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 = __le16_to_cpu(BLOCKHEAD (cache)->blk_nr_item); key = KEY (cache); for (i = 0; i < nr_item; i++) { if (__le32_to_cpu(key->k_dir_id) > dir_id || (__le32_to_cpu(key->k_dir_id) == dir_id && (__le32_to_cpu(key->k_objectid) > objectid || (__le32_to_cpu(key->k_objectid) == objectid && (__le32_to_cpu(key->u.v1.k_offset) | __le32_to_cpu(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_block_number(&(DC (cache)[i])), --depth); if (! cache) return 0; } /* cache == LEAF */ nr_item = __le16_to_cpu(BLOCKHEAD (LEAF)->blk_nr_item); ih = ITEMHEAD; for (i = 0; i < nr_item; i++) { if (__le32_to_cpu(ih->ih_key.k_dir_id) == dir_id && __le32_to_cpu(ih->ih_key.k_objectid) == objectid && __le32_to_cpu(ih->ih_key.u.v1.k_offset) == 0 && __le32_to_cpu(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[__le16_to_cpu(ih->ih_item_location)]; return 1; } ih++; } errnum = ERR_FSYS_CORRUPT; return 0;}intreiserfs_read (char *buf, unsigned 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=%Lx\n", filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);#endif /* REISERDEBUG */ if (__le32_to_cpu(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 (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != INFO->fileinfo.k_objectid) { break; } offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1; blocksize = __le16_to_cpu(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; 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 = __le32_to_cpu(((__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; /* Journal is only for meta data. Data blocks can be read * directly without using block_read */ reiserfs_devread (blocknr << INFO->blocksize_shift, blk_offset, to_read, buf); 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. */static 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", stat_data_v1(INFO->current_ih) ? sd_v1_mode((struct stat_data_v1 *) INFO->current_item) : sd_v2_mode((struct stat_data *) (INFO->current_item)), stat_data_v1(INFO->current_ih) ? sd_v1_size((struct stat_data_v1 *) INFO->current_item) : sd_v2_size((struct stat_data *) INFO->current_item) );#endif /* REISERDEBUG */ mode = stat_data_v1(INFO->current_ih) ? sd_v1_mode((struct stat_data_v1 *) INFO->current_item) : sd_v2_mode((struct stat_data *) INFO->current_item); /* If we've got a symbolic link, then chase it. */ if (S_ISLNK (mode)) { unsigned int len; if (++link_count > MAX_LINK_COUNT) { errnum = ERR_SYMLINK_LOOP; return 0; } /* Get the symlink size. */ filemax = stat_data_v1(INFO->current_ih) ? sd_v1_size((struct stat_data_v1 *) INFO->current_item) : sd_v2_size((struct stat_data *) INFO->current_item); /* 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! */ 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 = stat_data_v1(INFO->current_ih) ? sd_v1_size((struct stat_data_v1 *) INFO->current_item) : sd_v2_size((struct stat_data *) INFO->current_item);#if 0 /* If this is a new stat data and size is > 4GB set filemax to * maximum */ if (__le16_to_cpu(INFO->current_ih->ih_version) == ITEM_VERSION_2 && sd_size_hi((struct stat_data *) INFO->current_item) > 0) filemax = 0xffffffff;#endif 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", __le32_to_cpu(INFO->current_ih->ih_key.k_dir_id), __le32_to_cpu(INFO->current_ih->ih_key.k_objectid), __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_offset), __le32_to_cpu(INFO->current_ih->ih_key.u.v1.k_uniqueness), __le16_to_cpu(INFO->current_ih->ih_version));#endif /* REISERDEBUG */ if (__le32_to_cpu(INFO->current_ih->ih_key.k_objectid) != objectid) break; name_end = INFO->current_item + __le16_to_cpu(INFO->current_ih->ih_item_len); de_head = (struct reiserfs_de_head *) INFO->current_item; num_entries = __le16_to_cpu(INFO->current_ih->u.ih_entry_count); while (num_entries > 0) { char *filename = INFO->current_item + deh_location(de_head); char tmp = *name_end; if ((deh_state(de_head) & 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) { char fn[PATH_MAX]; struct fsys_reiser_info info_save; if (print_possibilities > 0) print_possibilities = -print_possibilities; *name_end = 0; strcpy(fn, filename); *name_end = tmp; /* If NAME is "." or "..", do not count it. */ if (strcmp (fn, ".") != 0 && strcmp (fn, "..") != 0) { memcpy(&info_save, INFO, sizeof(struct fsys_reiser_info)); search_stat (deh_dir_id(de_head), deh_objectid(de_head)); sd_print_item(INFO->current_ih, INFO->current_item); printf(" %s\n", fn); search_stat (dir_id, objectid); memcpy(INFO, &info_save, sizeof(struct fsys_reiser_info)); } } } 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 = deh_dir_id(de_head); objectid = deh_objectid(de_head); }}/* * U-Boot interface functions *//* * List given directory * * RETURN: 0 - OK, else grub_error_t errnum */intreiserfs_ls (char *dirname){ char *dir_slash; int res; errnum = 0; dir_slash = malloc(strlen(dirname) + 1); if (dir_slash == NULL) { return ERR_NUMBER_OVERFLOW; } strcpy(dir_slash, dirname); /* add "/" to the directory name */ strcat(dir_slash, "/"); print_possibilities = 1; res = reiserfs_dir (dir_slash); free(dir_slash); if (!res || errnum) { return errnum; } return 0;}/* * Open file for reading * * RETURN: >0 - OK, size of opened file * <0 - ERROR -grub_error_t errnum */intreiserfs_open (char *filename){ /* open the file */ errnum = 0; print_possibilities = 0; if (!reiserfs_dir (filename) || errnum) { return -errnum; } return filemax;}#endif /* CFG_CMD_REISER */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -