Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 106855
Collapse All | Expand All

(-)aboot-1.0_pre20040408/Makefile (-1 / +1 lines)
Lines 58-64 Link Here
58
	$(CC) $(ASFLAGS) -D__ASSEMBLY__ -traditional -c -o $*.o $<
58
	$(CC) $(ASFLAGS) -D__ASSEMBLY__ -traditional -c -o $*.o $<
59
59
60
NET_OBJS = net.o
60
NET_OBJS = net.o
61
DISK_OBJS = disk.o fs/ext2.o fs/ufs.o fs/dummy.o fs/iso.o
61
DISK_OBJS = disk.o fs/ext2.o fs/ufs.o fs/dummy.o fs/iso.o fs/reiserfs.o
62
ifeq ($(TESTING),)
62
ifeq ($(TESTING),)
63
ABOOT_OBJS = \
63
ABOOT_OBJS = \
64
	head.o aboot.o cons.o utils.o \
64
	head.o aboot.o cons.o utils.o \
(-)aboot-1.0_pre20040408/disk.c (-17 / +18 lines)
Lines 42-47 Link Here
42
extern struct bootfs iso;
42
extern struct bootfs iso;
43
extern struct bootfs ufs;
43
extern struct bootfs ufs;
44
extern struct bootfs dummyfs;
44
extern struct bootfs dummyfs;
45
extern struct bootfs reiserfs;
45
46
46
struct disklabel * label;
47
struct disklabel * label;
47
int boot_part = -1;
48
int boot_part = -1;
Lines 49-55 Link Here
49
static struct bootfs *bootfs[] = {
50
static struct bootfs *bootfs[] = {
50
	&ext2fs,
51
	&ext2fs,
51
	&iso,
52
	&iso,
52
	&ufs
53
	&ufs,
54
	&reiserfs,
55
	NULL
53
};
56
};
54
57
55
/*
58
/*
Lines 313-319 Link Here
313
		}
316
		}
314
	} else if (!label) {
317
	} else if (!label) {
315
		/* floppies and such, no disklabel */
318
		/* floppies and such, no disklabel */
316
		for (i = 0; i < (int)(sizeof(bootfs)/sizeof(bootfs[0])); ++i) {
319
		for (i = 0; bootfs[i] != NULL; ++i) {
317
			if ((*bootfs[i]->mount)(dev, 0, 1) >= 0) {
320
			if ((*bootfs[i]->mount)(dev, 0, 1) >= 0) {
318
				fs = bootfs[i];
321
				fs = bootfs[i];
319
				break;
322
				break;
Lines 329-349 Link Here
329
			return 0;
332
			return 0;
330
		}
333
		}
331
		part = &label->d_partitions[partition - 1];
334
		part = &label->d_partitions[partition - 1];
332
		for (i = 0; bootfs[i]->fs_type != part->p_fstype; ++i) {
335
		for (i = 0; bootfs[i] != NULL; ++i) {
333
			if (i + 1
336
			if (bootfs[i]->fs_type != part->p_fstype) continue;
334
			    >= (int) (sizeof(bootfs)/sizeof(bootfs[0])))
337
			fs = bootfs[i];
335
			{
338
			if ((*fs->mount)(dev, (long)(part->p_offset) *
336
				printf("aboot: don't know how to mount "
339
					(long)(label->d_secsize), 0) < 0) {
337
				       "partition %d (filesystem type %d)\n",
340
				printf("aboot: mount of partition %d failed\n",
338
				       partition, part->p_fstype);
341
				       partition);
339
				return 0;
342
			} else break;
340
			}
343
		}
341
		}
344
		if (bootfs[i] == NULL) {
342
		fs = bootfs[i];
345
			printf("aboot: don't know how to mount "
343
		if ((*fs->mount)(dev, (long)(part->p_offset) * (long)(label->d_secsize), 0)
346
			       "partition %d (filesystem type %d)\n",
344
		    < 0) {
347
			       partition, part->p_fstype);
345
			printf("aboot: mount of partition %d failed\n",
346
			       partition);
347
			return 0;
348
			return 0;
348
		}
349
		}
349
	}
350
	}
(-)aboot-1.0_pre20040408/fs/reiserfs.c (+1180 lines)
Line 0 Link Here
1
/* reiserfs.c - an implementation for the ReiserFS filesystem */
2
/*
3
 * This file was taken from GRUB and adapted to the aboot interface by
4
 * Ilia Mirkin [ibmirkin@gmail.com] in September 2005. Copyrights from
5
 * GRUB follow:
6
 *
7
 *  GRUB  --  GRand Unified Bootloader
8
 *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  (at your option) any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
 */
24
#include <asm/system.h>
25
26
#include <config.h>
27
#include <aboot.h>
28
#include <bootfs.h>
29
#include <cons.h>
30
#include <utils.h>
31
#include <disklabel.h>
32
#include <string.h>
33
34
#define BLOCKSIZE (16*SECT_SIZE)
35
36
//#define REISERDEBUG 1
37
#undef REISERDEBUG
38
39
#define ERR_FSYS_CORRUPT 2
40
41
/* Some parts of this code (mainly the structures and defines) are
42
 * from the original reiser fs code, as found in the linux kernel.
43
 */
44
45
/* include/asm-i386/types.h */
46
/*typedef __signed__ char __s8;
47
typedef unsigned char __u8;
48
typedef __signed__ short __s16;
49
typedef unsigned short __u16;
50
typedef __signed__ int __s32;
51
typedef unsigned int __u32;
52
typedef unsigned long long __u64;*/
53
54
/* linux/posix_type.h */
55
typedef long linux_off_t;
56
57
/* linux/little_endian.h */
58
/*#define __cpu_to_le64(x) ((__u64) (x))
59
#define __le64_to_cpu(x) ((__u64) (x))
60
#define __cpu_to_le32(x) ((__u32) (x))
61
#define __le32_to_cpu(x) ((__u32) (x))
62
#define __cpu_to_le16(x) ((__u16) (x))
63
#define __le16_to_cpu(x) ((__u16) (x))*/
64
65
/* include/linux/reiser_fs.h */
66
/* This is the new super block of a journaling reiserfs system */
67
struct reiserfs_super_block
68
{
69
  __u32 s_block_count;			/* blocks count         */
70
  __u32 s_free_blocks;                  /* free blocks count    */
71
  __u32 s_root_block;           	/* root block number    */
72
  __u32 s_journal_block;           	/* journal block number    */
73
  __u32 s_journal_dev;           	/* journal device number  */
74
  __u32 s_journal_size; 		/* size of the journal on FS creation.  used to make sure they don't overflow it */
75
  __u32 s_journal_trans_max;            /* max number of blocks in a transaction.  */
76
  __u32 s_journal_magic;                /* random value made on fs creation */
77
  __u32 s_journal_max_batch;            /* max number of blocks to batch into a trans */
78
  __u32 s_journal_max_commit_age;       /* in seconds, how old can an async commit be */
79
  __u32 s_journal_max_trans_age;        /* in seconds, how old can a transaction be */
80
  __u16 s_blocksize;                   	/* block size           */
81
  __u16 s_oid_maxsize;			/* max size of object id array  */
82
  __u16 s_oid_cursize;			/* current size of object id array */
83
  __u16 s_state;                       	/* valid or error       */
84
  char s_magic[16];                     /* reiserfs magic string indicates that file system is reiserfs */
85
  __u16 s_tree_height;                  /* height of disk tree */
86
  __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
87
  __u16 s_version;
88
  char s_unused[128];			/* zero filled by mkreiserfs */
89
};
90
91
#define REISERFS_MAX_SUPPORTED_VERSION 2
92
#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
93
#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
94
#define REISER3FS_SUPER_MAGIC_STRING "ReIsEr3Fs"
95
96
#define MAX_HEIGHT 7
97
98
/* must be correct to keep the desc and commit structs at 4k */
99
#define JOURNAL_TRANS_HALF 1018
100
101
/* first block written in a commit.  */
102
struct reiserfs_journal_desc {
103
  __u32 j_trans_id;			/* id of commit */
104
  __u32 j_len;				/* length of commit. len +1 is the commit block */
105
  __u32 j_mount_id;			/* mount id of this trans*/
106
  __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
107
  char j_magic[12];
108
};
109
110
/* last block written in a commit */
111
struct reiserfs_journal_commit {
112
  __u32 j_trans_id;			/* must match j_trans_id from the desc block */
113
  __u32 j_len;			/* ditto */
114
  __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
115
  char j_digest[16];			/* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
116
};
117
118
/* this header block gets written whenever a transaction is considered
119
   fully flushed, and is more recent than the last fully flushed
120
   transaction.  
121
   fully flushed means all the log blocks and all the real blocks are
122
   on disk, and this transaction does not need to be replayed.  
123
*/
124
struct reiserfs_journal_header {
125
  /* id of last fully flushed transaction */
126
  __u32 j_last_flush_trans_id;
127
  /* offset in the log of where to start replay after a crash */
128
  __u32 j_first_unflushed_offset;
129
  /* mount id to detect very old transactions */
130
  __u32 j_mount_id;
131
};
132
133
/* magic string to find desc blocks in the journal */
134
#define JOURNAL_DESC_MAGIC "ReIsErLB" 
135
136
137
/*
138
 * directories use this key as well as old files
139
 */
140
struct offset_v1
141
{
142
  /*
143
   * for regular files this is the offset to the first byte of the
144
   * body, contained in the object-item, as measured from the start of
145
   * the entire body of the object.
146
   *
147
   * for directory entries, k_offset consists of hash derived from
148
   * hashing the name and using few bits (23 or more) of the resulting
149
   * hash, and generation number that allows distinguishing names with
150
   * hash collisions. If number of collisions overflows generation
151
   * number, we return EEXIST.  High order bit is 0 always 
152
   */
153
  __u32 k_offset;
154
  __u32 k_uniqueness;
155
};
156
157
struct offset_v2
158
{
159
  /*
160
   * for regular files this is the offset to the first byte of the
161
   * body, contained in the object-item, as measured from the start of
162
   * the entire body of the object.
163
   *
164
   * for directory entries, k_offset consists of hash derived from
165
   * hashing the name and using few bits (23 or more) of the resulting
166
   * hash, and generation number that allows distinguishing names with
167
   * hash collisions. If number of collisions overflows generation
168
   * number, we return EEXIST.  High order bit is 0 always 
169
   */
170
  __u64 k_offset:60;
171
  __u64 k_type: 4;
172
};
173
174
175
struct key
176
{
177
  /* packing locality: by default parent directory object id */
178
  __u32 k_dir_id;
179
  /* object identifier */
180
  __u32 k_objectid;
181
  /* the offset and node type (old and new form) */
182
  union
183
  {
184
    struct offset_v1 v1;
185
    struct offset_v2 v2;
186
  }
187
  u;
188
};
189
190
#define KEY_SIZE (sizeof (struct key))
191
192
/* Header of a disk block.  More precisely, header of a formatted leaf
193
   or internal node, and not the header of an unformatted node. */
194
struct block_head
195
{       
196
  __u16 blk_level;        /* Level of a block in the tree. */
197
  __u16 blk_nr_item;      /* Number of keys/items in a block. */
198
  __u16 blk_free_space;   /* Block free space in bytes. */
199
  struct key  blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
200
				      only) */
201
};
202
#define BLKH_SIZE (sizeof (struct block_head))
203
#define DISK_LEAF_NODE_LEVEL  1 /* Leaf node level.                       */
204
205
struct item_head
206
{
207
  struct key ih_key; 	/* Everything in the tree is found by searching for it based on its key.*/
208
  
209
  union
210
  {
211
    __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this
212
			    is an indirect item.  This equals 0xFFFF iff this is a direct item or
213
			    stat data item. Note that the key, not this field, is used to determine
214
			    the item type, and thus which field this union contains. */
215
    __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory
216
			     entries in the directory item. */
217
  }
218
  u;
219
  __u16 ih_item_len;           /* total size of the item body                  */
220
  __u16 ih_item_location;      /* an offset to the item body within the block  */
221
  __u16 ih_version;	       /* ITEM_VERSION_1 for all old items, 
222
				  ITEM_VERSION_2 for new ones. 
223
				  Highest bit is set by fsck
224
                                  temporary, cleaned after all done */
225
};
226
/* size of item header     */
227
#define IH_SIZE (sizeof (struct item_head))
228
229
#define ITEM_VERSION_1 0
230
#define ITEM_VERSION_2 1
231
#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \
232
			   ? (ih)->ih_key.u.v1.k_offset \
233
			   : (ih)->ih_key.u.v2.k_offset)
234
235
#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \
236
				 ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \
237
				 : (ih)->ih_key.u.v2.k_type == V2_##type)
238
239
struct disk_child
240
{
241
  __u32       dc_block_number;              /* Disk child's block number. */
242
  __u16      dc_size;		            /* Disk child's used space.   */
243
    __u16      dc_reserved;
244
};
245
246
#define DC_SIZE (sizeof (struct disk_child))
247
248
/* Stat Data on disk.
249
 *
250
 * Note that reiserfs has two different forms of stat data.  Luckily
251
 * the fields needed by grub are at the same position.
252
 */
253
struct stat_data
254
{
255
  __u16 sd_mode;	/* file type, permissions */
256
  __u16 sd_notused1[3]; /* fields not needed by reiserfs */
257
  __u32 sd_size;	/* file size */
258
  __u32 sd_size_hi;	/* file size high 32 bits (since version 2) */
259
};
260
261
struct reiserfs_de_head
262
{
263
  __u32 deh_offset;  /* third component of the directory entry key */
264
  __u32 deh_dir_id;  /* objectid of the parent directory of the
265
			object, that is referenced by directory entry */
266
  __u32 deh_objectid;/* objectid of the object, that is referenced by
267
                        directory entry */
268
  __u16 deh_location;/* offset of name in the whole item */
269
  __u16 deh_state;   /* whether 1) entry contains stat data (for
270
			future), and 2) whether entry is hidden
271
			(unlinked) */
272
};
273
274
#define DEH_SIZE (sizeof (struct reiserfs_de_head))
275
276
#define DEH_Statdata (1 << 0)			/* not used now */
277
#define DEH_Visible  (1 << 2)
278
279
#define SD_OFFSET  0
280
#define SD_UNIQUENESS 0
281
#define DOT_OFFSET 1
282
#define DOT_DOT_OFFSET 2
283
#define DIRENTRY_UNIQUENESS 500
284
285
#define V1_TYPE_STAT_DATA 0x0
286
#define V1_TYPE_DIRECT 0xffffffff
287
#define V1_TYPE_INDIRECT 0xfffffffe
288
#define V1_TYPE_DIRECTORY_MAX 0xfffffffd
289
#define V2_TYPE_STAT_DATA 0
290
#define V2_TYPE_INDIRECT 1
291
#define V2_TYPE_DIRECT 2
292
#define V2_TYPE_DIRENTRY 3 
293
294
#define REISERFS_ROOT_OBJECTID 2
295
#define REISERFS_ROOT_PARENT_OBJECTID 1
296
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
297
/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
298
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
299
#define REISERFS_OLD_BLOCKSIZE 4096
300
301
#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
302
#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
303
#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
304
305
#define PATH_MAX       1024	/* include/linux/limits.h */
306
#define MAX_LINK_COUNT    5	/* number of symbolic links to follow */
307
308
/* The size of the node cache */
309
#define FSYSREISER_CACHE_SIZE 24*1024
310
#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
311
#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
312
313
/* Info about currently opened file */
314
struct fsys_reiser_fileinfo
315
{
316
  __u32 k_dir_id;
317
  __u32 k_objectid;
318
};
319
320
/* In memory info about the currently mounted filesystem */
321
struct fsys_reiser_info
322
{
323
  /* The last read item head */
324
  struct item_head *current_ih;
325
  /* The last read item */
326
  char *current_item;
327
  /* The information for the currently opened file */
328
  struct fsys_reiser_fileinfo fileinfo;
329
  /* The start of the journal */
330
  __u32 journal_block;
331
  /* The size of the journal */
332
  __u32 journal_block_count;
333
  /* The first valid descriptor block in journal
334
     (relative to journal_block) */
335
  __u32 journal_first_desc;
336
337
  /* The ReiserFS version. */
338
  __u16 version;
339
  /* The current depth of the reiser tree. */
340
  __u16 tree_depth;
341
  /* SECTOR_SIZE << blocksize_shift == blocksize. */
342
  __u8  blocksize_shift;
343
  /* 1 << full_blocksize_shift == blocksize. */
344
  __u8  fullblocksize_shift;
345
  /* The reiserfs block size  (must be a power of 2) */
346
  __u16 blocksize;
347
  /* The number of cached tree nodes */
348
  __u16 cached_slots;
349
  /* The number of valid transactions in journal */
350
  __u16 journal_transactions;
351
  
352
  unsigned int blocks[MAX_HEIGHT];
353
  unsigned int next_key_nr[MAX_HEIGHT];
354
};
355
356
/* The cached s+tree blocks in FSYS_BUF,  see below
357
 * for a more detailed description.
358
 */
359
360
#define FSYS_BUF ((__u64)fsys_buffer)
361
#define FSYS_BUFLEN  (0x8000L)
362
363
#define ROOT     ((char *) ((__u64) FSYS_BUF))
364
#define CACHE(i) (ROOT + (((__u64)i) << INFO->fullblocksize_shift))
365
#define LEAF     CACHE (DISK_LEAF_NODE_LEVEL)
366
367
#define BLOCKHEAD(cache) ((struct block_head *) cache)
368
#define ITEMHEAD         ((struct item_head  *) ((__u64) LEAF + BLKH_SIZE))
369
#define KEY(cache)       ((struct key        *) ((__u64) cache + BLKH_SIZE))
370
#define DC(cache)        ((struct disk_child *) \
371
			  ((__u64) cache + BLKH_SIZE + KEY_SIZE * nr_item))
372
/* The fsys_reiser_info block.
373
 */
374
#define INFO \
375
    ((struct fsys_reiser_info *) ((__u64) FSYS_BUF + FSYSREISER_CACHE_SIZE))
376
/* 
377
 * The journal cache.  For each transaction it contains the number of
378
 * blocks followed by the real block numbers of this transaction.  
379
 *
380
 * If the block numbers of some transaction won't fit in this space,
381
 * this list is stopped with a 0xffffffff marker and the remaining
382
 * uncommitted transactions aren't cached.  
383
 */
384
#define JOURNAL_START    ((__u32 *) (INFO + 1))
385
#define JOURNAL_END      ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
386
387
#define MAX_OPEN_FILES 5
388
389
static struct fd_table_entry {
390
    struct item_head *ih;
391
    char *current_item;
392
    int current_item_pos;
393
    int used;
394
    char *cur_name;
395
    int mode;
396
    struct fsys_reiser_fileinfo fileinfo;
397
} fd_table[MAX_OPEN_FILES];
398
399
static int errnum = 0;
400
401
static __inline__ unsigned long
402
log2 (unsigned long word)
403
{
404
  __asm__ ("bsfl %1,%0"
405
	   : "=r" (word)
406
	   : "r" (word));
407
  return word;
408
}
409
410
static __inline__ int
411
is_power_of_two (unsigned long word)
412
{
413
  return (word & -word) == word;
414
}
415
416
static int reiserfs_mount(long cons_dev, long p_offset, long quiet);
417
static int reiserfs_bread(int fd, long blkno, long nblks, char *buffer);
418
static int reiserfs_open(const char *filename);
419
static void reiserfs_close(int fd);
420
static const char *reiserfs_readdir(int fd, int rewind);
421
static int next_key(int);
422
static int search_stat(int, __u32, __u32);
423
424
struct bootfs reiserfs = {
425
	FS_EXT2, 0,
426
	reiserfs_mount,
427
	reiserfs_open,  reiserfs_bread,  reiserfs_close,
428
        reiserfs_readdir
429
};
430
431
int isspace(char ch) {
432
    if (ch == ' ' || ch == '\r' || ch == '\n') return 1;
433
    return 0;
434
}
435
436
static long dev = -1;
437
static long partition_offset = 0;
438
439
static void *fsys_buffer;
440
441
static int devread(int sector, int byte_offset, int byte_len, char *buf) {
442
    //printf("devread(sector = %d, offt = %d, len = %d, buf = %p)\n", sector,
443
    //       byte_offset, byte_len, buf);
444
    if (sector < 0) {
445
        return 0;
446
    }
447
448
    long offset = (((long)sector) << 9) + partition_offset + byte_offset;
449
    return cons_read(dev, buf, byte_len, offset);
450
}
451
452
static int 
453
journal_read (int block, int len, char *buffer) 
454
{
455
    //printf("journal_read(block = %d, len = %d, buffer = %p)\n", block, len, buffer);
456
    return devread ((int)((INFO->journal_block + block) << INFO->blocksize_shift),
457
                    0, len, buffer);
458
}
459
460
/* Read a block from ReiserFS file system, taking the journal into
461
 * account.  If the block nr is in the journal, the block from the
462
 * journal taken.  
463
 */
464
static int
465
block_read (int blockNr, int start, int len, char *buffer)
466
{
467
468
    //printf("block_read(blockNr = %d, start = %d, len = %d, buffer = %p)\n", blockNr,
469
    //       start, len, buffer);
470
471
    int transactions = INFO->journal_transactions;
472
    int desc_block = INFO->journal_first_desc;
473
    int journal_mask = INFO->journal_block_count - 1;
474
    int translatedNr = blockNr;
475
    __u32 *journal_table = JOURNAL_START;
476
    while (transactions-- > 0) {
477
        int i = 0;
478
        int j_len;
479
        if (*journal_table != 0xffffffff) {
480
            /* Search for the blockNr in cached journal */
481
            j_len = *journal_table++;
482
            while (i++ < j_len) {
483
                if (*journal_table++ == blockNr) {
484
                    journal_table += j_len - i;
485
                    goto found;
486
                }
487
            }
488
        } else {
489
            /* This is the end of cached journal marker.  The remaining
490
             * transactions are still on disk.
491
             */
492
            struct reiserfs_journal_desc   desc;
493
            struct reiserfs_journal_commit commit;
494
            
495
            if (! journal_read (desc_block, sizeof (desc), (char *) &desc))
496
                return 0;
497
            
498
            j_len = desc.j_len;
499
            while (i < j_len && i < JOURNAL_TRANS_HALF)
500
                if (desc.j_realblock[i++] == blockNr)
501
                    goto found;
502
            
503
            if (j_len >= JOURNAL_TRANS_HALF) {
504
                int commit_block = (desc_block + 1 + j_len) & journal_mask;
505
                if (! journal_read (commit_block, 
506
                                    sizeof (commit), (char *) &commit))
507
                    return 0;
508
                while (i < j_len)
509
                    if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr)
510
                        goto found;
511
            }
512
        }
513
        goto not_found;
514
        
515
    found:
516
        translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
517
#ifdef REISERDEBUG
518
        printf ("block_read: block %d is mapped to journal block %d.\n", 
519
                blockNr, translatedNr - INFO->journal_block);
520
#endif
521
        /* We must continue the search, as this block may be overwritten
522
         * in later transactions.
523
         */
524
    not_found:
525
        desc_block = (desc_block + 2 + j_len) & journal_mask;
526
    }
527
    return devread (translatedNr << INFO->blocksize_shift, start, len, buffer);
528
}
529
530
/* Init the journal data structure.  We try to cache as much as
531
 * possible in the JOURNAL_START-JOURNAL_END space, but if it is full
532
 * we can still read the rest from the disk on demand.
533
 *
534
 * The first number of valid transactions and the descriptor block of the
535
 * first valid transaction are held in INFO.  The transactions are all 
536
 * adjacent, but we must take care of the journal wrap around. 
537
 */
538
static int
539
journal_init (void)
540
{
541
    //printf("in journal_init()\n");
542
543
    unsigned int block_count = INFO->journal_block_count;
544
    unsigned int desc_block;
545
    unsigned int commit_block;
546
    unsigned int next_trans_id;
547
    struct reiserfs_journal_header header;
548
    struct reiserfs_journal_desc   desc;
549
    struct reiserfs_journal_commit commit;
550
    __u32 *journal_table = JOURNAL_START;
551
    
552
    journal_read (block_count, sizeof (header), (char *) &header);
553
    desc_block = header.j_first_unflushed_offset;
554
    if (desc_block >= block_count)
555
        return 0;
556
    
557
    INFO->journal_first_desc = desc_block;
558
    next_trans_id = header.j_last_flush_trans_id + 1;
559
    
560
#ifdef REISERDEBUG
561
    printf ("journal_init: last flushed %d\n", 
562
            header.j_last_flush_trans_id);
563
#endif
564
565
    while (1) {
566
        journal_read (desc_block, sizeof (desc), (char *) &desc);
567
        if (strcmp(JOURNAL_DESC_MAGIC, desc.j_magic) ||
568
            desc.j_trans_id != next_trans_id ||
569
            desc.j_mount_id != header.j_mount_id)
570
            /* no more valid transactions */
571
            break;
572
      
573
        commit_block = (desc_block + desc.j_len + 1) & (block_count - 1);
574
        journal_read (commit_block, sizeof (commit), (char *) &commit);
575
        if (desc.j_trans_id != commit.j_trans_id
576
            || desc.j_len != commit.j_len)
577
            /* no more valid transactions */
578
            break;
579
      
580
#ifdef REISERDEBUG
581
        printf ("Found valid transaction %d/%d at %d.\n", 
582
                desc.j_trans_id, desc.j_mount_id, desc_block);
583
#endif
584
585
        next_trans_id++;
586
        if (journal_table < JOURNAL_END) {
587
            if ((journal_table + 1 + desc.j_len) >= JOURNAL_END) {
588
                /* The table is almost full; mark the end of the cached
589
                 * journal.*/
590
                *journal_table = 0xffffffff;
591
                journal_table = JOURNAL_END;
592
	    } else {
593
                int i;
594
                /* Cache the length and the realblock numbers in the table.
595
                 * The block number of descriptor can easily be computed.
596
                 * and need not to be stored here.
597
                 */
598
                *journal_table++ = desc.j_len;
599
                for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++) {
600
                    *journal_table++ = desc.j_realblock[i];
601
#ifdef REISERDEBUG
602
                    printf ("block %d is in journal %d.\n", 
603
                            desc.j_realblock[i], desc_block);
604
#endif
605
		}
606
                for (     ; i < desc.j_len; i++) {
607
                    *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
608
#ifdef REISERDEBUG
609
                    printf ("block %d is in journal %d.\n", 
610
                            commit.j_realblock[i-JOURNAL_TRANS_HALF], 
611
                            desc_block);
612
#endif
613
		}
614
	    }
615
	}
616
        desc_block = (commit_block + 1) & (block_count - 1);
617
    }
618
#ifdef REISERDEBUG
619
    printf ("Transaction %d/%d at %d isn't valid.\n", 
620
            desc.j_trans_id, desc.j_mount_id, desc_block);
621
#endif
622
623
    INFO->journal_transactions
624
        = next_trans_id - header.j_last_flush_trans_id - 1;
625
    return errnum == 0;
626
}
627
628
629
/*
630
 * Initialize 'filesystem' 
631
 * Returns 0 if successful, -1 on failure.
632
 */
633
static int
634
reiserfs_mount(long cons_dev, long p_offset, long quiet)
635
{
636
    struct reiserfs_super_block super;
637
    dev = cons_dev;
638
    partition_offset = p_offset;
639
    int superblock = REISERFS_DISK_OFFSET_IN_BYTES;
640
    
641
    memset(fd_table, 0, sizeof(fd_table));
642
643
    if (!cons_read(dev, &super, sizeof(super), partition_offset + superblock) ||
644
        (strcmp(REISER3FS_SUPER_MAGIC_STRING, super.s_magic) &&
645
         strcmp(REISER2FS_SUPER_MAGIC_STRING, super.s_magic) &&
646
         strcmp(REISERFS_SUPER_MAGIC_STRING, super.s_magic)) ||
647
        (super.s_journal_block * super.s_blocksize <= 
648
         REISERFS_DISK_OFFSET_IN_BYTES)) {
649
        printf("FIXME: check for old partition type.\n");
650
        printf("ReiserFS partition not found\n");
651
        return -1;
652
    }
653
654
    if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION) return -1;
655
656
#define SECTOR_BITS                9
657
#define SECTOR_SIZE                0x200
658
659
    fsys_buffer = malloc(0x8000);
660
661
    INFO->version = super.s_version;
662
    INFO->blocksize = super.s_blocksize;
663
    reiserfs.blocksize = super.s_blocksize;
664
    INFO->fullblocksize_shift = 12;//log2 (super.s_blocksize);
665
    //printf("expecting s_blocksize to be 4096. it is %d\n", super.s_blocksize);
666
    INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
667
    INFO->cached_slots = (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
668
    
669
    if (!quiet) {
670
        printf("reiserfs_mount: version = %d, blocksize = %d, root block = %d\n",
671
               super.s_version, super.s_blocksize, super.s_root_block);
672
    }
673
674
    memset(INFO->blocks, 0, sizeof(INFO->blocks));
675
676
    if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE || 
677
        super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE ||
678
        (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize)
679
        return -1;
680
681
    INFO->journal_transactions = 0;
682
683
    if (super.s_journal_block != 0 && super.s_journal_dev == 0) {
684
        INFO->journal_block = super.s_journal_block;
685
        INFO->journal_block_count = super.s_journal_size;
686
        if (is_power_of_two (INFO->journal_block_count))
687
            journal_init ();
688
689
        /* Read in super block again, maybe it is in the journal */
690
        block_read (superblock >> INFO->fullblocksize_shift, 
691
                    0, sizeof (struct reiserfs_super_block), (char *) &super);
692
    }
693
694
    if (! block_read (super.s_root_block, 0, INFO->blocksize, (char*) ROOT))
695
        return -1;
696
  
697
    INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level;
698
  
699
#ifdef REISERDEBUG
700
    printf ("root read_in: block=%d, depth=%d\n", 
701
            super.s_root_block, INFO->tree_depth);
702
#endif /* REISERDEBUG */
703
704
    if (INFO->tree_depth >= MAX_HEIGHT)
705
        return -1;
706
    if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL) {
707
        /* There is only one node in the whole filesystem, 
708
         * which is simultanously leaf and root */
709
        memcpy (LEAF, ROOT, INFO->blocksize);
710
    }
711
712
    return 0;
713
}
714
715
716
/*
717
 * Read block number "blkno".
718
 */
719
static int
720
reiserfs_bread(int fd, long blkno, long nblks, char *buffer)
721
{
722
    //ok. this is going to be highly inefficient. seek to the
723
    //beginning of the file, then go to the block and read that data
724
    //into the buffer.
725
    search_stat(fd, fd_table[fd].fileinfo.k_dir_id, fd_table[fd].fileinfo.k_objectid);
726
727
    unsigned int blocksize;
728
    unsigned int offset;
729
    unsigned int to_read;
730
    char *prev_buf = buffer;
731
    long len = (blkno + nblks) * INFO->blocksize;
732
    long filepos = 0;
733
    errnum = 0;
734
  
735
#ifdef REISERDEBUG
736
    printf ("reiserfs_read: filepos=%d len=%d (really %d), offset=%x:%x\n",
737
            filepos, len, nblks * INFO->blocksize, (__u64) IH_KEY_OFFSET (fd_table[fd].ih) - 1);
738
#endif /* REISERDEBUG */
739
  
740
    goto get_next_key;
741
  
742
    while (! errnum) {
743
        if (fd_table[fd].ih->ih_key.k_objectid != fd_table[fd].fileinfo.k_objectid)
744
            break;
745
      
746
        offset = filepos - IH_KEY_OFFSET (fd_table[fd].ih) + 1;
747
        blocksize = fd_table[fd].ih->ih_item_len;
748
      
749
#ifdef REISERDEBUG
750
        printf ("  loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
751
                filepos, len, offset, blocksize);
752
#endif /* REISERDEBUG */
753
      
754
        if (IH_KEY_ISTYPE(fd_table[fd].ih, TYPE_DIRECT) && offset < blocksize) {
755
#ifdef REISERDEBUG
756
            printf ("direct_read: offset=%d, blocksize=%d\n",
757
                    offset, blocksize);
758
#endif /* REISERDEBUG */
759
            to_read = blocksize - offset;
760
            if (to_read > len)
761
                to_read = len;
762
763
            if (filepos < blkno * INFO->blocksize) {
764
                if (filepos + to_read > blkno * INFO->blocksize) {
765
                    int change = blkno * INFO->blocksize - filepos;
766
                    len -= change;
767
                    offset += change;
768
                    filepos += change;
769
                    to_read -= change;
770
                } else {
771
                    goto update_buf_len;
772
                }
773
            }
774
	    memcpy (buffer, fd_table[fd].current_item + offset, to_read);
775
            buffer += to_read;
776
            goto update_buf_len;
777
	} else if (IH_KEY_ISTYPE(fd_table[fd].ih, TYPE_INDIRECT)) {
778
            blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
779
#ifdef REISERDEBUG
780
            printf ("indirect_read: offset=%d, blocksize=%d\n",
781
                    offset, blocksize);
782
#endif /* REISERDEBUG */
783
	  
784
            while (offset < blocksize) {
785
                __u32 blocknr = ((__u32 *) fd_table[fd].current_item)
786
                    [offset >> INFO->fullblocksize_shift];
787
                int blk_offset = offset & (INFO->blocksize-1);
788
	      
789
                to_read = INFO->blocksize - blk_offset;
790
                if (to_read > len)
791
                    to_read = len;
792
	      
793
                if (filepos < blkno * INFO->blocksize) {
794
                    if (filepos + to_read > blkno * INFO->blocksize) {
795
                        int change = blkno * INFO->blocksize - filepos;
796
                        len -= change;
797
                        offset += change;
798
                        blk_offset += change;
799
                        filepos += change;
800
                        to_read -= change;
801
                    } else {
802
                        goto update_buf_len;
803
                    }
804
                }
805
806
                /* Journal is only for meta data.  Data blocks can be read
807
                 * directly without using block_read
808
                 */
809
                devread (blocknr << INFO->blocksize_shift,
810
                         blk_offset, to_read, buffer);
811
	      
812
                buffer += to_read;
813
	    update_buf_len:
814
                len -= to_read;
815
                offset += to_read;
816
                filepos += to_read;
817
                if (len == 0)
818
                    goto done;
819
	    }
820
	}
821
    get_next_key:
822
        next_key (fd);
823
    }
824
 done:
825
    return errnum ? -errnum : buffer - prev_buf;
826
}
827
828
829
/*
830
 * Unix-like open routine.  Returns a small integer 
831
 * (does not care what file, we say it's OK)
832
 */
833
static int reiserfs_open(const char *filename)
834
{
835
    struct reiserfs_de_head *de_head;
836
    __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
837
838
    int fd;
839
840
    char filname[128];
841
    char *fname = filname;
842
843
    if (strlen(fname) > 127) return -1;
844
    strncpy(fname, filename, 127);
845
846
    dir_id = REISERFS_ROOT_PARENT_OBJECTID;
847
    objectid = REISERFS_ROOT_OBJECTID;
848
849
    for (fd = 0; fd < MAX_OPEN_FILES; fd++) {
850
        if (fd_table[fd].used == 0) {
851
            break;
852
        }
853
    }
854
855
    if (fd == MAX_OPEN_FILES) {
856
        printf("reiserfs: no free fd's\n");
857
        return -1;
858
    }
859
860
    while (1) {
861
        //find object id (starts with /, then goes on from there)
862
        if (!search_stat(fd, dir_id, objectid))
863
            return -1;
864
865
        fd_table[fd].mode = ((struct stat_data *)fd_table[fd].current_item)->sd_mode;
866
867
        if (S_ISLNK(fd_table[fd].mode)) {
868
            printf("symlink detected in path -- currently not supported\n");
869
            return -1;
870
        }
871
872
        //remove prepended /'s
873
        while (*fname == '/') fname++;
874
875
        if (*fname == 0 || isspace(*fname)) {
876
            //we must have found it!
877
            fd_table[fd].current_item_pos = 0;
878
            fd_table[fd].fileinfo.k_dir_id = dir_id;
879
            fd_table[fd].fileinfo.k_objectid = objectid;
880
            //printf("calling next_key to init file (fd = %d)\n", fd);
881
            next_key(fd);
882
            //printf("open: found (fd = %d)!\n", fd);
883
            fd_table[fd].used = 1;
884
            return fd;
885
        }
886
887
        char *rest;
888
        char ch;
889
        //figure out what directory/file we want to find
890
        for (rest = fname; (ch = *rest) && !isspace(ch) && ch != '/'; rest++);
891
        *rest = 0;
892
893
        //find that directory/file
894
        while (1) {
895
            char *name_end;
896
            int num_entries;
897
898
            if (!next_key(fd))
899
                return -1;
900
901
            if (fd_table[fd].ih->ih_key.k_objectid != objectid) {
902
                break;
903
            }
904
905
            name_end = fd_table[fd].current_item + fd_table[fd].ih->ih_item_len;
906
            de_head = (struct reiserfs_de_head *) fd_table[fd].current_item;
907
            num_entries = fd_table[fd].ih->u.ih_entry_count;
908
            while (num_entries > 0) {
909
                char *name = fd_table[fd].current_item + de_head->deh_location;
910
                if ((de_head->deh_state & DEH_Visible)) {
911
                    int cmp;
912
                    char tmp = *name_end;
913
                    *name_end = 0;
914
                    cmp = strcmp(name, fname);
915
                    *name_end = tmp;
916
                    if (cmp == 0) goto found;
917
                }
918
                name_end = name;
919
                de_head++;
920
                num_entries--;
921
            }
922
        }
923
        *rest = ch;
924
        return -1;
925
    found:
926
        *rest = ch;
927
        fname = rest;
928
929
        parent_dir_id = dir_id;
930
        parent_objectid = objectid;
931
        dir_id = de_head->deh_dir_id;
932
        objectid = de_head->deh_objectid;
933
    }
934
}
935
936
937
static void reiserfs_close(int fd)
938
{
939
    if (fd_table[fd].cur_name) free(fd_table[fd].cur_name);
940
    fd_table[fd].cur_name = NULL;
941
    fd_table[fd].used = 0;
942
}
943
944
static const char *reiserfs_readdir(int fd, int rewind)
945
{
946
    //printf("readdir(%d)\n", fd);
947
    struct reiserfs_de_head *de_head;
948
    if (fd_table[fd].ih->u.ih_entry_count <= 
949
        fd_table[fd].current_item_pos) return NULL;
950
    if (fd_table[fd].cur_name == NULL) {
951
        fd_table[fd].cur_name = malloc(128);
952
    }
953
    de_head = (struct reiserfs_de_head *) fd_table[fd].current_item;
954
    de_head += fd_table[fd].current_item_pos;
955
956
    /*printf("from %p for %d bytes\n", fd_table[fd].current_item + de_head->deh_location,
957
           fd_table[fd].ih->ih_item_len - de_head->deh_location);
958
    */
959
    if ((de_head->deh_state & DEH_Visible)) {
960
        strncpy(fd_table[fd].cur_name,
961
                fd_table[fd].current_item + de_head->deh_location, 
962
                fd_table[fd].ih->ih_item_len - de_head->deh_location);
963
        fd_table[fd].cur_name[127] = 0;
964
        fd_table[fd].current_item_pos++;
965
        return fd_table[fd].cur_name;
966
    } else {
967
        fd_table[fd].current_item_pos++;
968
        return reiserfs_readdir(fd, rewind);
969
    }
970
}
971
972
/***************** TREE ACCESSING METHODS *****************************/
973
974
/* I assume you are familiar with the ReiserFS tree, if not go to
975
 * http://www.namesys.com/content_table.html
976
 *
977
 * My tree node cache is organized as following
978
 *   0   ROOT node
979
 *   1   LEAF node  (if the ROOT is also a LEAF it is copied here
980
 *   2-n other nodes on current path from bottom to top.  
981
 *       if there is not enough space in the cache, the top most are
982
 *       omitted.
983
 *
984
 * I have only two methods to find a key in the tree:
985
 *   search_stat(dir_id, objectid) searches for the stat entry (always
986
 *       the first entry) of an object.
987
 *   next_key() gets the next key in tree order.
988
 *
989
 * This means, that I can only sequential reads of files are
990
 * efficient, but this really doesn't hurt for grub.  
991
 */
992
993
/* Read in the node at the current path and depth into the node cache.
994
 * You must set INFO->blocks[depth] before.
995
 */
996
static char *
997
read_tree_node (unsigned int blockNr, int depth)
998
{
999
  char* cache = CACHE(depth);
1000
  int num_cached = INFO->cached_slots;
1001
  if (depth < num_cached)
1002
    {
1003
      /* This is the cached part of the path.  Check if same block is
1004
       * needed.  
1005
       */
1006
      if (0 && blockNr == INFO->blocks[depth])
1007
	return cache;
1008
    }
1009
  else
1010
    cache = CACHE(num_cached);
1011
1012
#ifdef REISERDEBUG
1013
  //printf ("  next read_in: block=%d (depth=%d)\n",
1014
  //blockNr, depth);
1015
#endif /* REISERDEBUG */
1016
  if (! block_read (blockNr, 0, INFO->blocksize, cache))
1017
    return 0;
1018
  /* Make sure it has the right node level */
1019
  if (BLOCKHEAD (cache)->blk_level != depth)
1020
    {
1021
      errnum = ERR_FSYS_CORRUPT;
1022
      return 0;
1023
    }
1024
1025
  INFO->blocks[depth] = blockNr;
1026
  return cache;
1027
}
1028
1029
/* Get the next key, i.e. the key following the last retrieved key in
1030
 * tree order.  INFO->current_ih and 
1031
 * INFO->current_info are adapted accordingly.  */
1032
static int
1033
next_key (int fd)
1034
{
1035
  int depth;
1036
  struct item_head *ih = fd_table[fd].ih + 1;
1037
  char *cache;
1038
  
1039
  if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item])
1040
    {
1041
      depth = DISK_LEAF_NODE_LEVEL;
1042
      /* The last item, was the last in the leaf node.  
1043
       * Read in the next block 
1044
       */
1045
      do
1046
	{
1047
	  if (depth == INFO->tree_depth)
1048
	    {
1049
	      /* There are no more keys at all.
1050
	       * Return a dummy item with MAX_KEY */
1051
	      ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
1052
	      goto found;
1053
	    }
1054
	  depth++;
1055
#ifdef REISERDEBUG
1056
	  printf ("  depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
1057
#endif /* REISERDEBUG */
1058
	}
1059
      while (INFO->next_key_nr[depth] == 0);
1060
      
1061
      if (depth == INFO->tree_depth)
1062
	cache = ROOT;
1063
      else if (depth <= INFO->cached_slots)
1064
	cache = CACHE (depth);
1065
      else 
1066
	{
1067
	  cache = read_tree_node (INFO->blocks[depth], depth);
1068
	  if (! cache)
1069
	    return 0;
1070
	}
1071
      
1072
      do
1073
	{
1074
	  int nr_item = BLOCKHEAD (cache)->blk_nr_item;
1075
	  int key_nr = INFO->next_key_nr[depth]++;
1076
#ifdef REISERDEBUG
1077
	  printf ("  depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
1078
#endif /* REISERDEBUG */
1079
	  if (key_nr == nr_item)
1080
	    /* This is the last item in this block, set the next_key_nr to 0 */
1081
	    INFO->next_key_nr[depth] = 0;
1082
1083
	  cache = read_tree_node (DC (cache)[key_nr].dc_block_number, --depth);
1084
	  if (! cache)
1085
	    return 0;
1086
	}
1087
      while (depth > DISK_LEAF_NODE_LEVEL);
1088
      
1089
      ih = ITEMHEAD;
1090
    }
1091
 found:
1092
  fd_table[fd].ih   = ih;
1093
  fd_table[fd].current_item = &LEAF[ih->ih_item_location];
1094
#ifdef REISERDEBUG
1095
  printf ("  new ih: key %d:%d:%d:%d version:%d\n", 
1096
	  fd_table[fd].ih->ih_key.k_dir_id, 
1097
	  fd_table[fd].ih->ih_key.k_objectid, 
1098
	  fd_table[fd].ih->ih_key.u.v1.k_offset,
1099
	  fd_table[fd].ih->ih_key.u.v1.k_uniqueness,
1100
	  fd_table[fd].ih->ih_version);
1101
#endif /* REISERDEBUG */
1102
  return 1;
1103
}
1104
1105
/* preconditions: reiserfs_mount already executed, therefore 
1106
 *   INFO block is valid
1107
 * returns: 0 if error (errnum is set), 
1108
 *   nonzero iff we were able to find the key successfully.
1109
 * postconditions: on a nonzero return, the current_ih and 
1110
 *   current_item fields describe the key that equals the
1111
 *   searched key.  INFO->next_key contains the next key after
1112
 *   the searched key.
1113
 * side effects: messes around with the cache.
1114
 */
1115
static int
1116
search_stat (int fd, __u32 dir_id, __u32 objectid) 
1117
{
1118
  char *cache;
1119
  int depth;
1120
  int nr_item;
1121
  int i;
1122
  struct item_head *ih;
1123
#ifdef REISERDEBUG
1124
  printf ("search_stat (%d):\n  key %d:%d:0:0\n", fd, dir_id, objectid);
1125
#endif /* REISERDEBUG */
1126
  
1127
  depth = INFO->tree_depth;
1128
  cache = ROOT;
1129
  
1130
  while (depth > DISK_LEAF_NODE_LEVEL)
1131
    {
1132
      struct key *key;
1133
      nr_item = BLOCKHEAD (cache)->blk_nr_item;
1134
      
1135
      key = KEY (cache);
1136
      
1137
      for (i = 0; i < nr_item; i++) 
1138
	{
1139
	  if (key->k_dir_id > dir_id
1140
	      || (key->k_dir_id == dir_id 
1141
		  && (key->k_objectid > objectid
1142
		      || (key->k_objectid == objectid
1143
			  && ((__u32)(key->u.v1.k_offset
1144
			      | key->u.v1.k_uniqueness)) > 0))))
1145
	    break;
1146
	  key++;
1147
	}
1148
      
1149
#ifdef REISERDEBUG
1150
      printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
1151
      //printf ("      (%d:%d)\n", key->k_dir_id, key->k_objectid);
1152
#endif /* REISERDEBUG */
1153
      INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
1154
      cache = read_tree_node (DC (cache)[i].dc_block_number, --depth);
1155
      if (! cache)
1156
	return 0;
1157
    }
1158
  
1159
  /* cache == LEAF */
1160
  nr_item = BLOCKHEAD (LEAF)->blk_nr_item;
1161
  ih = ITEMHEAD;
1162
  for (i = 0; i < nr_item; i++) 
1163
    {
1164
      if (ih->ih_key.k_dir_id == dir_id 
1165
	  && ih->ih_key.k_objectid == objectid
1166
	  && ih->ih_key.u.v1.k_offset == 0
1167
	  && ih->ih_key.u.v1.k_uniqueness == 0)
1168
	{
1169
#ifdef REISERDEBUG
1170
            printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
1171
#endif /* REISERDEBUG */
1172
	  fd_table[fd].ih   = ih;
1173
	  fd_table[fd].current_item = &LEAF[ih->ih_item_location];
1174
	  return 1;
1175
        }
1176
      ih++;
1177
    }
1178
  errnum = ERR_FSYS_CORRUPT;
1179
  return 0;
1180
}

Return to bug 106855