1 Upstream-Status: inappropriate
3 From 3d47e37e21f6a2ced489d49e8bf5a5c24bb9baaf Mon Sep 17 00:00:00 2001
4 From: Corey Minyard <cminyard@mvista.com>
5 Date: Sun, 5 Jun 2011 09:36:11 -0500
6 Subject: [PATCH 04/19] Add a dirwalker for walking through directory entries
8 The code to walk directory items was messy, to say the least. Write a
9 clean structure to do this.
11 Also, remove d_name[0]. This is bad style, and newer compilers will
12 think it is really a zero-length array and will abort if trying to write
13 any data to it, since the compiler thinks it has no contents.
15 genext2fs.c | 210 +++++++++++++++++++++++++++++++++++++++++++----------------
16 1 files changed, 154 insertions(+), 56 deletions(-)
18 diff --git a/genext2fs.c b/genext2fs.c
19 index 0b5ba6f..03d1b27 100644
22 @@ -533,7 +533,6 @@ typedef struct
29 typedef uint8 block[BLOCKSIZE];
30 @@ -795,6 +794,8 @@ static inline uint8 *
33 unsigned char* b=calloc(1,BLOCKSIZE);
35 + error_msg_and_die("get_workblk() failed, out of memory");
39 @@ -902,6 +903,126 @@ put_nod(nod_info *ni)
43 +// Used to hold state information while walking a directory inode.
54 +// Start a directory walk on the given inode. You must pass in a
55 +// dirwalker structure, then use that dirwalker for future operations.
56 +// Call put_dir when you are done walking the directory.
57 +static inline directory *
58 +get_dir(filesystem *fs, uint32 nod, dirwalker *dw)
61 + dw->b = get_blk(fs, nod, &dw->bi);
63 + dw->last_d = (directory *) dw->b;
65 + memcpy(&dw->d, dw->last_d, sizeof(directory));
69 +// Move to the next directory.
70 +static inline directory *
71 +next_dir(dirwalker *dw)
73 + directory *next_d = (directory *)((int8*)dw->last_d + dw->d.d_rec_len);
75 + memcpy(dw->last_d, &dw->d, sizeof(directory));
77 + if (((int8 *) next_d) >= ((int8 *) dw->b + BLOCKSIZE))
80 + dw->last_d = next_d;
81 + memcpy(&dw->d, next_d, sizeof(directory));
85 +// Call then when you are done with the directory walk.
87 +put_dir(dirwalker *dw)
89 + memcpy(dw->last_d, &dw->d, sizeof(directory));
92 + free_workblk(dw->b);
97 +// Create a new directory block with the given inode as it's destination
98 +// and append it to the current dirwalker.
100 +new_dir(filesystem *fs, uint32 dnod, const char *name, int nlen, dirwalker *dw)
105 + dw->b = get_workblk();
107 + dw->last_d = (directory *) dw->b;
110 + d->d_rec_len = BLOCKSIZE;
111 + d->d_name_len = nlen;
112 + strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
116 +// Shrink the current directory entry, make a new one with the free
117 +// space, and return the new directory entry (making it current).
118 +static inline directory *
119 +shrink_dir(dirwalker *dw, uint32 nod, const char *name, int nlen)
121 + int reclen, preclen;
122 + directory *d = &dw->d;
124 + reclen = d->d_rec_len;
125 + d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);
126 + preclen = d->d_rec_len;
128 + memcpy(dw->last_d, &dw->d, sizeof(directory));
130 + dw->last_d = (directory *) (((int8 *) dw->last_d) + preclen);
131 + d->d_rec_len = reclen;
133 + d->d_name_len = nlen;
134 + strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
139 +// Return the current block the directory is walking
140 +static inline uint8 *
141 +dir_data(dirwalker *dw)
146 +// Return the pointer to the name for the current directory
147 +static inline char *
148 +dir_name(dirwalker *dw)
150 + return ((char *) dw->last_d) + sizeof(directory);
153 +// Set the name for the current directory. Note that this doesn't
154 +// verify that there is space for the directory name, you must do
157 +dir_set_name(dirwalker *dw, const char *name, int nlen)
159 + dw->d.d_name_len = nlen;
160 + strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
163 // allocate a given block/inode in the bitmap
164 // allocate first free if item == 0
166 @@ -1354,11 +1475,10 @@ extend_blk(filesystem *fs, uint32 nod, block b, int amount)
168 add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
171 + blockwalker bw, lbw;
180 @@ -1376,55 +1496,46 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
181 if(reclen > BLOCKSIZE)
182 error_msg_and_die("bad name '%s' (too long)", name);
185 while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir
187 - b = get_blk(fs, bk, &bi);
188 // for all dir entries in block
189 - for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
190 + for(d = get_dir(fs, bk, &dw); d; d = next_dir(&dw))
192 // if empty dir entry, large enough, use it
193 if((!d->d_inode) && (d->d_rec_len >= reclen))
196 node = get_nod(fs, nod, &ni);
197 + dir_set_name(&dw, name, nlen);
199 node->i_links_count++;
200 - d->d_name_len = nlen;
201 - strncpy(d->d_name, name, nlen);
205 // if entry with enough room (last one?), shrink it & use it
206 if(d->d_rec_len >= (sizeof(directory) + rndup(d->d_name_len, 4) + reclen))
208 - reclen = d->d_rec_len;
209 - d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);
210 - reclen -= d->d_rec_len;
211 - d = (directory*) (((int8*)d) + d->d_rec_len);
212 - d->d_rec_len = reclen;
214 node = get_nod(fs, nod, &ni);
215 + d = shrink_dir(&dw, nod, name, nlen);
217 node->i_links_count++;
218 - d->d_name_len = nlen;
219 - strncpy(d->d_name, name, nlen);
227 // we found no free entry in the directory, so we add a block
228 - if(!(b = get_workblk()))
229 - error_msg_and_die("get_workblk() failed.");
232 node = get_nod(fs, nod, &ni);
233 + d = new_dir(fs, nod, name, nlen, &dw);
234 node->i_links_count++;
236 - d->d_rec_len = BLOCKSIZE;
237 - d->d_name_len = nlen;
238 - strncpy(d->d_name, name, nlen);
239 - extend_blk(fs, dnod, b, 1);
240 + next_dir(&dw); // Force the data into the buffer
241 + extend_blk(fs, dnod, dir_data(&dw), 1);
243 pnode->i_size += BLOCKSIZE;
248 @@ -1435,20 +1546,18 @@ find_dir(filesystem *fs, uint32 nod, const char * name)
253 int nlen = strlen(name);
255 while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
259 - b = get_blk(fs, bk, &bi);
260 - for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
261 - if(d->d_inode && (nlen == d->d_name_len) && !strncmp(d->d_name, name, nlen)) {
264 + for (d = get_dir(fs, bk, &dw); d; d=next_dir(&dw))
265 + if(d->d_inode && (nlen == d->d_name_len) && !strncmp(dir_name(&dw), name, nlen)) {
274 @@ -2090,8 +2199,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
281 uint32 nod, first_block;
282 uint32 nbgroups,nbinodes_per_group,overhead_per_group,free_blocks,
283 free_blocks_per_group,nbblocks_per_group,min_nbgroups;
284 @@ -2217,26 +2325,20 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
285 itab0->i_links_count = 2;
288 - if(!(b = get_workblk()))
289 - error_msg_and_die("get_workblk() failed.");
291 - d->d_inode = EXT2_ROOT_INO;
292 - d->d_rec_len = sizeof(directory)+4;
294 - strcpy(d->d_name, ".");
295 - d = (directory*)(b + d->d_rec_len);
296 - d->d_inode = EXT2_ROOT_INO;
297 - d->d_rec_len = BLOCKSIZE - (sizeof(directory)+4);
299 - strcpy(d->d_name, "..");
300 - extend_blk(fs, EXT2_ROOT_INO, b, 1);
301 + new_dir(fs, EXT2_ROOT_INO, ".", 1, &dw);
302 + shrink_dir(&dw, EXT2_ROOT_INO, "..", 2);
303 + next_dir(&dw); // Force the data into the buffer
304 + extend_blk(fs, EXT2_ROOT_INO, dir_data(&dw), 1);
307 // make lost+found directory and reserve blocks
308 if(fs->sb.s_r_blocks_count)
313 nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU, 0, 0, fs_timestamp, fs_timestamp);
315 memset(b, 0, BLOCKSIZE);
316 ((directory*)b)->d_rec_len = BLOCKSIZE;
317 /* We run into problems with e2fsck if directory lost+found grows
318 @@ -2246,11 +2348,11 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
319 fs->sb.s_r_blocks_count = fs->sb.s_blocks_count * MAX_RESERVED_BLOCKS;
320 for(i = 1; i < fs->sb.s_r_blocks_count; i++)
321 extend_blk(fs, nod, b, 1);
323 node = get_nod(fs, nod, &ni);
324 node->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
329 // administrative info
331 @@ -2368,19 +2470,15 @@ print_dir(filesystem *fs, uint32 nod)
332 while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
337 - b = get_blk(fs, bk, &bi);
338 - for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
340 + for (d = get_dir(fs, bk, &dw); d; d = next_dir(&dw))
345 - for(i = 0; i < d->d_name_len; i++)
346 - putchar(d->d_name[i]);
347 + fwrite(dir_name(&dw), 1, d->d_name_len, stdout);
348 printf("' (inode %d): rec_len: %d (name_len: %d)\n", d->d_inode, d->d_rec_len, d->d_name_len);