]> code.ossystems Code Review - openembedded-core.git/blob
014a69409f9e3882f82b744fce3bc641508e6495
[openembedded-core.git] /
1 Upstream-Status: inappropriate
2
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
7
8 The code to walk directory items was messy, to say the least.  Write a
9 clean structure to do this.
10
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.
14 ---
15  genext2fs.c |  210 +++++++++++++++++++++++++++++++++++++++++++----------------
16  1 files changed, 154 insertions(+), 56 deletions(-)
17
18 diff --git a/genext2fs.c b/genext2fs.c
19 index 0b5ba6f..03d1b27 100644
20 --- a/genext2fs.c
21 +++ b/genext2fs.c
22 @@ -533,7 +533,6 @@ typedef struct
23  typedef struct
24  {
25         directory_decl
26 -       char d_name[0];
27  } directory;
28  
29  typedef uint8 block[BLOCKSIZE];
30 @@ -795,6 +794,8 @@ static inline uint8 *
31  get_workblk(void)
32  {
33         unsigned char* b=calloc(1,BLOCKSIZE);
34 +       if (!b)
35 +               error_msg_and_die("get_workblk() failed, out of memory");
36         return b;
37  }
38  static inline void
39 @@ -902,6 +903,126 @@ put_nod(nod_info *ni)
40         free(ni);
41  }
42  
43 +// Used to hold state information while walking a directory inode.
44 +typedef struct
45 +{
46 +       directory d;
47 +       filesystem *fs;
48 +       uint32 nod;
49 +       directory *last_d;
50 +       uint8 *b;
51 +       blk_info *bi;
52 +} dirwalker;
53 +
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)
59 +{
60 +       dw->fs = fs;
61 +       dw->b = get_blk(fs, nod, &dw->bi);
62 +       dw->nod = nod;
63 +       dw->last_d = (directory *) dw->b;
64 +
65 +       memcpy(&dw->d, dw->last_d, sizeof(directory));
66 +       return &dw->d;
67 +}
68 +
69 +// Move to the next directory.
70 +static inline directory *
71 +next_dir(dirwalker *dw)
72 +{
73 +       directory *next_d = (directory *)((int8*)dw->last_d + dw->d.d_rec_len);
74 +
75 +       memcpy(dw->last_d, &dw->d, sizeof(directory));
76 +
77 +       if (((int8 *) next_d) >= ((int8 *) dw->b + BLOCKSIZE))
78 +               return NULL;
79 +
80 +       dw->last_d = next_d;
81 +       memcpy(&dw->d, next_d, sizeof(directory));
82 +       return &dw->d;
83 +}
84 +
85 +// Call then when you are done with the directory walk.
86 +static inline void
87 +put_dir(dirwalker *dw)
88 +{
89 +       memcpy(dw->last_d, &dw->d, sizeof(directory));
90 +
91 +       if (dw->nod == 0)
92 +               free_workblk(dw->b);
93 +       else
94 +               put_blk(dw->bi);
95 +}
96 +
97 +// Create a new directory block with the given inode as it's destination
98 +// and append it to the current dirwalker.
99 +static directory *
100 +new_dir(filesystem *fs, uint32 dnod, const char *name, int nlen, dirwalker *dw)
101 +{
102 +       directory *d;
103 +
104 +       dw->fs = fs;
105 +       dw->b = get_workblk();
106 +       dw->nod = 0;
107 +       dw->last_d = (directory *) dw->b;
108 +       d = &dw->d;
109 +       d->d_inode = dnod;
110 +       d->d_rec_len = BLOCKSIZE;
111 +       d->d_name_len = nlen;
112 +       strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
113 +       return d;
114 +}
115 +
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)
120 +{
121 +       int reclen, preclen;
122 +       directory *d = &dw->d;
123 +
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;
127 +       reclen -= preclen;
128 +       memcpy(dw->last_d, &dw->d, sizeof(directory));
129 +
130 +       dw->last_d = (directory *) (((int8 *) dw->last_d) + preclen);
131 +       d->d_rec_len = reclen;
132 +       d->d_inode = nod;
133 +       d->d_name_len = nlen;
134 +       strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
135 +
136 +       return d;
137 +}
138 +
139 +// Return the current block the directory is walking
140 +static inline uint8 *
141 +dir_data(dirwalker *dw)
142 +{
143 +       return dw->b;
144 +}
145 +
146 +// Return the pointer to the name for the current directory
147 +static inline char *
148 +dir_name(dirwalker *dw)
149 +{
150 +       return ((char *) dw->last_d) + sizeof(directory);
151 +}
152 +
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
155 +// that yourself.
156 +static void
157 +dir_set_name(dirwalker *dw, const char *name, int nlen)
158 +{
159 +       dw->d.d_name_len = nlen;
160 +       strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
161 +}
162 +
163  // allocate a given block/inode in the bitmap
164  // allocate first free if item == 0
165  static uint32
166 @@ -1354,11 +1475,10 @@ extend_blk(filesystem *fs, uint32 nod, block b, int amount)
167  static void
168  add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
169  {
170 -       blockwalker bw;
171 +       blockwalker bw, lbw;
172         uint32 bk;
173 -       uint8 *b;
174 -       blk_info *bi;
175         directory *d;
176 +       dirwalker dw;
177         int reclen, nlen;
178         inode *node;
179         inode *pnode;
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);
183         init_bw(&bw);
184 +       lbw = bw;
185         while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir
186         {
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))
191                 {
192                         // if empty dir entry, large enough, use it
193                         if((!d->d_inode) && (d->d_rec_len >= reclen))
194                         {
195                                 d->d_inode = nod;
196                                 node = get_nod(fs, nod, &ni);
197 +                               dir_set_name(&dw, name, nlen);
198 +                               put_dir(&dw);
199                                 node->i_links_count++;
200 -                               d->d_name_len = nlen;
201 -                               strncpy(d->d_name, name, nlen);
202                                 put_nod(ni);
203                                 goto out;
204                         }
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))
207                         {
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;
213 -                               d->d_inode = nod;
214                                 node = get_nod(fs, nod, &ni);
215 +                               d = shrink_dir(&dw, nod, name, nlen);
216 +                               put_dir(&dw);
217                                 node->i_links_count++;
218 -                               d->d_name_len = nlen;
219 -                               strncpy(d->d_name, name, nlen);
220                                 put_nod(ni);
221                                 goto out;
222                         }
223                 }
224 +               put_dir(&dw);
225 +               lbw = bw;
226         }
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.");
230 -       d = (directory*)b;
231 -       d->d_inode = nod;
232         node = get_nod(fs, nod, &ni);
233 +       d = new_dir(fs, nod, name, nlen, &dw);
234         node->i_links_count++;
235         put_nod(ni);
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);
242 +       put_dir(&dw);
243         pnode->i_size += BLOCKSIZE;
244 -       free_workblk(b);
245  out:
246         put_nod(dni);
247  }
248 @@ -1435,20 +1546,18 @@ find_dir(filesystem *fs, uint32 nod, const char * name)
249  {
250         blockwalker bw;
251         uint32 bk;
252 -       blk_info *bi;
253         int nlen = strlen(name);
254         init_bw(&bw);
255         while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
256         {
257                 directory *d;
258 -               uint8 *b;
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)) {
262 -                               put_blk(bi);
263 +               dirwalker dw;
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)) {
266 +                               put_dir(&dw);
267                                 return d->d_inode;
268                         }
269 -               put_blk(bi);
270 +               put_dir(&dw);
271         }
272         return 0;
273  }
274 @@ -2090,8 +2199,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
275  {
276         uint32 i;
277         filesystem *fs;
278 -       directory *d;
279 -       uint8 * b;
280 +       dirwalker dw;
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;
286         put_nod(ni);
287  
288 -       if(!(b = get_workblk()))
289 -               error_msg_and_die("get_workblk() failed.");
290 -       d = (directory*)b;
291 -       d->d_inode = EXT2_ROOT_INO;
292 -       d->d_rec_len = sizeof(directory)+4;
293 -       d->d_name_len = 1;
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);
298 -       d->d_name_len = 2;
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);
305 +       put_dir(&dw);
306  
307         // make lost+found directory and reserve blocks
308         if(fs->sb.s_r_blocks_count)
309         {
310                 inode *node;
311 +               uint8 *b;
312  
313                 nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU, 0, 0, fs_timestamp, fs_timestamp);
314 +               b = get_workblk();
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);
322 +               free_workblk(b);
323                 node = get_nod(fs, nod, &ni);
324                 node->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
325                 put_nod(ni);
326         }
327 -       free_workblk(b);
328  
329         // administrative info
330         fs->sb.s_state = 1;
331 @@ -2368,19 +2470,15 @@ print_dir(filesystem *fs, uint32 nod)
332         while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
333         {
334                 directory *d;
335 -               uint8 *b;
336 -               blk_info *bi;
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))
339 +               dirwalker dw;
340 +               for (d = get_dir(fs, bk, &dw); d; d = next_dir(&dw))
341                         if(d->d_inode)
342                         {
343 -                               int i;
344                                 printf("entry '");
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);
349                         }
350 -               put_blk(bi);
351 +               put_dir(&dw);
352         }
353  }
354  
355 -- 
356 1.7.4.1
357