📄 jffs2_1pass.c
字号:
static u32jffs2_1pass_search_inode(struct b_lists * pL, const char *fname, u32 pino){ int i; char tmp[256]; char working_tmp[256]; char *c; // discard any leading slash i = 0; while (fname[i] == '/') i++; strcpy(tmp, &fname[i]); while ((c = (char *) strchr(tmp, '/'))) // we are still dired searching { strncpy(working_tmp, tmp, c - tmp); working_tmp[c - tmp] = '\0';#if 0 putstr("search_inode: tmp = "); putstr(tmp); putstr("\r\n"); putstr("search_inode: wtmp = "); putstr(working_tmp); putstr("\r\n"); putstr("search_inode: c = "); putstr(c); putstr("\r\n");#endif for (i = 0; i < strlen(c) - 1; i++) tmp[i] = c[i + 1]; tmp[i] = '\0';#if 0 putstr("search_inode: post tmp = "); putstr(tmp); putstr("\r\n");#endif if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino))) { putstr("find_inode failed for name="); putstr(working_tmp); putstr("\r\n"); return 0; } } // this is for the bare filename, directories have already been mapped if (!(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { putstr("find_inode failed for name="); putstr(tmp); putstr("\r\n"); return 0; } return pino;}static u32jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino){ struct b_node *b; struct b_node *b2; struct jffs2_raw_dirent *jDir; struct jffs2_raw_inode *jNode; struct jffs2_raw_dirent *jDirFound = NULL; char tmp[256]; u32 version = 0; u32 pino; unsigned char *src; // we need to search all and return the inode with the highest version for(b = pL->dirListHead; b; b=b->next) { jDir = (struct jffs2_raw_dirent *) (b->offset); if (ino == jDir->ino) { if(jDir->version < version) continue; if(jDir->version == 0) { /* Is this legal? */ putstr(" ** WARNING ** "); putnstr(jDir->name, jDir->nsize); putstr(" is version 0 (in resolve, ignoring)\r\n"); } else if(jDir->version == version) { /* Im pretty sure this isn't ... */ putstr(" ** ERROR ** "); putnstr(jDir->name, jDir->nsize); putLabeledWord(" has dup version (resolve) = ", version); } jDirFound = jDir; version = jDir->version; } } // now we found the right entry again. (shoulda returned inode*) if (jDirFound->type != DT_LNK) return jDirFound->ino; // so its a soft link so we follow it again. b2 = pL->fragListHead; while (b2) { jNode = (struct jffs2_raw_inode *) (b2->offset); if (jNode->ino == jDirFound->ino) { src = (unsigned char *) (b2->offset + sizeof(struct jffs2_raw_inode));#if 0 putLabeledWord("\t\t dsize = ", jNode->dsize); putstr("\t\t target = "); putnstr(src, jNode->dsize); putstr("\r\n");#endif strncpy(tmp, src, jNode->dsize); tmp[jNode->dsize] = '\0'; break; } b2 = b2->next; } // ok so the name of the new file to find is in tmp // if it starts with a slash it is root based else shared dirs if (tmp[0] == '/') pino = 1; else pino = jDirFound->pino; return jffs2_1pass_search_inode(pL, tmp, pino);}static u32jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino){ int i; char tmp[256]; char working_tmp[256]; char *c; // discard any leading slash i = 0; while (fname[i] == '/') i++; strcpy(tmp, &fname[i]); working_tmp[0] = '\0'; while ((c = (char *) strchr(tmp, '/'))) // we are still dired searching { strncpy(working_tmp, tmp, c - tmp); working_tmp[c - tmp] = '\0'; for (i = 0; i < strlen(c) - 1; i++) tmp[i] = c[i + 1]; tmp[i] = '\0'; // only a failure if we arent looking at top level if (!(pino = jffs2_1pass_find_inode(pL, working_tmp, pino)) && (working_tmp[0])) { putstr("find_inode failed for name="); putstr(working_tmp); putstr("\r\n"); return 0; } } if (tmp[0] && !(pino = jffs2_1pass_find_inode(pL, tmp, pino))) { putstr("find_inode failed for name="); putstr(tmp); putstr("\r\n"); return 0; } // this is for the bare filename, directories have already been mapped if (!(pino = jffs2_1pass_list_inodes(pL, pino))) { putstr("find_inode failed for name="); putstr(tmp); putstr("\r\n"); return 0; } return pino;}unsigned charjffs2_1pass_rescan_needed(struct part_info *part, struct b_lists *pL){ unsigned char ret = 0; struct b_node *b; struct jffs2_unknown_node *node; // if we have no list, we need to rescan if (pL->fragListCount == 0) { DEBUGF ("rescan: fraglist zero\n"); return 1; } // or if we are scanninga new partition if (pL->partOffset != part->offset) { DEBUGF ("rescan: different partition\n"); return 1; } // but suppose someone reflashed the root partition at the same offset... b = pL->dirListHead; while (b) { node = (struct jffs2_unknown_node *) (b->offset); if (node->nodetype != JFFS2_NODETYPE_DIRENT) { DEBUGF ("rescan: fs changed beneath me? (%lx)\n", (unsigned long) b->offset); return 1; } b = b->next; } return ret;}static u32jffs2_1pass_build_lists(struct part_info * part, struct b_lists * pL){ struct jffs2_unknown_node *node; u32 offset; u32 max = part->size - sizeof(struct jffs2_raw_inode); u32 counter = 0; u32 counter4 = 0; u32 counterF = 0; u32 counterN = 0; // turn off the lcd. Refreshing the lcd adds 50% overhead to the // jffs2 list building enterprise nope. in newer versions the overhead is // only about 5 %. not enough to inconvenience people for. // lcd_off(); // if we are building a list we need to refresh the cache. // note that since we don't free our memory, eventually this will be bad. // but we're a bootldr so what the hell. jffs_init_1pass_list(); pL->partOffset = part->offset; offset = 0; printf("Scanning JFFS2 FS: "); /* start at the beginning of the partition */ while (offset < max) { if (! (++counter%10000)) printf("\b\b%c ", spinner[(counter / 10000) % 4]); node = (struct jffs2_unknown_node *) (part->offset + offset); if (node->magic == JFFS2_MAGIC_BITMASK && hdr_crc(node)) { // if its a fragment add it if (node->nodetype == JFFS2_NODETYPE_INODE && inode_crc((struct jffs2_raw_inode *) node)) { if (!(pL->fragListTail = add_node(pL->fragListTail, &(pL->fragListCount), &(pL->fragListMemBase)))) { putstr("add_node failed!\r\n"); return 0; } pL->fragListTail->offset = (u32) (part->offset + offset); if (!pL->fragListHead) pL->fragListHead = pL->fragListTail; } else if (node->nodetype == JFFS2_NODETYPE_DIRENT && dirent_crc((struct jffs2_raw_dirent *) node) && dirent_name_crc((struct jffs2_raw_dirent *) node)) { if (! (counterN%100)) printf("\b\b. ");#if 0 printf("Found DIRENT @ 0x%lx\n", offset); putstr("\r\nbuild_lists:p&l ->"); putnstr(((struct jffs2_raw_dirent *) node)->name, ((struct jffs2_raw_dirent *) node)->nsize); putstr("\r\n"); putLabeledWord("\tpino = ", ((struct jffs2_raw_dirent *) node)->pino); putLabeledWord("\tnsize = ", ((struct jffs2_raw_dirent *) node)->nsize);#endif if (!(pL->dirListTail = add_node(pL->dirListTail, &(pL->dirListCount), &(pL->dirListMemBase)))) { putstr("add_node failed!\r\n"); return 0; } pL->dirListTail->offset = (u32) (part->offset + offset);#if 0 putLabeledWord("\ttail = ", (u32) pL->dirListTail); putstr("\ttailName ->"); putnstr(((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->name, ((struct jffs2_raw_dirent *) (pL->dirListTail->offset))->nsize); putstr("\r\n");#endif if (!pL->dirListHead) pL->dirListHead = pL->dirListTail; counterN++; } else if (node->nodetype == JFFS2_NODETYPE_CLEANMARKER) { if (node->totlen != sizeof(struct jffs2_unknown_node)) printf("OOPS Cleanmarker has bad size %d != %d\n", node->totlen, sizeof(struct jffs2_unknown_node)); } else { printf("Unknown node type: %x len %d offset 0x%lx\n", node->nodetype, node->totlen, offset); } offset += ((node->totlen + 3) & ~3); counterF++; } else if (node->magic == JFFS2_EMPTY_BITMASK && node->nodetype == JFFS2_EMPTY_BITMASK) { offset = jffs2_scan_empty(offset, part); } else { // if we know nothing of the filesystem, we just step and look. offset += 4; counter4++; }// printf("unknown node magic %4.4x %4.4x @ %lx\n", node->magic, node->nodetype, (unsigned long)node); } putstr("\b\b done.\r\n"); // close off the dots // turn the lcd back on. // splash();#if 0 putLabeledWord("dir entries = ", pL->dirListCount); putLabeledWord("frag entries = ", pL->fragListCount); putLabeledWord("+4 increments = ", counter4); putLabeledWord("+file_offset increments = ", counterF);#endif#undef SHOW_ALL#undef SHOW_ALL_FRAGMENTS#ifdef SHOW_ALL { struct b_node *b; struct b_node *b2; struct jffs2_raw_dirent *jDir; struct jffs2_raw_inode *jNode; putstr("\r\n\r\n******The directory Entries******\r\n"); b = pL->dirListHead; while (b) { jDir = (struct jffs2_raw_dirent *) (b->offset); putstr("\r\n"); putnstr(jDir->name, jDir->nsize); putLabeledWord("\r\n\tbuild_list: magic = ", jDir->magic); putLabeledWord("\tbuild_list: nodetype = ", jDir->nodetype); putLabeledWord("\tbuild_list: hdr_crc = ", jDir->hdr_crc); putLabeledWord("\tbuild_list: pino = ", jDir->pino); putLabeledWord("\tbuild_list: version = ", jDir->version); putLabeledWord("\tbuild_list: ino = ", jDir->ino); putLabeledWord("\tbuild_list: mctime = ", jDir->mctime); putLabeledWord("\tbuild_list: nsize = ", jDir->nsize); putLabeledWord("\tbuild_list: type = ", jDir->type); putLabeledWord("\tbuild_list: node_crc = ", jDir->node_crc); putLabeledWord("\tbuild_list: name_crc = ", jDir->name_crc); b = b->next; }#ifdef SHOW_ALL_FRAGMENTS putstr("\r\n\r\n******The fragment Entries******\r\n"); b = pL->fragListHead; while (b) { jNode = (struct jffs2_raw_inode *) (b->offset); putLabeledWord("\r\n\tbuild_list: FLASH_OFFSET = ", b->offset); putLabeledWord("\tbuild_list: totlen = ", jNode->totlen); putLabeledWord("\tbuild_list: inode = ", jNode->ino); putLabeledWord("\tbuild_list: version = ", jNode->version); putLabeledWord("\tbuild_list: isize = ", jNode->isize); putLabeledWord("\tbuild_list: atime = ", jNode->atime); putLabeledWord("\tbuild_list: offset = ", jNode->offset); putLabeledWord("\tbuild_list: csize = ", jNode->csize); putLabeledWord("\tbuild_list: dsize = ", jNode->dsize); putLabeledWord("\tbuild_list: compr = ", jNode->compr); putLabeledWord("\tbuild_list: usercompr = ", jNode->usercompr); putLabeledWord("\tbuild_list: flags = ", jNode->flags); b = b->next; }#endif /* SHOW_ALL_FRAGMENTS */ }#endif /* SHOW_ALL */ // give visual feedback that we are done scanning the flash led_blink(0x0, 0x0, 0x1, 0x1); // off, forever, on 100ms, off 100ms return 1;}static u32jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL){ struct b_node *b; struct jffs2_raw_inode *jNode; int i; b = pL->fragListHead; for (i = 0; i < JFFS2_NUM_COMPR; i++) { piL->compr_info[i].num_frags = 0; piL->compr_info[i].compr_sum = 0; piL->compr_info[i].decompr_sum = 0; } while (b) { jNode = (struct jffs2_raw_inode *) (b->offset); if (jNode->compr < JFFS2_NUM_COMPR) { piL->compr_info[jNode->compr].num_frags++; piL->compr_info[jNode->compr].compr_sum += jNode->csize; piL->compr_info[jNode->compr].decompr_sum += jNode->dsize; } b = b->next; } return 0;}static struct b_lists *jffs2_get_list(struct part_info * part, const char *who){ struct b_lists *pl = &g_1PassList; if (jffs2_1pass_rescan_needed(part, pl)) { if (!jffs2_1pass_build_lists(part, pl)) { printf("%s: Failed to scan JFFSv2 file structure\n", who); return NULL; } } return pl;}/* Print directory / file contents */u32jffs2_1pass_ls(struct part_info * part, const char *fname){ struct b_lists *pl; long ret = 0; u32 inode; if (! (pl = jffs2_get_list(part, "ls"))) return 0; if (! (inode = jffs2_1pass_search_list_inodes(pl, fname, 1))) { putstr("ls: Failed to scan jffs2 file structure\r\n"); return 0; }#if 0 putLabeledWord("found file at inode = ", inode); putLabeledWord("read_inode returns = ", ret);#endif return ret;}/* Load a file from flash into memory. fname can be a full path */u32jffs2_1pass_load(char *dest, struct part_info * part, const char *fname){ struct b_lists *pl; long ret = 0; u32 inode; if (! (pl = jffs2_get_list(part, "load"))) return 0; if (! (inode = jffs2_1pass_search_inode(pl, fname, 1))) { putstr("load: Failed to find inode\r\n"); return 0; } /* Resolve symlinks */ if (! (inode = jffs2_1pass_resolve_inode(pl, inode))) { putstr("load: Failed to resolve inode structure\r\n"); return 0; } if ((ret = jffs2_1pass_read_inode(pl, inode, dest)) < 0) { putstr("load: Failed to read inode\r\n"); return 0; } DEBUGF ("load: loaded '%s' to 0x%lx (%ld bytes)\n", fname, (unsigned long) dest, ret); return ret;}/* Return information about the fs on this partition */u32jffs2_1pass_info(struct part_info * part){ struct b_jffs2_info info; struct b_lists *pl = &g_1PassList; int i; if (! (pl = jffs2_get_list(part, "info"))) return 0; jffs2_1pass_fill_info(pl, &info); for (i=0; i < JFFS2_NUM_COMPR; i++) { printf("Compression: %s\n", compr_names[i]); printf("\tfrag count: %ld\n", info.compr_info[i].num_frags); printf("\tcompressed sum: %ld\n", info.compr_info[i].compr_sum); printf("\tuncompressed sum: %ld\n", info.compr_info[i].decompr_sum); } return 1;}#endif /* CFG_CMD_JFFS2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -