⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reiserfs.c

📁 F:worksip2440a board可启动u-boot-like.tar.gz F:worksip2440a board可启动u-boot-like.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -