Commit ad49488ffb0dd6357139f74a6b88c0b51e1ac215
Committed by
Tom Rini
1 parent
908d006ba5
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
jffs2: remove unused code files
I failed to find where these two files are used and a few test compile runs with JFFS2 enabled succeeded also without these.
Showing 2 changed files with 0 additions and 1169 deletions Inline Diff
fs/jffs2/jffs2_nand_1pass.c
1 | #include <common.h> | File was deleted | |
2 | |||
3 | #include <malloc.h> | ||
4 | #include <linux/stat.h> | ||
5 | #include <linux/time.h> | ||
6 | |||
7 | #include <jffs2/jffs2.h> | ||
8 | #include <jffs2/jffs2_1pass.h> | ||
9 | #include <nand.h> | ||
10 | |||
11 | #include "jffs2_nand_private.h" | ||
12 | |||
13 | #define NODE_CHUNK 1024 /* size of memory allocation chunk in b_nodes */ | ||
14 | |||
15 | /* Debugging switches */ | ||
16 | #undef DEBUG_DIRENTS /* print directory entry list after scan */ | ||
17 | #undef DEBUG_FRAGMENTS /* print fragment list after scan */ | ||
18 | #undef DEBUG /* enable debugging messages */ | ||
19 | |||
20 | #ifdef DEBUG | ||
21 | # define DEBUGF(fmt,args...) printf(fmt ,##args) | ||
22 | #else | ||
23 | # define DEBUGF(fmt,args...) | ||
24 | #endif | ||
25 | |||
26 | static struct mtd_info *mtd; | ||
27 | |||
28 | /* Compression names */ | ||
29 | static char *compr_names[] = { | ||
30 | "NONE", | ||
31 | "ZERO", | ||
32 | "RTIME", | ||
33 | "RUBINMIPS", | ||
34 | "COPY", | ||
35 | "DYNRUBIN", | ||
36 | "ZLIB", | ||
37 | #if defined(CONFIG_JFFS2_LZO) | ||
38 | "LZO", | ||
39 | #endif | ||
40 | }; | ||
41 | |||
42 | /* Spinning wheel */ | ||
43 | static char spinner[] = { '|', '/', '-', '\\' }; | ||
44 | |||
45 | /* Memory management */ | ||
46 | struct mem_block { | ||
47 | unsigned index; | ||
48 | struct mem_block *next; | ||
49 | char nodes[0]; | ||
50 | }; | ||
51 | |||
52 | static void | ||
53 | free_nodes(struct b_list *list) | ||
54 | { | ||
55 | while (list->listMemBase != NULL) { | ||
56 | struct mem_block *next = list->listMemBase->next; | ||
57 | free(list->listMemBase); | ||
58 | list->listMemBase = next; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | static struct b_node * | ||
63 | add_node(struct b_list *list, int size) | ||
64 | { | ||
65 | u32 index = 0; | ||
66 | struct mem_block *memBase; | ||
67 | struct b_node *b; | ||
68 | |||
69 | memBase = list->listMemBase; | ||
70 | if (memBase != NULL) | ||
71 | index = memBase->index; | ||
72 | |||
73 | if (memBase == NULL || index >= NODE_CHUNK) { | ||
74 | /* we need more space before we continue */ | ||
75 | memBase = mmalloc(sizeof(struct mem_block) + NODE_CHUNK * size); | ||
76 | if (memBase == NULL) { | ||
77 | putstr("add_node: malloc failed\n"); | ||
78 | return NULL; | ||
79 | } | ||
80 | memBase->next = list->listMemBase; | ||
81 | index = 0; | ||
82 | } | ||
83 | /* now we have room to add it. */ | ||
84 | b = (struct b_node *)&memBase->nodes[size * index]; | ||
85 | index ++; | ||
86 | |||
87 | memBase->index = index; | ||
88 | list->listMemBase = memBase; | ||
89 | list->listCount++; | ||
90 | return b; | ||
91 | } | ||
92 | |||
93 | static struct b_node * | ||
94 | insert_node(struct b_list *list, struct b_node *new) | ||
95 | { | ||
96 | #ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS | ||
97 | struct b_node *b, *prev; | ||
98 | |||
99 | if (list->listTail != NULL && list->listCompare(new, list->listTail)) | ||
100 | prev = list->listTail; | ||
101 | else if (list->listLast != NULL && list->listCompare(new, list->listLast)) | ||
102 | prev = list->listLast; | ||
103 | else | ||
104 | prev = NULL; | ||
105 | |||
106 | for (b = (prev ? prev->next : list->listHead); | ||
107 | b != NULL && list->listCompare(new, b); | ||
108 | prev = b, b = b->next) { | ||
109 | list->listLoops++; | ||
110 | } | ||
111 | if (b != NULL) | ||
112 | list->listLast = prev; | ||
113 | |||
114 | if (b != NULL) { | ||
115 | new->next = b; | ||
116 | if (prev != NULL) | ||
117 | prev->next = new; | ||
118 | else | ||
119 | list->listHead = new; | ||
120 | } else | ||
121 | #endif | ||
122 | { | ||
123 | new->next = (struct b_node *) NULL; | ||
124 | if (list->listTail != NULL) { | ||
125 | list->listTail->next = new; | ||
126 | list->listTail = new; | ||
127 | } else { | ||
128 | list->listTail = list->listHead = new; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | return new; | ||
133 | } | ||
134 | |||
135 | static struct b_node * | ||
136 | insert_inode(struct b_list *list, struct jffs2_raw_inode *node, u32 offset) | ||
137 | { | ||
138 | struct b_inode *new; | ||
139 | |||
140 | if (!(new = (struct b_inode *)add_node(list, sizeof(struct b_inode)))) { | ||
141 | putstr("add_node failed!\r\n"); | ||
142 | return NULL; | ||
143 | } | ||
144 | new->offset = offset; | ||
145 | new->version = node->version; | ||
146 | new->ino = node->ino; | ||
147 | new->isize = node->isize; | ||
148 | new->csize = node->csize; | ||
149 | |||
150 | return insert_node(list, (struct b_node *)new); | ||
151 | } | ||
152 | |||
153 | static struct b_node * | ||
154 | insert_dirent(struct b_list *list, struct jffs2_raw_dirent *node, u32 offset) | ||
155 | { | ||
156 | struct b_dirent *new; | ||
157 | |||
158 | if (!(new = (struct b_dirent *)add_node(list, sizeof(struct b_dirent)))) { | ||
159 | putstr("add_node failed!\r\n"); | ||
160 | return NULL; | ||
161 | } | ||
162 | new->offset = offset; | ||
163 | new->version = node->version; | ||
164 | new->pino = node->pino; | ||
165 | new->ino = node->ino; | ||
166 | new->nhash = full_name_hash(node->name, node->nsize); | ||
167 | new->nsize = node->nsize; | ||
168 | new->type = node->type; | ||
169 | |||
170 | return insert_node(list, (struct b_node *)new); | ||
171 | } | ||
172 | |||
173 | #ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS | ||
174 | /* Sort data entries with the latest version last, so that if there | ||
175 | * is overlapping data the latest version will be used. | ||
176 | */ | ||
177 | static int compare_inodes(struct b_node *new, struct b_node *old) | ||
178 | { | ||
179 | struct jffs2_raw_inode ojNew; | ||
180 | struct jffs2_raw_inode ojOld; | ||
181 | struct jffs2_raw_inode *jNew = | ||
182 | (struct jffs2_raw_inode *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew); | ||
183 | struct jffs2_raw_inode *jOld = | ||
184 | (struct jffs2_raw_inode *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld); | ||
185 | |||
186 | return jNew->version > jOld->version; | ||
187 | } | ||
188 | |||
189 | /* Sort directory entries so all entries in the same directory | ||
190 | * with the same name are grouped together, with the latest version | ||
191 | * last. This makes it easy to eliminate all but the latest version | ||
192 | * by marking the previous version dead by setting the inode to 0. | ||
193 | */ | ||
194 | static int compare_dirents(struct b_node *new, struct b_node *old) | ||
195 | { | ||
196 | struct jffs2_raw_dirent ojNew; | ||
197 | struct jffs2_raw_dirent ojOld; | ||
198 | struct jffs2_raw_dirent *jNew = | ||
199 | (struct jffs2_raw_dirent *)get_fl_mem(new->offset, sizeof(ojNew), &ojNew); | ||
200 | struct jffs2_raw_dirent *jOld = | ||
201 | (struct jffs2_raw_dirent *)get_fl_mem(old->offset, sizeof(ojOld), &ojOld); | ||
202 | int cmp; | ||
203 | |||
204 | /* ascending sort by pino */ | ||
205 | if (jNew->pino != jOld->pino) | ||
206 | return jNew->pino > jOld->pino; | ||
207 | |||
208 | /* pino is the same, so use ascending sort by nsize, so | ||
209 | * we don't do strncmp unless we really must. | ||
210 | */ | ||
211 | if (jNew->nsize != jOld->nsize) | ||
212 | return jNew->nsize > jOld->nsize; | ||
213 | |||
214 | /* length is also the same, so use ascending sort by name | ||
215 | */ | ||
216 | cmp = strncmp(jNew->name, jOld->name, jNew->nsize); | ||
217 | if (cmp != 0) | ||
218 | return cmp > 0; | ||
219 | |||
220 | /* we have duplicate names in this directory, so use ascending | ||
221 | * sort by version | ||
222 | */ | ||
223 | if (jNew->version > jOld->version) { | ||
224 | /* since jNew is newer, we know jOld is not valid, so | ||
225 | * mark it with inode 0 and it will not be used | ||
226 | */ | ||
227 | jOld->ino = 0; | ||
228 | return 1; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | #endif | ||
234 | |||
235 | static u32 | ||
236 | jffs_init_1pass_list(struct part_info *part) | ||
237 | { | ||
238 | struct b_lists *pL; | ||
239 | |||
240 | if (part->jffs2_priv != NULL) { | ||
241 | pL = (struct b_lists *)part->jffs2_priv; | ||
242 | free_nodes(&pL->frag); | ||
243 | free_nodes(&pL->dir); | ||
244 | free(pL); | ||
245 | } | ||
246 | if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) { | ||
247 | pL = (struct b_lists *)part->jffs2_priv; | ||
248 | |||
249 | memset(pL, 0, sizeof(*pL)); | ||
250 | #ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS | ||
251 | pL->dir.listCompare = compare_dirents; | ||
252 | pL->frag.listCompare = compare_inodes; | ||
253 | #endif | ||
254 | } | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | /* find the inode from the slashless name given a parent */ | ||
259 | static long | ||
260 | jffs2_1pass_read_inode(struct b_lists *pL, u32 ino, char *dest, | ||
261 | struct stat *stat) | ||
262 | { | ||
263 | struct b_inode *jNode; | ||
264 | u32 totalSize = 0; | ||
265 | u32 latestVersion = 0; | ||
266 | long ret; | ||
267 | |||
268 | #ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS | ||
269 | /* Find file size before loading any data, so fragments that | ||
270 | * start past the end of file can be ignored. A fragment | ||
271 | * that is partially in the file is loaded, so extra data may | ||
272 | * be loaded up to the next 4K boundary above the file size. | ||
273 | * This shouldn't cause trouble when loading kernel images, so | ||
274 | * we will live with it. | ||
275 | */ | ||
276 | for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { | ||
277 | if ((ino == jNode->ino)) { | ||
278 | /* get actual file length from the newest node */ | ||
279 | if (jNode->version >= latestVersion) { | ||
280 | totalSize = jNode->isize; | ||
281 | latestVersion = jNode->version; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | #endif | ||
286 | |||
287 | for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { | ||
288 | if ((ino != jNode->ino)) | ||
289 | continue; | ||
290 | #ifndef CONFIG_SYS_JFFS2_SORT_FRAGMENTS | ||
291 | /* get actual file length from the newest node */ | ||
292 | if (jNode->version >= latestVersion) { | ||
293 | totalSize = jNode->isize; | ||
294 | latestVersion = jNode->version; | ||
295 | } | ||
296 | #endif | ||
297 | if (dest || stat) { | ||
298 | char *src, *dst; | ||
299 | char data[4096 + sizeof(struct jffs2_raw_inode)]; | ||
300 | struct jffs2_raw_inode *inode; | ||
301 | size_t len; | ||
302 | |||
303 | inode = (struct jffs2_raw_inode *)&data; | ||
304 | len = sizeof(struct jffs2_raw_inode); | ||
305 | if (dest) | ||
306 | len += jNode->csize; | ||
307 | nand_read(mtd, jNode->offset, &len, inode); | ||
308 | /* ignore data behind latest known EOF */ | ||
309 | if (inode->offset > totalSize) | ||
310 | continue; | ||
311 | |||
312 | if (stat) { | ||
313 | stat->st_mtime = inode->mtime; | ||
314 | stat->st_mode = inode->mode; | ||
315 | stat->st_ino = inode->ino; | ||
316 | stat->st_size = totalSize; | ||
317 | } | ||
318 | |||
319 | if (!dest) | ||
320 | continue; | ||
321 | |||
322 | src = ((char *) inode) + sizeof(struct jffs2_raw_inode); | ||
323 | dst = (char *) (dest + inode->offset); | ||
324 | |||
325 | switch (inode->compr) { | ||
326 | case JFFS2_COMPR_NONE: | ||
327 | ret = 0; | ||
328 | memcpy(dst, src, inode->dsize); | ||
329 | break; | ||
330 | case JFFS2_COMPR_ZERO: | ||
331 | ret = 0; | ||
332 | memset(dst, 0, inode->dsize); | ||
333 | break; | ||
334 | case JFFS2_COMPR_RTIME: | ||
335 | ret = 0; | ||
336 | rtime_decompress(src, dst, inode->csize, inode->dsize); | ||
337 | break; | ||
338 | case JFFS2_COMPR_DYNRUBIN: | ||
339 | /* this is slow but it works */ | ||
340 | ret = 0; | ||
341 | dynrubin_decompress(src, dst, inode->csize, inode->dsize); | ||
342 | break; | ||
343 | case JFFS2_COMPR_ZLIB: | ||
344 | ret = zlib_decompress(src, dst, inode->csize, inode->dsize); | ||
345 | break; | ||
346 | #if defined(CONFIG_JFFS2_LZO) | ||
347 | case JFFS2_COMPR_LZO: | ||
348 | ret = lzo_decompress(src, dst, inode->csize, inode->dsize); | ||
349 | break; | ||
350 | #endif | ||
351 | default: | ||
352 | /* unknown */ | ||
353 | putLabeledWord("UNKNOWN COMPRESSION METHOD = ", inode->compr); | ||
354 | return -1; | ||
355 | } | ||
356 | } | ||
357 | } | ||
358 | |||
359 | return totalSize; | ||
360 | } | ||
361 | |||
362 | /* find the inode from the slashless name given a parent */ | ||
363 | static u32 | ||
364 | jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino) | ||
365 | { | ||
366 | struct b_dirent *jDir; | ||
367 | int len = strlen(name); /* name is assumed slash free */ | ||
368 | unsigned int nhash = full_name_hash(name, len); | ||
369 | u32 version = 0; | ||
370 | u32 inode = 0; | ||
371 | |||
372 | /* we need to search all and return the inode with the highest version */ | ||
373 | for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { | ||
374 | if ((pino == jDir->pino) && (jDir->ino) && /* 0 for unlink */ | ||
375 | (len == jDir->nsize) && (nhash == jDir->nhash)) { | ||
376 | /* TODO: compare name */ | ||
377 | if (jDir->version < version) | ||
378 | continue; | ||
379 | |||
380 | if (jDir->version == version && inode != 0) { | ||
381 | /* I'm pretty sure this isn't legal */ | ||
382 | putstr(" ** ERROR ** "); | ||
383 | /* putnstr(jDir->name, jDir->nsize); */ | ||
384 | /* putLabeledWord(" has dup version =", version); */ | ||
385 | } | ||
386 | inode = jDir->ino; | ||
387 | version = jDir->version; | ||
388 | } | ||
389 | } | ||
390 | return inode; | ||
391 | } | ||
392 | |||
393 | char *mkmodestr(unsigned long mode, char *str) | ||
394 | { | ||
395 | static const char *l = "xwr"; | ||
396 | int mask = 1, i; | ||
397 | char c; | ||
398 | |||
399 | switch (mode & S_IFMT) { | ||
400 | case S_IFDIR: str[0] = 'd'; break; | ||
401 | case S_IFBLK: str[0] = 'b'; break; | ||
402 | case S_IFCHR: str[0] = 'c'; break; | ||
403 | case S_IFIFO: str[0] = 'f'; break; | ||
404 | case S_IFLNK: str[0] = 'l'; break; | ||
405 | case S_IFSOCK: str[0] = 's'; break; | ||
406 | case S_IFREG: str[0] = '-'; break; | ||
407 | default: str[0] = '?'; | ||
408 | } | ||
409 | |||
410 | for(i = 0; i < 9; i++) { | ||
411 | c = l[i%3]; | ||
412 | str[9-i] = (mode & mask)?c:'-'; | ||
413 | mask = mask<<1; | ||
414 | } | ||
415 | |||
416 | if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S'; | ||
417 | if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S'; | ||
418 | if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T'; | ||
419 | str[10] = '\0'; | ||
420 | return str; | ||
421 | } | ||
422 | |||
423 | static inline void dump_stat(struct stat *st, const char *name) | ||
424 | { | ||
425 | char str[20]; | ||
426 | char s[64], *p; | ||
427 | |||
428 | if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */ | ||
429 | st->st_mtime = 1; | ||
430 | |||
431 | ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */ | ||
432 | |||
433 | if ((p = strchr(s,'\n')) != NULL) *p = '\0'; | ||
434 | if ((p = strchr(s,'\r')) != NULL) *p = '\0'; | ||
435 | |||
436 | /* | ||
437 | printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str), | ||
438 | st->st_size, s, name); | ||
439 | */ | ||
440 | |||
441 | printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name); | ||
442 | } | ||
443 | |||
444 | static inline int | ||
445 | dump_inode(struct b_lists *pL, struct b_dirent *d, struct b_inode *i) | ||
446 | { | ||
447 | char fname[JFFS2_MAX_NAME_LEN + 1]; | ||
448 | struct stat st; | ||
449 | size_t len; | ||
450 | |||
451 | if(!d || !i) return -1; | ||
452 | len = d->nsize; | ||
453 | nand_read(mtd, d->offset + sizeof(struct jffs2_raw_dirent), | ||
454 | &len, &fname); | ||
455 | fname[d->nsize] = '\0'; | ||
456 | |||
457 | memset(&st, 0, sizeof(st)); | ||
458 | |||
459 | jffs2_1pass_read_inode(pL, i->ino, NULL, &st); | ||
460 | |||
461 | dump_stat(&st, fname); | ||
462 | /* FIXME | ||
463 | if (d->type == DT_LNK) { | ||
464 | unsigned char *src = (unsigned char *) (&i[1]); | ||
465 | putstr(" -> "); | ||
466 | putnstr(src, (int)i->dsize); | ||
467 | } | ||
468 | */ | ||
469 | putstr("\r\n"); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | /* list inodes with the given pino */ | ||
475 | static u32 | ||
476 | jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino) | ||
477 | { | ||
478 | struct b_dirent *jDir; | ||
479 | u32 i_version = 0; | ||
480 | |||
481 | for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { | ||
482 | if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */ | ||
483 | struct b_inode *jNode = (struct b_inode *)pL->frag.listHead; | ||
484 | struct b_inode *i = NULL; | ||
485 | |||
486 | while (jNode) { | ||
487 | if (jNode->ino == jDir->ino && jNode->version >= i_version) { | ||
488 | i_version = jNode->version; | ||
489 | i = jNode; | ||
490 | } | ||
491 | jNode = jNode->next; | ||
492 | } | ||
493 | dump_inode(pL, jDir, i); | ||
494 | } | ||
495 | } | ||
496 | return pino; | ||
497 | } | ||
498 | |||
499 | static u32 | ||
500 | jffs2_1pass_search_inode(struct b_lists * pL, const char *fname, u32 pino) | ||
501 | { | ||
502 | int i; | ||
503 | char tmp[256]; | ||
504 | char working_tmp[256]; | ||
505 | char *c; | ||
506 | |||
507 | /* discard any leading slash */ | ||
508 | i = 0; | ||
509 | while (fname[i] == '/') | ||
510 | i++; | ||
511 | strcpy(tmp, &fname[i]); | ||
512 | |||
513 | while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */ | ||
514 | { | ||
515 | strncpy(working_tmp, tmp, c - tmp); | ||
516 | working_tmp[c - tmp] = '\0'; | ||
517 | #if 0 | ||
518 | putstr("search_inode: tmp = "); | ||
519 | putstr(tmp); | ||
520 | putstr("\r\n"); | ||
521 | putstr("search_inode: wtmp = "); | ||
522 | putstr(working_tmp); | ||
523 | putstr("\r\n"); | ||
524 | putstr("search_inode: c = "); | ||
525 | putstr(c); | ||
526 | putstr("\r\n"); | ||
527 | #endif | ||
528 | for (i = 0; i < strlen(c) - 1; i++) | ||
529 | tmp[i] = c[i + 1]; | ||
530 | tmp[i] = '\0'; | ||
531 | #if 0 | ||
532 | putstr("search_inode: post tmp = "); | ||
533 | putstr(tmp); | ||
534 | putstr("\r\n"); | ||
535 | #endif | ||
536 | |||
537 | if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino))) { | ||
538 | putstr("find_inode failed for name="); | ||
539 | putstr(working_tmp); | ||
540 | putstr("\r\n"); | ||
541 | return 0; | ||
542 | } | ||
543 | } | ||
544 | /* this is for the bare filename, directories have already been mapped */ | ||
545 | if (!(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { | ||
546 | putstr("find_inode failed for name="); | ||
547 | putstr(tmp); | ||
548 | putstr("\r\n"); | ||
549 | return 0; | ||
550 | } | ||
551 | return pino; | ||
552 | |||
553 | } | ||
554 | |||
555 | static u32 | ||
556 | jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino) | ||
557 | { | ||
558 | struct b_dirent *jDir; | ||
559 | struct b_inode *jNode; | ||
560 | u8 jDirFoundType = 0; | ||
561 | u32 jDirFoundIno = 0; | ||
562 | u32 jDirFoundPino = 0; | ||
563 | char tmp[JFFS2_MAX_NAME_LEN + 1]; | ||
564 | u32 version = 0; | ||
565 | u32 pino; | ||
566 | |||
567 | /* we need to search all and return the inode with the highest version */ | ||
568 | for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) { | ||
569 | if (ino == jDir->ino) { | ||
570 | if (jDir->version < version) | ||
571 | continue; | ||
572 | |||
573 | if (jDir->version == version && jDirFoundType) { | ||
574 | /* I'm pretty sure this isn't legal */ | ||
575 | putstr(" ** ERROR ** "); | ||
576 | /* putnstr(jDir->name, jDir->nsize); */ | ||
577 | /* putLabeledWord(" has dup version (resolve) = ", */ | ||
578 | /* version); */ | ||
579 | } | ||
580 | |||
581 | jDirFoundType = jDir->type; | ||
582 | jDirFoundIno = jDir->ino; | ||
583 | jDirFoundPino = jDir->pino; | ||
584 | version = jDir->version; | ||
585 | } | ||
586 | } | ||
587 | /* now we found the right entry again. (shoulda returned inode*) */ | ||
588 | if (jDirFoundType != DT_LNK) | ||
589 | return jDirFoundIno; | ||
590 | |||
591 | /* it's a soft link so we follow it again. */ | ||
592 | for (jNode = (struct b_inode *)pL->frag.listHead; jNode; jNode = jNode->next) { | ||
593 | if (jNode->ino == jDirFoundIno) { | ||
594 | size_t len = jNode->csize; | ||
595 | nand_read(mtd, | ||
596 | jNode->offset + sizeof(struct jffs2_raw_inode), | ||
597 | &len, &tmp); | ||
598 | tmp[jNode->csize] = '\0'; | ||
599 | break; | ||
600 | } | ||
601 | } | ||
602 | /* ok so the name of the new file to find is in tmp */ | ||
603 | /* if it starts with a slash it is root based else shared dirs */ | ||
604 | if (tmp[0] == '/') | ||
605 | pino = 1; | ||
606 | else | ||
607 | pino = jDirFoundPino; | ||
608 | |||
609 | return jffs2_1pass_search_inode(pL, tmp, pino); | ||
610 | } | ||
611 | |||
612 | static u32 | ||
613 | jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino) | ||
614 | { | ||
615 | int i; | ||
616 | char tmp[256]; | ||
617 | char working_tmp[256]; | ||
618 | char *c; | ||
619 | |||
620 | /* discard any leading slash */ | ||
621 | i = 0; | ||
622 | while (fname[i] == '/') | ||
623 | i++; | ||
624 | strcpy(tmp, &fname[i]); | ||
625 | working_tmp[0] = '\0'; | ||
626 | while ((c = (char *) strchr(tmp, '/'))) /* we are still dired searching */ | ||
627 | { | ||
628 | strncpy(working_tmp, tmp, c - tmp); | ||
629 | working_tmp[c - tmp] = '\0'; | ||
630 | for (i = 0; i < strlen(c) - 1; i++) | ||
631 | tmp[i] = c[i + 1]; | ||
632 | tmp[i] = '\0'; | ||
633 | /* only a failure if we arent looking at top level */ | ||
634 | if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && | ||
635 | (working_tmp[0])) { | ||
636 | putstr("find_inode failed for name="); | ||
637 | putstr(working_tmp); | ||
638 | putstr("\r\n"); | ||
639 | return 0; | ||
640 | } | ||
641 | } | ||
642 | |||
643 | if (tmp[0] && !(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { | ||
644 | putstr("find_inode failed for name="); | ||
645 | putstr(tmp); | ||
646 | putstr("\r\n"); | ||
647 | return 0; | ||
648 | } | ||
649 | /* this is for the bare filename, directories have already been mapped */ | ||
650 | if (!(pino = jffs2_1pass_list_inodes(pL, pino))) { | ||
651 | putstr("find_inode failed for name="); | ||
652 | putstr(tmp); | ||
653 | putstr("\r\n"); | ||
654 | return 0; | ||
655 | } | ||
656 | return pino; | ||
657 | |||
658 | } | ||
659 | |||
660 | unsigned char | ||
661 | jffs2_1pass_rescan_needed(struct part_info *part) | ||
662 | { | ||
663 | struct b_node *b; | ||
664 | struct jffs2_unknown_node onode; | ||
665 | struct jffs2_unknown_node *node; | ||
666 | struct b_lists *pL = (struct b_lists *)part->jffs2_priv; | ||
667 | |||
668 | if (part->jffs2_priv == 0){ | ||
669 | DEBUGF ("rescan: First time in use\n"); | ||
670 | return 1; | ||
671 | } | ||
672 | /* if we have no list, we need to rescan */ | ||
673 | if (pL->frag.listCount == 0) { | ||
674 | DEBUGF ("rescan: fraglist zero\n"); | ||
675 | return 1; | ||
676 | } | ||
677 | |||
678 | /* or if we are scanning a new partition */ | ||
679 | if (pL->partOffset != part->offset) { | ||
680 | DEBUGF ("rescan: different partition\n"); | ||
681 | return 1; | ||
682 | } | ||
683 | |||
684 | /* FIXME */ | ||
685 | #if 0 | ||
686 | /* but suppose someone reflashed a partition at the same offset... */ | ||
687 | b = pL->dir.listHead; | ||
688 | while (b) { | ||
689 | node = (struct jffs2_unknown_node *) get_fl_mem(b->offset, | ||
690 | sizeof(onode), &onode); | ||
691 | if (node->nodetype != JFFS2_NODETYPE_DIRENT) { | ||
692 | DEBUGF ("rescan: fs changed beneath me? (%lx)\n", | ||
693 | (unsigned long) b->offset); | ||
694 | return 1; | ||
695 | } | ||
696 | b = b->next; | ||
697 | } | ||
698 | #endif | ||
699 | return 0; | ||
700 | } | ||
701 | |||
702 | #ifdef DEBUG_FRAGMENTS | ||
703 | static void | ||
704 | dump_fragments(struct b_lists *pL) | ||
705 | { | ||
706 | struct b_node *b; | ||
707 | struct jffs2_raw_inode ojNode; | ||
708 | struct jffs2_raw_inode *jNode; | ||
709 | |||
710 | putstr("\r\n\r\n******The fragment Entries******\r\n"); | ||
711 | b = pL->frag.listHead; | ||
712 | while (b) { | ||
713 | jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, | ||
714 | sizeof(ojNode), &ojNode); | ||
715 | putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset); | ||
716 | putLabeledWord("\tbuild_list: totlen = ", jNode->totlen); | ||
717 | putLabeledWord("\tbuild_list: inode = ", jNode->ino); | ||
718 | putLabeledWord("\tbuild_list: version = ", jNode->version); | ||
719 | putLabeledWord("\tbuild_list: isize = ", jNode->isize); | ||
720 | putLabeledWord("\tbuild_list: atime = ", jNode->atime); | ||
721 | putLabeledWord("\tbuild_list: offset = ", jNode->offset); | ||
722 | putLabeledWord("\tbuild_list: csize = ", jNode->csize); | ||
723 | putLabeledWord("\tbuild_list: dsize = ", jNode->dsize); | ||
724 | putLabeledWord("\tbuild_list: compr = ", jNode->compr); | ||
725 | putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr); | ||
726 | putLabeledWord("\tbuild_list: flags = ", jNode->flags); | ||
727 | putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */ | ||
728 | b = b->next; | ||
729 | } | ||
730 | } | ||
731 | #endif | ||
732 | |||
733 | #ifdef DEBUG_DIRENTS | ||
734 | static void | ||
735 | dump_dirents(struct b_lists *pL) | ||
736 | { | ||
737 | struct b_node *b; | ||
738 | struct jffs2_raw_dirent *jDir; | ||
739 | |||
740 | putstr("\r\n\r\n******The directory Entries******\r\n"); | ||
741 | b = pL->dir.listHead; | ||
742 | while (b) { | ||
743 | jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset); | ||
744 | putstr("\r\n"); | ||
745 | putnstr(jDir->name, jDir->nsize); | ||
746 | putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic); | ||
747 | putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype); | ||
748 | putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc); | ||
749 | putLabeledWord("\tbuild_list: pino = ", jDir->pino); | ||
750 | putLabeledWord("\tbuild_list: version = ", jDir->version); | ||
751 | putLabeledWord("\tbuild_list: ino = ", jDir->ino); | ||
752 | putLabeledWord("\tbuild_list: mctime = ", jDir->mctime); | ||
753 | putLabeledWord("\tbuild_list: nsize = ", jDir->nsize); | ||
754 | putLabeledWord("\tbuild_list: type = ", jDir->type); | ||
755 | putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc); | ||
756 | putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc); | ||
757 | putLabeledWord("\tbuild_list: offset = ", b->offset); /* FIXME: ? [RS] */ | ||
758 | b = b->next; | ||
759 | put_fl_mem(jDir); | ||
760 | } | ||
761 | } | ||
762 | #endif | ||
763 | |||
764 | static int | ||
765 | jffs2_fill_scan_buf(struct mtd_info *mtd, unsigned char *buf, | ||
766 | unsigned ofs, unsigned len) | ||
767 | { | ||
768 | int ret; | ||
769 | unsigned olen; | ||
770 | |||
771 | olen = len; | ||
772 | ret = nand_read(mtd, ofs, &olen, buf); | ||
773 | if (ret) { | ||
774 | printf("nand_read(0x%x bytes from 0x%x) returned %d\n", len, ofs, ret); | ||
775 | return ret; | ||
776 | } | ||
777 | if (olen < len) { | ||
778 | printf("Read at 0x%x gave only 0x%x bytes\n", ofs, olen); | ||
779 | return -1; | ||
780 | } | ||
781 | return 0; | ||
782 | } | ||
783 | |||
784 | #define EMPTY_SCAN_SIZE 1024 | ||
785 | static u32 | ||
786 | jffs2_1pass_build_lists(struct part_info * part) | ||
787 | { | ||
788 | struct b_lists *pL; | ||
789 | struct jffs2_unknown_node *node; | ||
790 | unsigned nr_blocks, sectorsize, ofs, offset; | ||
791 | char *buf; | ||
792 | int i; | ||
793 | u32 counter = 0; | ||
794 | u32 counter4 = 0; | ||
795 | u32 counterF = 0; | ||
796 | u32 counterN = 0; | ||
797 | |||
798 | struct mtdids *id = part->dev->id; | ||
799 | mtd = get_nand_dev_by_index(id->num); | ||
800 | if (!mtd) { | ||
801 | pr_err("\nno NAND devices available\n"); | ||
802 | return 0; | ||
803 | } | ||
804 | |||
805 | /* if we are building a list we need to refresh the cache. */ | ||
806 | jffs_init_1pass_list(part); | ||
807 | pL = (struct b_lists *)part->jffs2_priv; | ||
808 | pL->partOffset = part->offset; | ||
809 | puts ("Scanning JFFS2 FS: "); | ||
810 | |||
811 | sectorsize = mtd->erasesize; | ||
812 | nr_blocks = part->size / sectorsize; | ||
813 | buf = malloc(sectorsize); | ||
814 | if (!buf) | ||
815 | return 0; | ||
816 | |||
817 | for (i = 0; i < nr_blocks; i++) { | ||
818 | printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]); | ||
819 | |||
820 | offset = part->offset + i * sectorsize; | ||
821 | |||
822 | if (nand_block_isbad(mtd, offset)) | ||
823 | continue; | ||
824 | |||
825 | if (jffs2_fill_scan_buf(mtd, buf, offset, EMPTY_SCAN_SIZE)) | ||
826 | return 0; | ||
827 | |||
828 | ofs = 0; | ||
829 | /* Scan only 4KiB of 0xFF before declaring it's empty */ | ||
830 | while (ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF) | ||
831 | ofs += 4; | ||
832 | if (ofs == EMPTY_SCAN_SIZE) | ||
833 | continue; | ||
834 | |||
835 | if (jffs2_fill_scan_buf(mtd, buf + EMPTY_SCAN_SIZE, offset + EMPTY_SCAN_SIZE, sectorsize - EMPTY_SCAN_SIZE)) | ||
836 | return 0; | ||
837 | offset += ofs; | ||
838 | |||
839 | while (ofs < sectorsize - sizeof(struct jffs2_unknown_node)) { | ||
840 | node = (struct jffs2_unknown_node *)&buf[ofs]; | ||
841 | if (node->magic != JFFS2_MAGIC_BITMASK || !hdr_crc(node)) { | ||
842 | offset += 4; | ||
843 | ofs += 4; | ||
844 | counter4++; | ||
845 | continue; | ||
846 | } | ||
847 | /* if its a fragment add it */ | ||
848 | if (node->nodetype == JFFS2_NODETYPE_INODE && | ||
849 | inode_crc((struct jffs2_raw_inode *) node)) { | ||
850 | if (insert_inode(&pL->frag, (struct jffs2_raw_inode *) node, | ||
851 | offset) == NULL) { | ||
852 | return 0; | ||
853 | } | ||
854 | } else if (node->nodetype == JFFS2_NODETYPE_DIRENT && | ||
855 | dirent_crc((struct jffs2_raw_dirent *) node) && | ||
856 | dirent_name_crc((struct jffs2_raw_dirent *) node)) { | ||
857 | if (! (counterN%100)) | ||
858 | puts ("\b\b. "); | ||
859 | if (insert_dirent(&pL->dir, (struct jffs2_raw_dirent *) node, | ||
860 | offset) == NULL) { | ||
861 | return 0; | ||
862 | } | ||
863 | counterN++; | ||
864 | } else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) { | ||
865 | if (node->totlen != sizeof(struct jffs2_unknown_node)) | ||
866 | printf("OOPS Cleanmarker has bad size " | ||
867 | "%d != %zu\n", | ||
868 | node->totlen, | ||
869 | sizeof(struct jffs2_unknown_node)); | ||
870 | } else if (node->nodetype == JFFS2_NODETYPE_PADDING) { | ||
871 | if (node->totlen < sizeof(struct jffs2_unknown_node)) | ||
872 | printf("OOPS Padding has bad size " | ||
873 | "%d < %zu\n", | ||
874 | node->totlen, | ||
875 | sizeof(struct jffs2_unknown_node)); | ||
876 | } else { | ||
877 | printf("Unknown node type: %x len %d offset 0x%x\n", | ||
878 | node->nodetype, | ||
879 | node->totlen, offset); | ||
880 | } | ||
881 | offset += ((node->totlen + 3) & ~3); | ||
882 | ofs += ((node->totlen + 3) & ~3); | ||
883 | counterF++; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | putstr("\b\b done.\r\n"); /* close off the dots */ | ||
888 | |||
889 | #if 0 | ||
890 | putLabeledWord("dir entries = ", pL->dir.listCount); | ||
891 | putLabeledWord("frag entries = ", pL->frag.listCount); | ||
892 | putLabeledWord("+4 increments = ", counter4); | ||
893 | putLabeledWord("+file_offset increments = ", counterF); | ||
894 | #endif | ||
895 | |||
896 | #ifdef DEBUG_DIRENTS | ||
897 | dump_dirents(pL); | ||
898 | #endif | ||
899 | |||
900 | #ifdef DEBUG_FRAGMENTS | ||
901 | dump_fragments(pL); | ||
902 | #endif | ||
903 | |||
904 | /* give visual feedback that we are done scanning the flash */ | ||
905 | led_blink(0x0, 0x0, 0x1, 0x1); /* off, forever, on 100ms, off 100ms */ | ||
906 | free(buf); | ||
907 | |||
908 | return 1; | ||
909 | } | ||
910 | |||
911 | |||
912 | static u32 | ||
913 | jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL) | ||
914 | { | ||
915 | struct b_node *b; | ||
916 | struct jffs2_raw_inode ojNode; | ||
917 | struct jffs2_raw_inode *jNode; | ||
918 | int i; | ||
919 | |||
920 | for (i = 0; i < JFFS2_NUM_COMPR; i++) { | ||
921 | piL->compr_info[i].num_frags = 0; | ||
922 | piL->compr_info[i].compr_sum = 0; | ||
923 | piL->compr_info[i].decompr_sum = 0; | ||
924 | } | ||
925 | /* FIXME | ||
926 | b = pL->frag.listHead; | ||
927 | while (b) { | ||
928 | jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, | ||
929 | sizeof(ojNode), &ojNode); | ||
930 | if (jNode->compr < JFFS2_NUM_COMPR) { | ||
931 | piL->compr_info[jNode->compr].num_frags++; | ||
932 | piL->compr_info[jNode->compr].compr_sum += jNode->csize; | ||
933 | piL->compr_info[jNode->compr].decompr_sum += jNode->dsize; | ||
934 | } | ||
935 | b = b->next; | ||
936 | } | ||
937 | */ | ||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | |||
942 | static struct b_lists * | ||
943 | jffs2_get_list(struct part_info * part, const char *who) | ||
944 | { | ||
945 | if (jffs2_1pass_rescan_needed(part)) { | ||
946 | if (!jffs2_1pass_build_lists(part)) { | ||
947 | printf("%s: Failed to scan JFFSv2 file structure\n", who); | ||
948 | return NULL; | ||
949 | } | ||
950 | } | ||
951 | return (struct b_lists *)part->jffs2_priv; | ||
952 | } | ||
953 | |||
954 | |||
955 | /* Print directory / file contents */ | ||
956 | u32 | ||
957 | jffs2_1pass_ls(struct part_info * part, const char *fname) | ||
958 | { | ||
959 | struct b_lists *pl; | ||
960 | long ret = 0; | ||
961 | u32 inode; | ||
962 | |||
963 | if (! (pl = jffs2_get_list(part, "ls"))) | ||
964 | return 0; | ||
965 | |||
966 | if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) { | ||
967 | putstr("ls: Failed to scan jffs2 file structure\r\n"); | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | #if 0 | ||
972 | putLabeledWord("found file at inode = ", inode); | ||
973 | putLabeledWord("read_inode returns = ", ret); | ||
974 | #endif | ||
975 | |||
976 | return ret; | ||
977 | } | ||
978 | |||
979 | |||
980 | /* Load a file from flash into memory. fname can be a full path */ | ||
981 | u32 | ||
982 | jffs2_1pass_load(char *dest, struct part_info * part, const char *fname) | ||
983 | { | ||
984 | |||
985 | struct b_lists *pl; | ||
986 | long ret = 0; | ||
987 | u32 inode; | ||
988 | |||
989 | if (! (pl = jffs2_get_list(part, "load"))) | ||
990 | return 0; | ||
991 | |||
992 | if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) { | ||
993 | putstr("load: Failed to find inode\r\n"); | ||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | /* Resolve symlinks */ | ||
998 | if (! (inode = jffs2_1pass_resolve_inode(pl, inode))) { | ||
999 | putstr("load: Failed to resolve inode structure\r\n"); | ||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | if ((ret = jffs2_1pass_read_inode(pl, inode, dest, NULL)) < 0) { | ||
1004 | putstr("load: Failed to read inode\r\n"); | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | DEBUGF ("load: loaded '%s' to 0x%lx (%ld bytes)\n", fname, | ||
1009 | (unsigned long) dest, ret); | ||
1010 | return ret; | ||
1011 | } | ||
1012 | |||
1013 | /* Return information about the fs on this partition */ | ||
1014 | u32 | ||
1015 | jffs2_1pass_info(struct part_info * part) | ||
1016 | { | ||
1017 | struct b_jffs2_info info; | ||
1018 | struct b_lists *pl; | ||
1019 | int i; | ||
1020 | |||
1021 | if (! (pl = jffs2_get_list(part, "info"))) | ||
1022 | return 0; | ||
1023 | |||
1024 | jffs2_1pass_fill_info(pl, &info); | ||
1025 | for (i = 0; i < JFFS2_NUM_COMPR; i++) { | ||
1026 | printf ("Compression: %s\n" | ||
1027 | "\tfrag count: %d\n" | ||
1028 | "\tcompressed sum: %d\n" | ||
1029 | "\tuncompressed sum: %d\n", | ||
1030 | compr_names[i], | ||
1031 | info.compr_info[i].num_frags, | ||
1032 | info.compr_info[i].compr_sum, | ||
1033 | info.compr_info[i].decompr_sum); | ||
1034 | } | ||
1035 | return 1; | ||
1036 | } | ||
1037 | 1 | #include <common.h> |
fs/jffs2/jffs2_nand_private.h
1 | #ifndef jffs2_private_h | File was deleted | |
2 | #define jffs2_private_h | ||
3 | |||
4 | #include <jffs2/jffs2.h> | ||
5 | |||
6 | struct b_node { | ||
7 | struct b_node *next; | ||
8 | }; | ||
9 | |||
10 | struct b_inode { | ||
11 | struct b_inode *next; | ||
12 | u32 offset; /* physical offset to beginning of real inode */ | ||
13 | u32 version; | ||
14 | u32 ino; | ||
15 | u32 isize; | ||
16 | u32 csize; | ||
17 | }; | ||
18 | |||
19 | struct b_dirent { | ||
20 | struct b_dirent *next; | ||
21 | u32 offset; /* physical offset to beginning of real dirent */ | ||
22 | u32 version; | ||
23 | u32 pino; | ||
24 | u32 ino; | ||
25 | unsigned int nhash; | ||
26 | unsigned char nsize; | ||
27 | unsigned char type; | ||
28 | }; | ||
29 | |||
30 | struct b_list { | ||
31 | struct b_node *listTail; | ||
32 | struct b_node *listHead; | ||
33 | unsigned int listCount; | ||
34 | struct mem_block *listMemBase; | ||
35 | }; | ||
36 | |||
37 | struct b_lists { | ||
38 | char *partOffset; | ||
39 | struct b_list dir; | ||
40 | struct b_list frag; | ||
41 | }; | ||
42 | |||
43 | struct b_compr_info { | ||
44 | u32 num_frags; | ||
45 | u32 compr_sum; | ||
46 | u32 decompr_sum; | ||
47 | }; | ||
48 | |||
49 | struct b_jffs2_info { | ||
50 | struct b_compr_info compr_info[JFFS2_NUM_COMPR]; | ||
51 | }; | ||
52 | |||
53 | static inline int | ||
54 | hdr_crc(struct jffs2_unknown_node *node) | ||
55 | { | ||
56 | #if 1 | ||
57 | u32 crc = crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4); | ||
58 | #else | ||
59 | /* what's the semantics of this? why is this here? */ | ||
60 | u32 crc = crc32_no_comp(~0, (unsigned char *)node, sizeof(struct jffs2_unknown_node) - 4); | ||
61 | |||
62 | crc ^= ~0; | ||
63 | #endif | ||
64 | if (node->hdr_crc != crc) { | ||
65 | return 0; | ||
66 | } else { | ||
67 | return 1; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | static inline int | ||
72 | dirent_crc(struct jffs2_raw_dirent *node) | ||
73 | { | ||
74 | if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_dirent) - 8)) { | ||
75 | return 0; | ||
76 | } else { | ||
77 | return 1; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static inline int | ||
82 | dirent_name_crc(struct jffs2_raw_dirent *node) | ||
83 | { | ||
84 | if (node->name_crc != crc32_no_comp(0, (unsigned char *)&(node->name), node->nsize)) { | ||
85 | return 0; | ||
86 | } else { | ||
87 | return 1; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static inline int | ||
92 | inode_crc(struct jffs2_raw_inode *node) | ||
93 | { | ||
94 | if (node->node_crc != crc32_no_comp(0, (unsigned char *)node, sizeof(struct jffs2_raw_inode) - 8)) { | ||
95 | return 0; | ||
96 | } else { | ||
97 | return 1; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | /* Borrowed from include/linux/dcache.h */ | ||
102 | |||
103 | /* Name hashing routines. Initial hash value */ | ||
104 | /* Hash courtesy of the R5 hash in reiserfs modulo sign bits */ | ||
105 | #define init_name_hash() 0 | ||
106 | |||
107 | /* partial hash update function. Assume roughly 4 bits per character */ | ||
108 | static inline unsigned long | ||
109 | partial_name_hash(unsigned long c, unsigned long prevhash) | ||
110 | { | ||
111 | return (prevhash + (c << 4) + (c >> 4)) * 11; | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Finally: cut down the number of bits to a int value (and try to avoid | ||
116 | * losing bits) | ||
117 | */ | ||
118 | static inline unsigned long end_name_hash(unsigned long hash) | ||
119 | { | ||
120 | return (unsigned int) hash; | ||
121 | } | ||
122 | |||
123 | /* Compute the hash for a name string. */ | ||
124 | static inline unsigned int | ||
125 | full_name_hash(const unsigned char *name, unsigned int len) | ||
126 | { | ||
127 | unsigned long hash = init_name_hash(); | ||
128 | while (len--) | ||
129 | hash = partial_name_hash(*name++, hash); | ||
130 | return end_name_hash(hash); | ||
131 | } | ||
132 | |||
133 | #endif /* jffs2_private.h */ | ||
134 | 1 | #ifndef jffs2_private_h |