📄 jffs2_1pass.c
字号:
/* 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 *) (b->offset); if ((inode == jNode->ino)) { /* get actual file length from the newest node */ if (jNode->version >= latestVersion) { totalSize = jNode->isize; latestVersion = jNode->version; } } }#endif for (b = pL->frag.listHead; b != NULL; b = b->next) { jNode = (struct jffs2_raw_inode *) (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) 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); return -1; break; } }#if 0 putLabeledWord("read_inode: totalSize = ", totalSize); putLabeledWord("read_inode: compr ret = ", ret);#endif } counter++; }#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 *) (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) 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 } return inode;}static 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 *) (b->offset); if ((pino == jDir->pino) && (jDir->ino)) { /* ino=0 -> unlink */ u32 i_version = 0; struct jffs2_raw_inode *jNode, *i = NULL; struct b_node *b2 = pL->frag.listHead; while (b2) { jNode = (struct jffs2_raw_inode *) (b2->offset); if (jNode->ino == jDir->ino && jNode->version >= i_version) i = jNode; b2 = b2->next; } dump_inode(pL, jDir, i); } } 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; 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->dir.listHead; b; b = b->next) { jDir = (struct jffs2_raw_dirent *) (b->offset); if (ino == jDir->ino) { if (jDir->version < version) continue; if (jDir->version == version && jDirFound) { /* I'm pretty sure this isn't legal */ 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; /* it's a soft link so we follow it again. */ b2 = pL->frag.listHead; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -