21
21
#include "ext2fsP.h"
22
22
23
23
struct lookup_struct {
24
- const char * name ;
25
- int len ;
26
- ext2_ino_t * inode ;
27
- int found ;
24
+ const char * name ;
25
+ int len ;
26
+ ext2_ino_t * inode ;
27
+ int found ;
28
28
};
29
29
30
30
#ifdef __TURBOC__
@@ -33,14 +33,14 @@ struct lookup_struct {
33
33
static int lookup_proc (ext2_ino_t dir EXT2FS_ATTR ((unused )),
34
34
int entru EXT2FS_ATTR ( (unused )),
35
35
struct ext2_dir_entry * dirent ,
36
- int offset EXT2FS_ATTR ( (unused )),
37
- int blocksize EXT2FS_ATTR ( (unused )),
38
- char * buf EXT2FS_ATTR ((unused )),
39
- void * priv_data )
36
+ int offset EXT2FS_ATTR ( (unused )),
37
+ int blocksize EXT2FS_ATTR ( (unused )),
38
+ char * buf EXT2FS_ATTR ((unused )),
39
+ void * priv_data )
40
40
{
41
41
struct lookup_struct * ls = (struct lookup_struct * ) priv_data ;
42
42
43
- if (dirent -> inode == 0 )
43
+ if (dirent -> inode == 0 /* useless? */ )
44
44
return 0 ;
45
45
if (ls -> len != ext2fs_dirent_name_len (dirent ))
46
46
return 0 ;
@@ -51,6 +51,54 @@ static int lookup_proc(ext2_ino_t dir EXT2FS_ATTR((unused)),
51
51
return DIRENT_ABORT ;
52
52
}
53
53
54
+ /**
55
+ * @return 0 if the caller should continue to search, or errcode
56
+ */
57
+ static int htree_next_block (ext2_filsys fs , ext2_ino_t dir , struct ext2_inode * diri , struct dx_lookup_info * info ) {
58
+ errcode_t retval = 0 ;
59
+ struct dx_frame * p ;
60
+ int num_frames = 0 ;
61
+
62
+ p = & (info -> frames [info -> levels - 1 ]);
63
+ /*
64
+ * Find the next leaf page by incrementing the frame pointer.
65
+ * If we run out of entries in the interior node, loop around and
66
+ * increment pointer in the parent node. When we break out of
67
+ * this loop, num_frames indicates the number of interior
68
+ * nodes need to be read.
69
+ */
70
+ while (1 ) {
71
+ int count = ext2fs_le16_to_cpu (p -> head -> count );
72
+ if (++ (p -> at ) < p -> entries + count ) break ;
73
+ if (p == info -> frames ) return EXT2_ET_FILE_NOT_FOUND ;
74
+ num_frames ++ ;
75
+ p -- ;
76
+ }
77
+
78
+ __u32 next_hash = ext2fs_le32_to_cpu (p -> at -> hash );
79
+ if ((info -> hash & 1 ) == 0 /* useless? */ && (next_hash & ~1 ) != info -> hash ) {
80
+ return EXT2_ET_FILE_NOT_FOUND ;
81
+ }
82
+
83
+ while (num_frames -- ) {
84
+ e2_blkcnt_t blockcnt = ext2fs_le32_to_cpu (info -> frames [info -> levels - 1 ].at -> block ) & 0x0fffffff ;
85
+ p ++ ;
86
+ if ((retval = load_logical_dir_block (fs , dir , diri , blockcnt , & (p -> pblock ), p -> buf )) != 0 ) {
87
+ return retval ;
88
+ }
89
+ if ((retval = ext2fs_get_dx_countlimit (fs , p -> buf , & (p -> head ), NULL )) != 0 ) {
90
+ return retval ;
91
+ }
92
+ int count = ext2fs_le16_to_cpu (p -> head -> count );
93
+ int limit = ext2fs_le16_to_cpu (p -> head -> limit );
94
+ if (!count || count > limit ) {
95
+ return EXT2_ET_DIR_CORRUPTED ;
96
+ }
97
+ p -> at = p -> entries = (struct ext2_dx_entry * ) (p -> head );
98
+ }
99
+ return 0 ;
100
+ }
101
+
54
102
static errcode_t dx_namei (ext2_filsys fs , ext2_ino_t dir , struct ext2_inode * diri , const char * name , int namelen , char * buf , ext2_ino_t * res_inode ) {
55
103
struct dx_lookup_info dx_info ;
56
104
errcode_t retval = 0 ;
@@ -68,43 +116,48 @@ static errcode_t dx_namei(ext2_filsys fs, ext2_ino_t dir, struct ext2_inode *dir
68
116
if ((retval = dx_lookup (fs , dir , diri , & dx_info )) != 0 )
69
117
goto cleanup ;
70
118
71
- e2_blkcnt_t blockcnt = ext2fs_le32_to_cpu (dx_info .frames [dx_info .levels - 1 ].at -> block ) & 0x0fffffff ;
72
- if ((retval = load_logical_dir_block (fs , dir , diri , blockcnt , & leaf_pblk , buf )) != 0 )
73
- goto cleanup ;
74
-
75
- struct dir_context ctx ;
76
- struct lookup_struct ls ;
77
- ctx .errcode = 0 ;
78
- ctx .func = lookup_proc ;
79
- ctx .dir = dir ;
80
- ctx .flags = DIRENT_FLAG_INCLUDE_EMPTY ;
81
- ctx .buf = buf ;
82
- ctx .priv_data = & ls ;
119
+ do {
120
+ e2_blkcnt_t blockcnt = ext2fs_le32_to_cpu (dx_info .frames [dx_info .levels - 1 ].at -> block ) & 0x0fffffff ;
83
121
84
- ls .name = name ;
85
- ls .len = namelen ;
86
- ls .inode = res_inode ;
87
- ls .found = 0 ;
122
+ if ((retval = load_logical_dir_block (fs , dir , diri , blockcnt , & leaf_pblk , buf )) != 0 )
123
+ goto cleanup ;
88
124
89
- ext2fs_process_dir_block (fs , & leaf_pblk , blockcnt , 0 , 0 , & ctx );
90
- dx_release (& dx_info );
91
- if (ctx .errcode ) {
92
- retval = ctx .errcode ;
93
- goto cleanup ;
94
- }
125
+ struct dir_context ctx ;
126
+ struct lookup_struct ls ;
127
+ ctx .errcode = 0 ;
128
+ ctx .func = lookup_proc ;
129
+ ctx .dir = dir ;
130
+ ctx .flags = 0 ;
131
+ ctx .buf = buf ;
132
+ ctx .priv_data = & ls ;
133
+
134
+ ls .name = name ;
135
+ ls .len = namelen ;
136
+ ls .inode = res_inode ;
137
+ ls .found = 0 ;
138
+
139
+ ext2fs_process_dir_block (fs , & leaf_pblk , blockcnt , 0 , 0 , & ctx );
140
+ if (ctx .errcode ) {
141
+ retval = ctx .errcode ;
142
+ goto cleanup ;
143
+ }
144
+ if (ls .found ) {
145
+ break ;
146
+ }
147
+ retval = htree_next_block (fs , dir , diri , & dx_info );
148
+ } while (retval == 0 );
95
149
96
- if (!ls .found )
97
- retval = EXT2_ET_FILE_NOT_FOUND ;
98
150
cleanup :
99
151
if (block_buf ) {
100
152
ext2fs_free_mem (& block_buf );
101
153
}
154
+ dx_release (& dx_info );
102
155
103
156
return retval ;
104
157
}
105
158
106
159
errcode_t ext2fs_lookup (ext2_filsys fs , ext2_ino_t dir , const char * name ,
107
- int namelen , char * buf , ext2_ino_t * inode )
160
+ int namelen , char * buf , ext2_ino_t * inode )
108
161
{
109
162
errcode_t retval ;
110
163
struct lookup_struct ls ;
0 commit comments