* stage2/fsys_reiserfs.c: Symlink support added.
(S_ISLNK): New macro. (PATH_MAX): Likewise. (MAX_LINK_COUNT): Likewise. (reiserfs_dir): Check for symlink and handle them. (read_tree_node): Take a block number and check if tree node was already read in. If not update the INFO->blocks field. (next_key): Changed call of read_tree_node. (search_stat): Likewise. (journal_init): Fixed a small bug. Some debugging messages added.
This commit is contained in:
parent
b6092dd0ea
commit
bef3d7d863
3 changed files with 195 additions and 30 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2000-08-01 Jochen Hoenicke <jochen@gnu.org>
|
||||||
|
|
||||||
|
* stage2/fsys_reiserfs.c: Symlink support added.
|
||||||
|
(S_ISLNK): New macro.
|
||||||
|
(PATH_MAX): Likewise.
|
||||||
|
(MAX_LINK_COUNT): Likewise.
|
||||||
|
(reiserfs_dir): Check for symlink and handle them.
|
||||||
|
(read_tree_node): Take a block number and check if tree node was
|
||||||
|
already read in. If not update the INFO->blocks field.
|
||||||
|
(next_key): Changed call of read_tree_node.
|
||||||
|
(search_stat): Likewise.
|
||||||
|
(journal_init): Fixed a small bug. Some debugging messages added.
|
||||||
|
|
||||||
2000-07-31 Pavel Roskin <proski@gnu.org>
|
2000-07-31 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
* grub/asmstub.c (biosdisk) [__linux__]: The first argument for
|
* grub/asmstub.c (biosdisk) [__linux__]: The first argument for
|
||||||
|
|
1
NEWS
1
NEWS
|
@ -8,6 +8,7 @@ New in 0.5.96 - XXXX-XX-XX:
|
||||||
GRUB not to pass a Linux's mem option automatically.
|
GRUB not to pass a Linux's mem option automatically.
|
||||||
* Now GRUB is compliant with the Linux/i386 boot protocol version 2.02.
|
* Now GRUB is compliant with the Linux/i386 boot protocol version 2.02.
|
||||||
* The network support is updated to Etherboot-4.6.4.
|
* The network support is updated to Etherboot-4.6.4.
|
||||||
|
* Symlinks in ReiserFS are supported.
|
||||||
|
|
||||||
New in 0.5.95 - 2000-06-27:
|
New in 0.5.95 - 2000-06-27:
|
||||||
* NetBSD ELF kernel support is added. You have to specify the new option
|
* NetBSD ELF kernel support is added. You have to specify the new option
|
||||||
|
|
|
@ -266,10 +266,6 @@ struct reiserfs_de_head
|
||||||
#define V2_TYPE_DIRECT 2
|
#define V2_TYPE_DIRECT 2
|
||||||
#define V2_TYPE_DIRENTRY 3
|
#define V2_TYPE_DIRENTRY 3
|
||||||
|
|
||||||
#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
|
|
||||||
#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
|
|
||||||
|
|
||||||
|
|
||||||
#define REISERFS_ROOT_OBJECTID 2
|
#define REISERFS_ROOT_OBJECTID 2
|
||||||
#define REISERFS_ROOT_PARENT_OBJECTID 1
|
#define REISERFS_ROOT_PARENT_OBJECTID 1
|
||||||
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
|
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
|
||||||
|
@ -277,8 +273,14 @@ struct reiserfs_de_head
|
||||||
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
|
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
|
||||||
#define REISERFS_OLD_BLOCKSIZE 4096
|
#define REISERFS_OLD_BLOCKSIZE 4096
|
||||||
|
|
||||||
|
#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
|
||||||
|
#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
|
||||||
|
#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
|
||||||
|
|
||||||
/* The size of the node cache (must be power of two) */
|
#define PATH_MAX 1024 /* include/linux/limits.h */
|
||||||
|
#define MAX_LINK_COUNT 5 /* number of symbolic links to follow */
|
||||||
|
|
||||||
|
/* The size of the node cache */
|
||||||
#define FSYSREISER_CACHE_SIZE 24*1024
|
#define FSYSREISER_CACHE_SIZE 24*1024
|
||||||
#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
|
#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
|
||||||
#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
|
#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
|
||||||
|
@ -324,7 +326,9 @@ struct fsys_reiser_info
|
||||||
unsigned int next_key_nr[MAX_HEIGHT];
|
unsigned int next_key_nr[MAX_HEIGHT];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The cached s+tree blocks in FSYS_BUF */
|
/* The cached s+tree blocks in FSYS_BUF, see below
|
||||||
|
* for a more detailed description.
|
||||||
|
*/
|
||||||
#define ROOT ((char *) ((int) FSYS_BUF))
|
#define ROOT ((char *) ((int) FSYS_BUF))
|
||||||
#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
|
#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
|
||||||
#define LEAF CACHE (DISK_LEAF_NODE_LEVEL)
|
#define LEAF CACHE (DISK_LEAF_NODE_LEVEL)
|
||||||
|
@ -334,8 +338,18 @@ struct fsys_reiser_info
|
||||||
#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE))
|
#define KEY(cache) ((struct key *) ((int) cache + BLKH_SIZE))
|
||||||
#define DC(cache) ((struct disk_child *) \
|
#define DC(cache) ((struct disk_child *) \
|
||||||
((int) cache + BLKH_SIZE + KEY_SIZE * nr_item))
|
((int) cache + BLKH_SIZE + KEY_SIZE * nr_item))
|
||||||
|
/* The fsys_reiser_info block.
|
||||||
|
*/
|
||||||
#define INFO \
|
#define INFO \
|
||||||
((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE))
|
((struct fsys_reiser_info *) ((int) FSYS_BUF + FSYSREISER_CACHE_SIZE))
|
||||||
|
/*
|
||||||
|
* The journal cache. For each transaction it contains the number of
|
||||||
|
* blocks followed by the real block numbers of this transaction.
|
||||||
|
*
|
||||||
|
* If the block numbers of some transaction won't fit in this space,
|
||||||
|
* this list is stopped with a 0xffffffff marker and the remaining
|
||||||
|
* uncommitted transactions aren't cached.
|
||||||
|
*/
|
||||||
#define JOURNAL_START ((__u32 *) (INFO + 1))
|
#define JOURNAL_START ((__u32 *) (INFO + 1))
|
||||||
#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
|
#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
|
||||||
|
|
||||||
|
@ -422,6 +436,10 @@ block_read (int blockNr, int start, int len, char *buffer)
|
||||||
|
|
||||||
found:
|
found:
|
||||||
translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
|
translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
|
||||||
|
#ifdef REISERDEBUG
|
||||||
|
printf ("block_read: block %d is mapped to journal block %d.\n",
|
||||||
|
blockNr, translatedNr - INFO->journal_block);
|
||||||
|
#endif
|
||||||
/* We must continue the search, as this block may be overwritten
|
/* We must continue the search, as this block may be overwritten
|
||||||
* in later transactions.
|
* in later transactions.
|
||||||
*/
|
*/
|
||||||
|
@ -460,6 +478,11 @@ journal_init (void)
|
||||||
INFO->journal_first_desc = desc_block;
|
INFO->journal_first_desc = desc_block;
|
||||||
next_trans_id = header.j_last_flush_trans_id + 1;
|
next_trans_id = header.j_last_flush_trans_id + 1;
|
||||||
|
|
||||||
|
#ifdef REISERDEBUG
|
||||||
|
printf ("journal_init: last flushed %d\n",
|
||||||
|
header.j_last_flush_trans_id);
|
||||||
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
journal_read (desc_block, sizeof (desc), (char *) &desc);
|
journal_read (desc_block, sizeof (desc), (char *) &desc);
|
||||||
|
@ -476,11 +499,16 @@ journal_init (void)
|
||||||
/* no more valid transactions */
|
/* no more valid transactions */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef REISERDEBUG
|
||||||
|
printf ("Found valid transaction %d/%d at %d.\n",
|
||||||
|
desc.j_trans_id, desc.j_mount_id, desc_block);
|
||||||
|
#endif
|
||||||
|
|
||||||
INFO->journal_transactions++;
|
INFO->journal_transactions++;
|
||||||
next_trans_id++;
|
next_trans_id++;
|
||||||
if (journal_table < JOURNAL_END)
|
if (journal_table < JOURNAL_END)
|
||||||
{
|
{
|
||||||
if ((journal_table + 1 + JOURNAL_TRANS_HALF) >= JOURNAL_END)
|
if ((journal_table + 1 + desc.j_len) >= JOURNAL_END)
|
||||||
{
|
{
|
||||||
/* The table is almost full; mark the end of the cached
|
/* The table is almost full; mark the end of the cached
|
||||||
* journal.*/
|
* journal.*/
|
||||||
|
@ -496,13 +524,31 @@ journal_init (void)
|
||||||
*/
|
*/
|
||||||
*journal_table++ = desc.j_len;
|
*journal_table++ = desc.j_len;
|
||||||
for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++)
|
for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++)
|
||||||
|
{
|
||||||
*journal_table++ = desc.j_realblock[i];
|
*journal_table++ = desc.j_realblock[i];
|
||||||
|
#ifdef REISERDEBUG
|
||||||
|
printf ("block %d is in journal %d.\n",
|
||||||
|
desc.j_realblock[i], desc_block);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
for ( ; i < desc.j_len; i++)
|
for ( ; i < desc.j_len; i++)
|
||||||
|
{
|
||||||
*journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
|
*journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
|
||||||
|
#ifdef REISERDEBUG
|
||||||
|
printf ("block %d is in journal %d.\n",
|
||||||
|
commit.j_realblock[i-JOURNAL_TRANS_HALF],
|
||||||
|
desc_block);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
desc_block = (commit_block + 1) & (block_count - 1);
|
desc_block = (commit_block + 1) & (block_count - 1);
|
||||||
}
|
}
|
||||||
|
#ifdef REISERDEBUG
|
||||||
|
printf ("Transaction %d/%d at %d isn't valid.\n",
|
||||||
|
desc.j_trans_id, desc.j_mount_id, desc_block);
|
||||||
|
#endif
|
||||||
|
|
||||||
INFO->journal_transactions = next_trans_id - header.j_last_flush_trans_id;
|
INFO->journal_transactions = next_trans_id - header.j_last_flush_trans_id;
|
||||||
return errnum == 0;
|
return errnum == 0;
|
||||||
}
|
}
|
||||||
|
@ -594,23 +640,60 @@ reiserfs_mount (void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************** TREE ACCESSING METHODS *****************************/
|
||||||
|
|
||||||
|
/* I assume you are familiar with the ReiserFS tree, if not go to
|
||||||
|
* http://devlinux.com/projects/reiserfs/
|
||||||
|
*
|
||||||
|
* My tree node cache is organized as following
|
||||||
|
* 0 ROOT node
|
||||||
|
* 1 LEAF node (if the ROOT is also a LEAF it is copied here
|
||||||
|
* 2-n other nodes on current path from bottom to top.
|
||||||
|
* if there is not enough space in the cache, the top most are
|
||||||
|
* omitted.
|
||||||
|
*
|
||||||
|
* I have only two methods to find a key in the tree:
|
||||||
|
* search_stat(dir_id, objectid) searches for the stat entry (always
|
||||||
|
* the first entry) of an object.
|
||||||
|
* next_key() gets the next key in tree order.
|
||||||
|
*
|
||||||
|
* This means, that I can only sequential reads of files are
|
||||||
|
* efficient, but this really doesn't hurt for grub.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Read in the node at the current path and depth into the node cache.
|
||||||
|
* You must set INFO->blocks[depth] before.
|
||||||
|
*/
|
||||||
static char *
|
static char *
|
||||||
read_tree_node (int depth)
|
read_tree_node (unsigned int blockNr, int depth)
|
||||||
{
|
{
|
||||||
char* cache = CACHE (depth > INFO->cached_slots ? 1 : depth);
|
char* cache = CACHE(depth);
|
||||||
|
int num_cached = INFO->cached_slots;
|
||||||
|
if (depth < num_cached)
|
||||||
|
{
|
||||||
|
/* This is the cached part of the path. Check if same block is
|
||||||
|
* needed.
|
||||||
|
*/
|
||||||
|
if (blockNr == INFO->blocks[depth])
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cache = CACHE(num_cached);
|
||||||
|
|
||||||
#ifdef REISERDEBUG
|
#ifdef REISERDEBUG
|
||||||
printf (" next read_in: block=%d (depth=%d)\n",
|
printf (" next read_in: block=%d (depth=%d)\n",
|
||||||
INFO->blocks[depth], depth);
|
blockNr, depth);
|
||||||
#endif /* REISERDEBUG */
|
#endif /* REISERDEBUG */
|
||||||
if (! block_read (INFO->blocks[depth], 0, INFO->blocksize, cache))
|
if (! block_read (blockNr, 0, INFO->blocksize, cache))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Make sure it has the right node level */
|
/* Make sure it has the right node level */
|
||||||
if (BLOCKHEAD (cache)->blk_level != depth)
|
if (BLOCKHEAD (cache)->blk_level != depth)
|
||||||
{
|
{
|
||||||
errnum = ERR_FSYS_CORRUPT;
|
errnum = ERR_FSYS_CORRUPT;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INFO->blocks[depth] = blockNr;
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,7 +741,11 @@ next_key (void)
|
||||||
else if (depth <= INFO->cached_slots)
|
else if (depth <= INFO->cached_slots)
|
||||||
cache = CACHE (depth);
|
cache = CACHE (depth);
|
||||||
else
|
else
|
||||||
goto read_at_depth;
|
{
|
||||||
|
cache = read_tree_node (INFO->blocks[depth], --depth);
|
||||||
|
if (! cache)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -670,10 +757,8 @@ next_key (void)
|
||||||
if (key_nr == nr_item)
|
if (key_nr == nr_item)
|
||||||
/* This is the last item in this block, set the next_key_nr to 0 */
|
/* This is the last item in this block, set the next_key_nr to 0 */
|
||||||
INFO->next_key_nr[depth] = 0;
|
INFO->next_key_nr[depth] = 0;
|
||||||
INFO->blocks[--depth] = DC (cache)[key_nr].dc_block_number;
|
|
||||||
|
|
||||||
read_at_depth:
|
cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth);
|
||||||
cache = read_tree_node (depth);
|
|
||||||
if (! cache)
|
if (! cache)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -742,9 +827,7 @@ search_stat (__u32 dir_id, __u32 objectid)
|
||||||
printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
|
printf (" depth=%d, i=%d/%d\n", depth, i, nr_item);
|
||||||
#endif /* REISERDEBUG */
|
#endif /* REISERDEBUG */
|
||||||
INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
|
INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
|
||||||
INFO->blocks[--depth] = DC (cache)[i].dc_block_number;
|
cache = read_tree_node (DC (cache)[i].dc_block_number, --depth);
|
||||||
|
|
||||||
cache = read_tree_node (depth);
|
|
||||||
if (! cache)
|
if (! cache)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -887,10 +970,14 @@ reiserfs_dir (char *dirname)
|
||||||
{
|
{
|
||||||
struct reiserfs_de_head *de_head;
|
struct reiserfs_de_head *de_head;
|
||||||
char *rest, ch;
|
char *rest, ch;
|
||||||
__u32 dir_id, objectid;
|
__u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
|
||||||
#ifndef STAGE1_5
|
#ifndef STAGE1_5
|
||||||
int do_possibilities = 0;
|
int do_possibilities = 0;
|
||||||
#endif /* ! STAGE1_5 */
|
#endif /* ! STAGE1_5 */
|
||||||
|
char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
|
||||||
|
int link_count = 0;
|
||||||
|
int mode;
|
||||||
|
|
||||||
dir_id = REISERFS_ROOT_PARENT_OBJECTID;
|
dir_id = REISERFS_ROOT_PARENT_OBJECTID;
|
||||||
objectid = REISERFS_ROOT_OBJECTID;
|
objectid = REISERFS_ROOT_OBJECTID;
|
||||||
|
|
||||||
|
@ -910,12 +997,71 @@ reiserfs_dir (char *dirname)
|
||||||
((struct stat_data *) INFO->current_item)->sd_size);
|
((struct stat_data *) INFO->current_item)->sd_size);
|
||||||
#endif /* REISERDEBUG */
|
#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)
|
||||||
|
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),
|
/* if we have a real file (and we're not just printing possibilities),
|
||||||
then this is where we want to exit */
|
then this is where we want to exit */
|
||||||
|
|
||||||
if (! *dirname || isspace (*dirname))
|
if (! *dirname || isspace (*dirname))
|
||||||
{
|
{
|
||||||
if (! S_ISREG (((struct stat_data *) INFO->current_item)->sd_mode))
|
if (! S_ISREG (mode))
|
||||||
{
|
{
|
||||||
errnum = ERR_BAD_FILETYPE;
|
errnum = ERR_BAD_FILETYPE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -939,7 +1085,7 @@ reiserfs_dir (char *dirname)
|
||||||
/* continue with the file/directory name interpretation */
|
/* continue with the file/directory name interpretation */
|
||||||
while (*dirname == '/')
|
while (*dirname == '/')
|
||||||
dirname++;
|
dirname++;
|
||||||
if (! S_ISDIR (((struct stat_data *) INFO->current_item)->sd_mode))
|
if (! S_ISDIR (mode))
|
||||||
{
|
{
|
||||||
errnum = ERR_BAD_FILETYPE;
|
errnum = ERR_BAD_FILETYPE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -979,9 +1125,12 @@ reiserfs_dir (char *dirname)
|
||||||
if ((de_head->deh_state & DEH_Visible))
|
if ((de_head->deh_state & DEH_Visible))
|
||||||
{
|
{
|
||||||
int cmp;
|
int cmp;
|
||||||
/* Note that this may also overwrite the next block in
|
/* Directory names in ReiserFS are not null
|
||||||
* the cache. But that doesn't hurt as long as we don't
|
* terminated. We write a temporary 0 behind it.
|
||||||
* call next_key (). */
|
* 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;
|
*name_end = 0;
|
||||||
cmp = substring (dirname, filename);
|
cmp = substring (dirname, filename);
|
||||||
*name_end = tmp;
|
*name_end = tmp;
|
||||||
|
@ -1024,6 +1173,8 @@ reiserfs_dir (char *dirname)
|
||||||
*rest = ch;
|
*rest = ch;
|
||||||
dirname = rest;
|
dirname = rest;
|
||||||
|
|
||||||
|
parent_dir_id = dir_id;
|
||||||
|
parent_objectid = objectid;
|
||||||
dir_id = de_head->deh_dir_id;
|
dir_id = de_head->deh_dir_id;
|
||||||
objectid = de_head->deh_objectid;
|
objectid = de_head->deh_objectid;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue