📄 jffs2_1pass.c
字号:
cmp = strncmp(jNew->name, jOld->name, jNew->nsize); if (cmp != 0) return cmp > 0; /* we have duplicate names in this directory, so use ascending * sort by version */ if (jNew->version > jOld->version) { /* since jNew is newer, we know jOld is not valid, so * mark it with inode 0 and it will not be used */ jOld->ino = 0; return 1; } return 0;}#endifstatic u32jffs2_scan_empty(u32 start_offset, struct part_info *part){ char *max = part->offset + part->size - sizeof(struct jffs2_raw_inode); char *offset = part->offset + start_offset; u32 off; while (offset < max && *(u32*)get_fl_mem((u32)offset, sizeof(u32), &off) == 0xFFFFFFFF) { offset += sizeof(u32); /* return if spinning is due */ if (((u32)offset & ((1 << SPIN_BLKSIZE)-1)) == 0) break; } return offset - part->offset;}static u32jffs_init_1pass_list(struct part_info *part){ struct b_lists *pL; if (part->jffs2_priv != NULL) { pL = (struct b_lists *)part->jffs2_priv; free_nodes(&pL->frag); free_nodes(&pL->dir); free(pL); } if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) { pL = (struct b_lists *)part->jffs2_priv; memset(pL, 0, sizeof(*pL));#ifdef CFG_JFFS2_SORT_FRAGMENTS pL->dir.listCompare = compare_dirents; pL->frag.listCompare = compare_inodes;#endif } return 0;}/* find the inode from the slashless name given a parent */static longjffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest){ struct b_node *b; struct jffs2_raw_inode *jNode; u32 totalSize = 0; u32 latestVersion = 0; char *lDest; char *src; long ret; int i; u32 counter = 0;#ifdef CFG_JFFS2_SORT_FRAGMENTS /* Find file size before loading any data, so fragments that * start past the end of file can be ignored. A fragment * that is partially in the file is loaded, so extra data may * be loaded up to the next 4K boundary above the file size. * This shouldn't cause trouble when loading kernel images, so * we will live with it. */ for (b = pL->frag.listHead; b != NULL; b = b->next) { jNode = (struct jffs2_raw_inode *) get_fl_mem(b->offset, sizeof(struct jffs2_raw_inode), NULL); if ((inode == jNode->ino)) { /* get actual file length from the newest node */ if (jNode->version >= latestVersion) { totalSize = jNode->isize; latestVersion = jNode->version; } } put_fl_mem(jNode); }#endif for (b = pL->frag.listHead; b != NULL; b = b->next) { jNode = (struct jffs2_raw_inode *) get_node_mem(b->offset); if ((inode == jNode->ino)) {#if 0 putLabeledWord("\r\n\r\nread_inode: totlen = ", jNode->totlen); putLabeledWord("read_inode: inode = ", jNode->ino); putLabeledWord("read_inode: version = ", jNode->version); putLabeledWord("read_inode: isize = ", jNode->isize); putLabeledWord("read_inode: offset = ", jNode->offset); putLabeledWord("read_inode: csize = ", jNode->csize); putLabeledWord("read_inode: dsize = ", jNode->dsize); putLabeledWord("read_inode: compr = ", jNode->compr); putLabeledWord("read_inode: usercompr = ", jNode->usercompr); putLabeledWord("read_inode: flags = ", jNode->flags);#endif#ifndef CFG_JFFS2_SORT_FRAGMENTS /* get actual file length from the newest node */ if (jNode->version >= latestVersion) { totalSize = jNode->isize; latestVersion = jNode->version; }#endif if(dest) { src = ((char *) jNode) + sizeof(struct jffs2_raw_inode); /* ignore data behind latest known EOF */ if (jNode->offset > totalSize) { put_fl_mem(jNode); continue; } lDest = (char *) (dest + jNode->offset);#if 0 putLabeledWord("read_inode: src = ", src); putLabeledWord("read_inode: dest = ", lDest);#endif switch (jNode->compr) { case JFFS2_COMPR_NONE: ret = (unsigned long) ldr_memcpy(lDest, src, jNode->dsize); break; case JFFS2_COMPR_ZERO: ret = 0; for (i = 0; i < jNode->dsize; i++) *(lDest++) = 0; break; case JFFS2_COMPR_RTIME: ret = 0; rtime_decompress(src, lDest, jNode->csize, jNode->dsize); break; case JFFS2_COMPR_DYNRUBIN: /* this is slow but it works */ ret = 0; dynrubin_decompress(src, lDest, jNode->csize, jNode->dsize); break; case JFFS2_COMPR_ZLIB: ret = zlib_decompress(src, lDest, jNode->csize, jNode->dsize); break; default: /* unknown */ putLabeledWord("UNKOWN COMPRESSION METHOD = ", jNode->compr); put_fl_mem(jNode); return -1; break; } }#if 0 putLabeledWord("read_inode: totalSize = ", totalSize); putLabeledWord("read_inode: compr ret = ", ret);#endif } counter++; put_fl_mem(jNode); }#if 0 putLabeledWord("read_inode: returning = ", totalSize);#endif return totalSize;}/* find the inode from the slashless name given a parent */static u32jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino){ struct b_node *b; struct jffs2_raw_dirent *jDir; int len; u32 counter; u32 version = 0; u32 inode = 0; /* name is assumed slash free */ len = strlen(name); counter = 0; /* we need to search all and return the inode with the highest version */ for(b = pL->dir.listHead; b; b = b->next, counter++) { jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset); if ((pino == jDir->pino) && (len == jDir->nsize) && (jDir->ino) && /* 0 for unlink */ (!strncmp(jDir->name, name, len))) { /* a match */ if (jDir->version < version) { put_fl_mem(jDir); continue; } if (jDir->version == version && inode != 0) { /* I'm pretty sure this isn't legal */ putstr(" ** ERROR ** "); putnstr(jDir->name, jDir->nsize); putLabeledWord(" has dup version =", version); } inode = jDir->ino; version = jDir->version; }#if 0 putstr("\r\nfind_inode:p&l ->"); putnstr(jDir->name, jDir->nsize); putstr("\r\n"); putLabeledWord("pino = ", jDir->pino); putLabeledWord("nsize = ", jDir->nsize); putLabeledWord("b = ", (u32) b); putLabeledWord("counter = ", counter);#endif put_fl_mem(jDir); } return inode;}char *mkmodestr(unsigned long mode, char *str){ static const char *l = "xwr"; int mask = 1, i; char c; switch (mode & S_IFMT) { case S_IFDIR: str[0] = 'd'; break; case S_IFBLK: str[0] = 'b'; break; case S_IFCHR: str[0] = 'c'; break; case S_IFIFO: str[0] = 'f'; break; case S_IFLNK: str[0] = 'l'; break; case S_IFSOCK: str[0] = 's'; break; case S_IFREG: str[0] = '-'; break; default: str[0] = '?'; } for(i = 0; i < 9; i++) { c = l[i%3]; str[9-i] = (mode & mask)?c:'-'; mask = mask<<1; } if(mode & S_ISUID) str[3] = (mode & S_IXUSR)?'s':'S'; if(mode & S_ISGID) str[6] = (mode & S_IXGRP)?'s':'S'; if(mode & S_ISVTX) str[9] = (mode & S_IXOTH)?'t':'T'; str[10] = '\0'; return str;}static inline void dump_stat(struct stat *st, const char *name){ char str[20]; char s[64], *p; if (st->st_mtime == (time_t)(-1)) /* some ctimes really hate -1 */ st->st_mtime = 1; ctime_r(&st->st_mtime, s/*,64*/); /* newlib ctime doesn't have buflen */ if ((p = strchr(s,'\n')) != NULL) *p = '\0'; if ((p = strchr(s,'\r')) != NULL) *p = '\0';/* printf("%6lo %s %8ld %s %s\n", st->st_mode, mkmodestr(st->st_mode, str), st->st_size, s, name);*/ printf(" %s %8ld %s %s", mkmodestr(st->st_mode,str), st->st_size, s, name);}static inline u32 dump_inode(struct b_lists * pL, struct jffs2_raw_dirent *d, struct jffs2_raw_inode *i){ char fname[256]; struct stat st; if(!d || !i) return -1; strncpy(fname, d->name, d->nsize); fname[d->nsize] = '\0'; memset(&st,0,sizeof(st)); st.st_mtime = i->mtime; st.st_mode = i->mode; st.st_ino = i->ino; /* neither dsize nor isize help us.. do it the long way */ st.st_size = jffs2_1pass_read_inode(pL, i->ino, NULL); dump_stat(&st, fname); if (d->type == DT_LNK) { unsigned char *src = (unsigned char *) (&i[1]); putstr(" -> "); putnstr(src, (int)i->dsize); } putstr("\r\n"); return 0;}/* list inodes with the given pino */static u32jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino){ struct b_node *b; struct jffs2_raw_dirent *jDir; for (b = pL->dir.listHead; b; b = b->next) { jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset); if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */ u32 i_version = 0; struct jffs2_raw_inode ojNode; struct jffs2_raw_inode *jNode, *i = NULL; struct b_node *b2 = pL->frag.listHead; while (b2) { jNode = (struct jffs2_raw_inode *) get_fl_mem(b2->offset, sizeof(ojNode), &ojNode); if (jNode->ino == jDir->ino && jNode->version >= i_version) { if (i) put_fl_mem(i); i = get_fl_mem(b2->offset, sizeof(*i), NULL); } b2 = b2->next; } dump_inode(pL, jDir, i); put_fl_mem(i); } put_fl_mem(jDir); } return pino;}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; u8 jDirFoundType = 0; u32 jDirFoundIno = 0; u32 jDirFoundPino = 0; 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->dir.listHead; b; b = b->next) { jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset); if (ino == jDir->ino) { if (jDir->version < version) { put_fl_mem(jDir); continue; } if (jDir->version == version && jDirFoundType) { /* I'm pretty sure this isn't legal */ putstr(" ** ERROR ** "); putnstr(jDir->name, jDir->nsize); putLabeledWord(" has dup version (resolve) = ", version); } jDirFoundType = jDir->type; jDirFoundIno = jDir->ino; jDirFoundPino = jDir->pino;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -