static int io_lines (lua_State *L) { if (lua_isnoneornil(L, 1)) { /* no arguments? */ /* will iterate over default input */ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); return f_lines(L); } else { const char *filename = luaL_checkstring(L, 1); FILE **pf = newfile(L); *pf = fopen(filename, "r"); if (*pf == NULL) fileerror(L, 1, filename); aux_lines(L, lua_gettop(L), 1); return 1; } }
static int g_iofile (lua_State *L, int f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); if (filename) { FILE **pf = newfile(L); *pf = fopen(filename, mode); if (*pf == NULL) fileerror(L, 1, filename); } else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } LUA_IO_SETFIELD(f); } /* return current value */ LUA_IO_GETFIELD(f); return 1; }
static int g_iofile (lua_State *L, int f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); if (filename) { FILE **pf = newfile(L); *pf = wrap_fopen(filename, mode); if (*pf == NULL) fileerror(L, 1, filename); } else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } lua_rawseti(L, LUA_ENVIRONINDEX, f); } /* return current value */ lua_rawgeti(L, LUA_ENVIRONINDEX, f); return 1; }
pass2() { register struct dinode *dp; register struct inoinfo **inpp, *inp; struct inoinfo **inpend; struct inodesc curino; struct dinode dino; char pathbuf[MAXPATHLEN + 1]; switch (statemap[ROOTINO]) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) errexit(""); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; } if (reply("CONTINUE") == 0) errexit(""); break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; } if (reply("FIX") == 0) errexit(""); dp = ginode(ROOTINO); dp->di_mode &= ~IFMT; dp->di_mode |= IFDIR; inodirty(); break; case DSTATE: break; default: errexit("BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]); } statemap[ROOTINO] = DFOUND; /* * Sort the directory list into disk block order. */ qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); /* * Check the integrity of each directory. */ bzero((char *)&curino, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; dp = &dino; inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_isize == 0) continue; if (inp->i_isize < MINDIRSIZE) { direrror(inp->i_number, "DIRECTORY TOO SHORT"); inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); if (reply("FIX") == 1) { dp = ginode(inp->i_number); dp->di_size = inp->i_isize; inodirty(); dp = &dino; } } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { getpathname(pathbuf, inp->i_number, inp->i_number); pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", pathbuf, inp->i_isize, DIRBLKSIZ); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); inodirty(); dp = &dino; } } bzero((char *)&dino, sizeof(struct dinode)); dino.di_mode = IFDIR; dp->di_size = inp->i_isize; bcopy((char *)&inp->i_blks[0], (char *)&dp->di_db[0], (size_t)inp->i_numblks); curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(dp, &curino); } /* * Now that the parents of all directories have been found, * make another pass to verify the value of `..' */ for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_isize == 0) continue; if (statemap[inp->i_parent] == DFOUND && statemap[inp->i_number] == DSTATE) statemap[inp->i_number] = DFOUND; if (inp->i_dotdot == inp->i_parent || inp->i_dotdot == (ino_t)-1) continue; if (inp->i_dotdot == 0) { inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); if (reply("FIX") == 0) continue; (void)makeentry(inp->i_number, inp->i_parent, ".."); lncntp[inp->i_parent]--; continue; } fileerror(inp->i_parent, inp->i_number, "BAD INODE NUMBER FOR '..'"); if (reply("FIX") == 0) continue; lncntp[inp->i_dotdot]++; lncntp[inp->i_parent]--; inp->i_dotdot = inp->i_parent; (void)changeino(inp->i_number, "..", inp->i_parent); } /* * Mark all the directories that can be found from the root. */ propagate(); }
void pass2(void) { union dinode *dp; struct inoinfo **inpp, *inp; struct inoinfo **inpend; struct inodesc curino; union dinode dino; int i; char pathbuf[MAXPATHLEN + 1]; switch (inoinfo(ROOTINO)->ino_state) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) { ckfini(0); exit(EEXIT); } if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; } if (reply("CONTINUE") == 0) { ckfini(0); exit(EEXIT); } break; case FSTATE: case FCLEAR: case FZLINK: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; } if (reply("FIX") == 0) { ckfini(0); exit(EEXIT); } dp = ginode(ROOTINO); DIP_SET(dp, di_mode, DIP(dp, di_mode) & ~IFMT); DIP_SET(dp, di_mode, DIP(dp, di_mode) | IFDIR); inodirty(); break; case DSTATE: case DZLINK: break; default: errx(EEXIT, "BAD STATE %d FOR ROOT INODE", inoinfo(ROOTINO)->ino_state); } inoinfo(ROOTINO)->ino_state = DFOUND; inoinfo(WINO)->ino_state = FSTATE; inoinfo(WINO)->ino_type = DT_WHT; /* * Sort the directory list into disk block order. */ qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); /* * Check the integrity of each directory. */ memset(&curino, 0, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { if (got_siginfo) { printf("%s: phase 2: dir %td of %d (%d%%)\n", cdevname, inpp - inpsort, (int)inplast, (int)((inpp - inpsort) * 100 / inplast)); got_siginfo = 0; } if (got_sigalarm) { setproctitle("%s p2 %d%%", cdevname, (int)((inpp - inpsort) * 100 / inplast)); got_sigalarm = 0; } inp = *inpp; if (inp->i_isize == 0) continue; if (inp->i_isize < MINDIRSIZE) { direrror(inp->i_number, "DIRECTORY TOO SHORT"); inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); if (reply("FIX") == 1) { dp = ginode(inp->i_number); DIP_SET(dp, di_size, inp->i_isize); inodirty(); } } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { getpathname(pathbuf, inp->i_number, inp->i_number); if (usedsoftdep) pfatal("%s %s: LENGTH %jd NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, (intmax_t)inp->i_isize, DIRBLKSIZ); else pwarn("%s %s: LENGTH %jd NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, (intmax_t)inp->i_isize, DIRBLKSIZ); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); DIP_SET(dp, di_size, roundup(inp->i_isize, DIRBLKSIZ)); inodirty(); } } dp = &dino; memset(dp, 0, sizeof(struct ufs2_dinode)); DIP_SET(dp, di_mode, IFDIR); DIP_SET(dp, di_size, inp->i_isize); for (i = 0; i < (inp->i_numblks<NDADDR ? inp->i_numblks : NDADDR); i++) DIP_SET(dp, di_db[i], inp->i_blks[i]); if (inp->i_numblks > NDADDR) for (i = 0; i < NIADDR; i++) DIP_SET(dp, di_ib[i], inp->i_blks[NDADDR + i]); curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(dp, &curino); } /* * Now that the parents of all directories have been found, * make another pass to verify the value of `..' */ for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_isize == 0) continue; if (inoinfo(inp->i_parent)->ino_state == DFOUND && INO_IS_DUNFOUND(inp->i_number)) inoinfo(inp->i_number)->ino_state = DFOUND; if (inp->i_dotdot == inp->i_parent || inp->i_dotdot == (ino_t)-1) continue; if (inp->i_dotdot == 0) { inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); if (reply("FIX") == 0) continue; (void)makeentry(inp->i_number, inp->i_parent, ".."); inoinfo(inp->i_parent)->ino_linkcnt--; continue; } /* * Here we have: * inp->i_number is directory with bad ".." in it. * inp->i_dotdot is current value of "..". * inp->i_parent is directory to which ".." should point. */ getpathname(pathbuf, inp->i_parent, inp->i_number); printf("BAD INODE NUMBER FOR '..' in DIR I=%d (%s)\n", inp->i_number, pathbuf); getpathname(pathbuf, inp->i_dotdot, inp->i_dotdot); printf("CURRENTLY POINTS TO I=%d (%s), ", inp->i_dotdot, pathbuf); getpathname(pathbuf, inp->i_parent, inp->i_parent); printf("SHOULD POINT TO I=%d (%s)", inp->i_parent, pathbuf); if (cursnapshot != 0) { /* * We need to: * setcwd(inp->i_number); * setdotdot(inp->i_dotdot, inp->i_parent); */ cmd.value = inp->i_number; if (sysctlbyname("vfs.ffs.setcwd", 0, 0, &cmd, sizeof cmd) == -1) { /* kernel lacks support for these functions */ printf(" (IGNORED)\n"); continue; } cmd.value = inp->i_dotdot; /* verify same value */ cmd.size = inp->i_parent; /* new parent */ if (sysctlbyname("vfs.ffs.setdotdot", 0, 0, &cmd, sizeof cmd) == -1) { printf(" (FIX FAILED: %s)\n", strerror(errno)); continue; } printf(" (FIXED)\n"); inoinfo(inp->i_parent)->ino_linkcnt--; inp->i_dotdot = inp->i_parent; continue; } if (preen) printf(" (FIXED)\n"); else if (reply("FIX") == 0) continue; inoinfo(inp->i_dotdot)->ino_linkcnt++; inoinfo(inp->i_parent)->ino_linkcnt--; inp->i_dotdot = inp->i_parent; (void)changeino(inp->i_number, "..", inp->i_parent); } /* * Mark all the directories that can be found from the root. */ propagate(); }
static int pass2check(struct inodesc *idesc) { struct direct *dirp = idesc->id_dirp; char dirname[MAXPATHLEN + 1]; struct inoinfo *inp; int n, entrysize, ret = 0; union dinode *dp; const char *errmsg; struct direct proto; /* * check for "." */ if (dirp->d_ino > maxino) goto chk2; if (idesc->id_entryno != 0) goto chk1; if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { if (dirp->d_ino != idesc->id_number) { direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); dirp->d_ino = idesc->id_number; if (reply("FIX") == 1) ret |= ALTERED; } if (dirp->d_type != DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); dirp->d_type = DT_DIR; if (reply("FIX") == 1) ret |= ALTERED; } goto chk1; } direrror(idesc->id_number, "MISSING '.'"); proto.d_ino = idesc->id_number; proto.d_type = DT_DIR; proto.d_namlen = 1; (void)strcpy(proto.d_name, "."); entrysize = DIRSIZ(0, &proto); if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); } else if (dirp->d_reclen < entrysize) { pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); } else if (dirp->d_reclen < 2 * entrysize) { proto.d_reclen = dirp->d_reclen; memmove(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; } else { n = dirp->d_reclen - entrysize; proto.d_reclen = entrysize; memmove(dirp, &proto, (size_t)entrysize); idesc->id_entryno++; inoinfo(dirp->d_ino)->ino_linkcnt--; dirp = (struct direct *)((char *)(dirp) + entrysize); memset(dirp, 0, (size_t)n); dirp->d_reclen = n; if (reply("FIX") == 1) ret |= ALTERED; } chk1: if (idesc->id_entryno > 1) goto chk2; inp = getinoinfo(idesc->id_number); proto.d_ino = inp->i_parent; proto.d_type = DT_DIR; proto.d_namlen = 2; (void)strcpy(proto.d_name, ".."); entrysize = DIRSIZ(0, &proto); if (idesc->id_entryno == 0) { n = DIRSIZ(0, dirp); if (dirp->d_reclen < n + entrysize) goto chk2; proto.d_reclen = dirp->d_reclen - n; dirp->d_reclen = n; idesc->id_entryno++; inoinfo(dirp->d_ino)->ino_linkcnt--; dirp = (struct direct *)((char *)(dirp) + n); memset(dirp, 0, (size_t)proto.d_reclen); dirp->d_reclen = proto.d_reclen; } if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { inp->i_dotdot = dirp->d_ino; if (dirp->d_type != DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); dirp->d_type = DT_DIR; if (reply("FIX") == 1) ret |= ALTERED; } goto chk2; } if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); inp->i_dotdot = (ino_t)-1; } else if (dirp->d_reclen < entrysize) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); inp->i_dotdot = (ino_t)-1; } else if (inp->i_parent != 0) { /* * We know the parent, so fix now. */ inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); proto.d_reclen = dirp->d_reclen; memmove(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; } idesc->id_entryno++; if (dirp->d_ino != 0) inoinfo(dirp->d_ino)->ino_linkcnt--; return (ret|KEEPON); chk2: if (dirp->d_ino == 0) return (ret|KEEPON); if (dirp->d_namlen <= 2 && dirp->d_name[0] == '.' && idesc->id_entryno >= 2) { if (dirp->d_namlen == 1) { direrror(idesc->id_number, "EXTRA '.' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } if (dirp->d_name[1] == '.') { direrror(idesc->id_number, "EXTRA '..' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } } idesc->id_entryno++; n = 0; if (dirp->d_ino > maxino) { fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); n = reply("REMOVE"); } else if (((dirp->d_ino == WINO && dirp->d_type != DT_WHT) || (dirp->d_ino != WINO && dirp->d_type == DT_WHT))) { fileerror(idesc->id_number, dirp->d_ino, "BAD WHITEOUT ENTRY"); dirp->d_ino = WINO; dirp->d_type = DT_WHT; if (reply("FIX") == 1) ret |= ALTERED; } else { again: switch (inoinfo(dirp->d_ino)->ino_state) { case USTATE: if (idesc->id_entryno <= 2) break; fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); n = reply("REMOVE"); break; case DCLEAR: case FCLEAR: if (idesc->id_entryno <= 2) break; if (inoinfo(dirp->d_ino)->ino_state == FCLEAR) errmsg = "DUP/BAD"; else if (!preen && !usedsoftdep) errmsg = "ZERO LENGTH DIRECTORY"; else if (cursnapshot == 0) { n = 1; break; } else { getpathname(dirname, idesc->id_number, dirp->d_ino); pwarn("ZERO LENGTH DIRECTORY %s I=%d", dirname, dirp->d_ino); /* * We need to: * setcwd(idesc->id_parent); * rmdir(dirp->d_name); */ cmd.value = idesc->id_number; if (sysctlbyname("vfs.ffs.setcwd", 0, 0, &cmd, sizeof cmd) == -1) { /* kernel lacks support */ printf(" (IGNORED)\n"); n = 1; break; } if (rmdir(dirp->d_name) == -1) { printf(" (REMOVAL FAILED: %s)\n", strerror(errno)); n = 1; break; } /* ".." reference to parent is removed */ inoinfo(idesc->id_number)->ino_linkcnt--; printf(" (REMOVED)\n"); break; } fileerror(idesc->id_number, dirp->d_ino, errmsg); if ((n = reply("REMOVE")) == 1) break; dp = ginode(dirp->d_ino); inoinfo(dirp->d_ino)->ino_state = (DIP(dp, di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE; inoinfo(dirp->d_ino)->ino_linkcnt = DIP(dp, di_nlink); goto again; case DSTATE: case DZLINK: if (inoinfo(idesc->id_number)->ino_state == DFOUND) inoinfo(dirp->d_ino)->ino_state = DFOUND; /* FALLTHROUGH */ case DFOUND: inp = getinoinfo(dirp->d_ino); if (idesc->id_entryno > 2) { if (inp->i_parent == 0) inp->i_parent = idesc->id_number; else if ((n = fix_extraneous(inp, idesc)) == 1) break; } /* FALLTHROUGH */ case FSTATE: case FZLINK: if (dirp->d_type != inoinfo(dirp->d_ino)->ino_type) { fileerror(idesc->id_number, dirp->d_ino, "BAD TYPE VALUE"); dirp->d_type = inoinfo(dirp->d_ino)->ino_type; if (reply("FIX") == 1) ret |= ALTERED; } inoinfo(dirp->d_ino)->ino_linkcnt--; break; default: errx(EEXIT, "BAD STATE %d FOR INODE I=%d", inoinfo(dirp->d_ino)->ino_state, dirp->d_ino); } } if (n == 0) return (ret|KEEPON); dirp->d_ino = 0; return (ret|KEEPON|ALTERED); }
static bool vbr_fix(char *selected_file) { unsigned char xingbuf[1500]; struct mp3entry entry; int fd; int rc; int flen; int num_frames; int numbytes; int framelen; int unused_space; rb->lcd_clear_display(); rb->lcd_puts_scroll(0, 0, selected_file); #ifdef HAVE_LCD_BITMAP rb->lcd_update(); #endif xingupdate(0); rc = rb->mp3info(&entry, selected_file, false); if(rc < 0) { fileerror(rc); return true; } fd = rb->open(selected_file, O_RDWR); if(fd < 0) { fileerror(fd); return true; } flen = rb->lseek(fd, 0, SEEK_END); xingupdate(0); num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset, flen, xingupdate); if(num_frames) { /* Note: We don't need to pass a template header because it will be taken from the mpeg stream */ framelen = rb->create_xing_header(fd, entry.first_frame_offset, flen, xingbuf, num_frames, 0, 0, xingupdate, true); /* Try to fit the Xing header first in the stream. Replace the existing VBR header if there is one, else see if there is room between the ID3 tag and the first MP3 frame. */ if(entry.first_frame_offset - entry.id3v2len >= (unsigned int)framelen) { DEBUGF("Using existing space between ID3 and first frame\n"); /* Seek to the beginning of the unused space */ rc = rb->lseek(fd, entry.id3v2len, SEEK_SET); if(rc < 0) { rb->close(fd); fileerror(rc); return true; } unused_space = entry.first_frame_offset - entry.id3v2len - framelen; /* Fill the unused space with 0's (using the MP3 buffer) and write it to the file */ if(unused_space) { rb->memset(audiobuf, 0, unused_space); rc = rb->write(fd, audiobuf, unused_space); if(rc < 0) { rb->close(fd); fileerror(rc); return true; } } /* Then write the Xing header */ rc = rb->write(fd, xingbuf, framelen); if(rc < 0) { rb->close(fd); fileerror(rc); return true; } rb->close(fd); } else { /* If not, insert some space. If there is an ID3 tag in the file we only insert just enough to squeeze the Xing header in. If not, we insert an additional empty ID3 tag of 4K. */ rb->close(fd); /* Nasty trick alert! The insert_data_in_file() function uses the MP3 buffer when copying the data. We assume that the ID3 tag isn't longer than 1MB so the xing buffer won't be overwritten. */ if(entry.first_frame_offset) { DEBUGF("Inserting %d bytes\n", framelen); numbytes = framelen; } else { DEBUGF("Inserting 4096+%d bytes\n", framelen); numbytes = 4096 + framelen; rb->memset(audiobuf + 0x100000, 0, numbytes); /* Insert the ID3 header */ rb->memcpy(audiobuf + 0x100000, empty_id3_header, sizeof(empty_id3_header)); } /* Copy the Xing header */ rb->memcpy(audiobuf + 0x100000 + numbytes - framelen, xingbuf, framelen); rc = insert_data_in_file(selected_file, entry.first_frame_offset, audiobuf + 0x100000, numbytes); if(rc < 0) { fileerror(rc); return true; } } xingupdate(100); } else { /* Not a VBR file */ DEBUGF("Not a VBR file\n"); rb->splash(HZ*2, true, "Not a VBR file"); } return false; }
int toplevelstatement(stats_t *stats) /* * At the top level of a C file, the statements are blocks of * tokens ending in either ; or are function definitions which * end in }. Interesting types of statements include class * and struct definitions - because they may contain inline functions, * and function definitions. All others are merely counted. */ { int endofstatement = FALSE; int c; char buf[1024]; int functionFirstLine = -1; int functionFirstNLine = -1; int functionDefLine; int line, nLine; buf[0] = '\0'; c = skipws(); ncss_Ungetc(c); /* gettoken eats whitespace */ while (!endofstatement && (c = fancygettoken(buf, stats->type == STATS_CLASS, &line, &nLine)) != EOF) { if (functionFirstLine == -1) { functionFirstLine = line; functionFirstNLine = nLine; } switch (c) { case T_EXTERN: case T_CLASS: case T_STRUCT: case T_UNION: if (maybeclass()) { stats->nsemicolons--; endofstatement = TRUE; } break; case T_NAMESPACE: if (maybenamespace()) { /* no trailing semicolon for namespaces */ endofstatement = TRUE; } break; case '(': /* possible start of function */ functionDefLine = Line; possiblefn(stats, buf, functionFirstLine, functionDefLine, functionFirstNLine); endofstatement = TRUE; break; case '}': case ')': Exit = 2; { char _buf[100]; sprintf(_buf, "too many %c's", c); fileerror(_buf); } break; case '{': c = matchcurly(); break; case ':': /* This should catch C++ "class foo { public: } */ case ';': /* end of statement */ endofstatement = TRUE; break; case T_ENUM: c = fancygettoken(buf, stats->type == STATS_CLASS, &line, &nLine); if (c == T_CLASS || c == T_STRUCT) { endofstatement = TRUE; break; } else { ungettoken(c, buf); } break; default: break; } } return c; }
int maybeclass() /* * We've just seen "class" at the top level in a file so * we may be entering a definition of same. If so, we want to be * on the lookout for inline functions. Return 1 if this is a * class definition else restore the function name and return 0. */ { char classname[256], dummy[256]; int isclass = 0; int c; if ((c =gettoken(classname, NULL, NULL)) == T_IDENT) { /* "class name" */ switch(c = gettoken(dummy, NULL, NULL)) { case '{': /* "class name {" */ break; case ':': /* "class name :" */ c = gettoken(dummy, NULL, NULL); if (c == ':') { /* "class name :: */ /* this is a namespace-qualified declaration since cannot have a definition like this. */ break; } else { /* "clas name : [one or more initializers]" */ while (c != '{') { c = gettoken(dummy, NULL, NULL); } } break; default: /* if we fail to get "class name [:.*] {" */ ungettoken(c, dummy); } } else if (c == '{') /* Unnamed class */ { /* "class {" */ strcpy(classname, "unnamed"); } else { /* "class BOGUS" -- perhaps this is C code using a variable "class" */ ungettoken(c, dummy); } if (isclass = (c == '{')) { stats_t *class = stats_push(classname, STATS_CLASS); while ((c = gettoken(dummy, NULL, NULL)) != '}') { if (c == EOF) { fileerror("unexpected EOF"); break; } else ungettoken(c, dummy); toplevelstatement(class); } stats_pop(class); }
void pass2(void) { struct ufs1_dinode *dp; struct inoinfo **inpp, *inp; struct inoinfo **inpend; struct inodesc curino; struct ufs1_dinode dino; char pathbuf[MAXPATHLEN + 1]; long i, n; switch (inoinfo(ROOTINO)->ino_state) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) { ckfini(0); exit(EEXIT); } if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; } if (reply("CONTINUE") == 0) { ckfini(0); exit(EEXIT); } break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); break; } if (reply("FIX") == 0) { ckfini(0); exit(EEXIT); } dp = ginode(ROOTINO); dp->di_mode &= ~IFMT; dp->di_mode |= IFDIR; inodirty(); break; case DSTATE: break; default: errx(EEXIT, "BAD STATE %d FOR ROOT INODE", inoinfo(ROOTINO)->ino_state); } inoinfo(ROOTINO)->ino_state = DFOUND; if (newinofmt) { inoinfo(WINO)->ino_state = FSTATE; inoinfo(WINO)->ino_type = DT_WHT; } /* * Sort the directory list into disk block order. Do this in blocks * of 1000 directories in order to maintain locality of reference * in memory in case fsck is using swap space. */ for (i = 0; i < inplast; i += 1000) { if ((n = inplast - i) > 1000) n = 1000; qsort(inpsort + i, (size_t)n, sizeof *inpsort, blksort); } /* * Check the integrity of each directory. */ memset(&curino, 0, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; dp = &dino; inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { if (got_siginfo) { printf("%s: phase 2: dir %d of %ld (%d%%)\n", cdevname, inpp - inpsort, inplast, (int)((inpp - inpsort) * 100 / inplast)); got_siginfo = 0; } inp = *inpp; if (inp->i_isize == 0) continue; if (inp->i_isize < MINDIRSIZE) { direrror(inp->i_number, "DIRECTORY TOO SHORT"); inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); if (reply("FIX") == 1) { dp = ginode(inp->i_number); dp->di_size = inp->i_isize; inodirty(); dp = &dino; } } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { getpathname(pathbuf, inp->i_number, inp->i_number); if (usedsoftdep) pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, inp->i_isize, DIRBLKSIZ); else pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, inp->i_isize, DIRBLKSIZ); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); inodirty(); dp = &dino; } } memset(&dino, 0, sizeof(struct ufs1_dinode)); dino.di_mode = IFDIR; dp->di_size = inp->i_isize; memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks); curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; ckinode(dp, &curino); } /* * Now that the parents of all directories have been found, * make another pass to verify the value of `..' */ for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_isize == 0) continue; if (inoinfo(inp->i_parent)->ino_state == DFOUND && inoinfo(inp->i_number)->ino_state == DSTATE) inoinfo(inp->i_number)->ino_state = DFOUND; if (inp->i_dotdot == inp->i_parent || inp->i_dotdot == (ufs1_ino_t)-1) continue; if (inp->i_dotdot == 0) { inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); if (reply("FIX") == 0) continue; makeentry(inp->i_number, inp->i_parent, ".."); inoinfo(inp->i_parent)->ino_linkcnt--; continue; } fileerror(inp->i_parent, inp->i_number, "BAD INODE NUMBER FOR '..'"); if (reply("FIX") == 0) continue; inoinfo(inp->i_dotdot)->ino_linkcnt++; inoinfo(inp->i_parent)->ino_linkcnt--; inp->i_dotdot = inp->i_parent; changeino(inp->i_number, "..", inp->i_parent); } /* * Mark all the directories that can be found from the root. */ propagate(); }
/* * Scan each entry in a directory block. */ int dirscan(struct inodesc *idesc) { struct direct *dp; struct bufarea *bp; int dsize, n; long blksiz; #if DIRBLKSIZ > APPLEUFS_DIRBLKSIZ char dbuf[DIRBLKSIZ]; #else char dbuf[APPLEUFS_DIRBLKSIZ]; #endif if (idesc->id_type != DATA) errexit("wrong type to dirscan %d", idesc->id_type); if (idesc->id_entryno == 0 && (idesc->id_filesize & (dirblksiz - 1)) != 0) idesc->id_filesize = roundup(idesc->id_filesize, dirblksiz); blksiz = idesc->id_numfrags * sblock->fs_fsize; if (chkrange(idesc->id_blkno, idesc->id_numfrags)) { idesc->id_filesize -= blksiz; return (SKIP); } /* * If we are are swapping byte order in directory entries, just swap * this block and return. */ if (do_dirswap) { int off; bp = getdirblk(idesc->id_blkno, blksiz); for (off = 0; off < blksiz; off += iswap16(dp->d_reclen)) { dp = (struct direct *)(bp->b_un.b_buf + off); dp->d_ino = bswap32(dp->d_ino); dp->d_reclen = bswap16(dp->d_reclen); if (!newinofmt) { u_int8_t tmp = dp->d_namlen; dp->d_namlen = dp->d_type; dp->d_type = tmp; } if (dp->d_reclen == 0) break; } dirty(bp); idesc->id_filesize -= blksiz; return (idesc->id_filesize > 0 ? KEEPON : STOP); } idesc->id_loc = 0; for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { dsize = iswap16(dp->d_reclen); if (dsize > sizeof dbuf) dsize = sizeof dbuf; memmove(dbuf, dp, (size_t)dsize); # if (BYTE_ORDER == LITTLE_ENDIAN) if (!newinofmt && !needswap) { # else if (!newinofmt && needswap) { # endif struct direct *tdp = (struct direct *)dbuf; u_char tmp; tmp = tdp->d_namlen; tdp->d_namlen = tdp->d_type; tdp->d_type = tmp; } idesc->id_dirp = (struct direct *)dbuf; if ((n = (*idesc->id_func)(idesc)) & ALTERED) { # if (BYTE_ORDER == LITTLE_ENDIAN) if (!newinofmt && !doinglevel2 && !needswap) { # else if (!newinofmt && !doinglevel2 && needswap) { # endif struct direct *tdp; u_char tmp; tdp = (struct direct *)dbuf; tmp = tdp->d_namlen; tdp->d_namlen = tdp->d_type; tdp->d_type = tmp; } bp = getdirblk(idesc->id_blkno, blksiz); memmove(bp->b_un.b_buf + idesc->id_loc - dsize, dbuf, (size_t)dsize); dirty(bp); sbdirty(); } if (n & STOP) return (n); } return (idesc->id_filesize > 0 ? KEEPON : STOP); } /* * get next entry in a directory. */ static struct direct * fsck_readdir(struct inodesc *idesc) { struct direct *dp, *ndp; struct bufarea *bp; long size, blksiz, fix, dploc; blksiz = idesc->id_numfrags * sblock->fs_fsize; bp = getdirblk(idesc->id_blkno, blksiz); if (idesc->id_loc % dirblksiz == 0 && idesc->id_filesize > 0 && idesc->id_loc < blksiz) { dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); if (dircheck(idesc, dp)) goto dpok; if (idesc->id_fix == IGNORE) return (0); fix = dofix(idesc, "DIRECTORY CORRUPTED"); bp = getdirblk(idesc->id_blkno, blksiz); dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); dp->d_reclen = iswap16(dirblksiz); dp->d_ino = 0; dp->d_type = 0; dp->d_namlen = 0; dp->d_name[0] = '\0'; if (fix) dirty(bp); else markclean = 0; idesc->id_loc += dirblksiz; idesc->id_filesize -= dirblksiz; return (dp); } dpok: if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz) return NULL; dploc = idesc->id_loc; dp = (struct direct *)(bp->b_un.b_buf + dploc); idesc->id_loc += iswap16(dp->d_reclen); idesc->id_filesize -= iswap16(dp->d_reclen); if ((idesc->id_loc % dirblksiz) == 0) return (dp); ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc); if (idesc->id_loc < blksiz && idesc->id_filesize > 0 && dircheck(idesc, ndp) == 0) { size = dirblksiz - (idesc->id_loc % dirblksiz); idesc->id_loc += size; idesc->id_filesize -= size; if (idesc->id_fix == IGNORE) return (0); fix = dofix(idesc, "DIRECTORY CORRUPTED"); bp = getdirblk(idesc->id_blkno, blksiz); dp = (struct direct *)(bp->b_un.b_buf + dploc); dp->d_reclen = iswap16(iswap16(dp->d_reclen) + size); if (fix) dirty(bp); else markclean = 0; } return (dp); } /* * Verify that a directory entry is valid. * This is a superset of the checks made in the kernel. */ static int dircheck(struct inodesc *idesc, struct direct *dp) { int size; char *cp; u_char namlen, type; int spaceleft; spaceleft = dirblksiz - (idesc->id_loc % dirblksiz); if (iswap32(dp->d_ino) >= maxino || dp->d_reclen == 0 || iswap16(dp->d_reclen) > spaceleft || (iswap16(dp->d_reclen) & 0x3) != 0) return (0); if (dp->d_ino == 0) return (1); size = DIRSIZ(!newinofmt, dp, needswap); # if (BYTE_ORDER == LITTLE_ENDIAN) if (!newinofmt && !needswap) { # else if (!newinofmt && needswap) { # endif type = dp->d_namlen; namlen = dp->d_type; } else { namlen = dp->d_namlen; type = dp->d_type; } if (iswap16(dp->d_reclen) < size || idesc->id_filesize < size || /* namlen > MAXNAMLEN || */ type > 15) return (0); for (cp = dp->d_name, size = 0; size < namlen; size++) if (*cp == '\0' || (*cp++ == '/')) return (0); if (*cp != '\0') return (0); return (1); } void direrror(ino_t ino, const char *errmesg) { fileerror(ino, ino, errmesg); } void fileerror(ino_t cwd, ino_t ino, const char *errmesg) { union dinode *dp; char pathbuf[MAXPATHLEN + 1]; uint16_t mode; pwarn("%s ", errmesg); pinode(ino); printf("\n"); getpathname(pathbuf, sizeof(pathbuf), cwd, ino); if (ino < ROOTINO || ino > maxino) { pfatal("NAME=%s\n", pathbuf); return; } dp = ginode(ino); if (ftypeok(dp)) { mode = DIP(dp, mode); pfatal("%s=%s\n", (iswap16(mode) & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf); } else pfatal("NAME=%s\n", pathbuf); } void adjust(struct inodesc *idesc, int lcnt) { union dinode *dp; int16_t nlink; int saveresolved; dp = ginode(idesc->id_number); nlink = iswap16(DIP(dp, nlink)); if (nlink == lcnt) { /* * If we have not hit any unresolved problems, are running * in preen mode, and are on a file system using soft updates, * then just toss any partially allocated files. */ if (resolved && preen && usedsoftdep) { clri(idesc, "UNREF", 1); return; } else { /* * The file system can be marked clean even if * a file is not linked up, but is cleared. * Hence, resolved should not be cleared when * linkup is answered no, but clri is answered yes. */ saveresolved = resolved; if (linkup(idesc->id_number, (ino_t)0, NULL) == 0) { resolved = saveresolved; clri(idesc, "UNREF", 0); return; } /* * Account for the new reference created by linkup(). */ dp = ginode(idesc->id_number); lcnt--; } } if (lcnt != 0) { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : ((iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %d SHOULD BE %d", nlink, nlink - lcnt); if (preen || usedsoftdep) { if (lcnt < 0) { printf("\n"); pfatal("LINK COUNT INCREASING"); } if (preen) printf(" (ADJUSTED)\n"); } if (preen || reply("ADJUST") == 1) { DIP_SET(dp, nlink, iswap16(nlink - lcnt)); inodirty(); } else markclean = 0; } } static int mkentry(struct inodesc *idesc) { struct direct *dirp = idesc->id_dirp; struct direct newent; int newlen, oldlen; newent.d_namlen = strlen(idesc->id_name); newlen = DIRSIZ(0, &newent, 0); if (dirp->d_ino != 0) oldlen = DIRSIZ(0, dirp, 0); else oldlen = 0; if (iswap16(dirp->d_reclen) - oldlen < newlen) return (KEEPON); newent.d_reclen = iswap16(iswap16(dirp->d_reclen) - oldlen); dirp->d_reclen = iswap16(oldlen); dirp = (struct direct *)(((char *)dirp) + oldlen); /* ino to be entered is in id_parent */ dirp->d_ino = iswap32(idesc->id_parent); dirp->d_reclen = newent.d_reclen; if (newinofmt) dirp->d_type = inoinfo(idesc->id_parent)->ino_type; else dirp->d_type = 0; dirp->d_namlen = newent.d_namlen; memmove(dirp->d_name, idesc->id_name, (size_t)newent.d_namlen + 1); # if (BYTE_ORDER == LITTLE_ENDIAN) /* * If the entry was split, dirscan() will only reverse the byte * order of the original entry, and not the new one, before * writing it back out. So, we reverse the byte order here if * necessary. */ if (oldlen != 0 && !newinofmt && !doinglevel2 && !needswap) { # else if (oldlen != 0 && !newinofmt && !doinglevel2 && needswap) { # endif u_char tmp; tmp = dirp->d_namlen; dirp->d_namlen = dirp->d_type; dirp->d_type = tmp; } return (ALTERED|STOP); } static int chgino(struct inodesc *idesc) { struct direct *dirp = idesc->id_dirp; if (memcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1)) return (KEEPON); dirp->d_ino = iswap32(idesc->id_parent); if (newinofmt) dirp->d_type = inoinfo(idesc->id_parent)->ino_type; else dirp->d_type = 0; return (ALTERED|STOP); } int linkup(ino_t orphan, ino_t parentdir, char *name) { union dinode *dp; int lostdir; ino_t oldlfdir; struct inodesc idesc; char tempname[BUFSIZ]; int16_t nlink; uint16_t mode; memset(&idesc, 0, sizeof(struct inodesc)); dp = ginode(orphan); mode = iswap16(DIP(dp, mode)); nlink = iswap16(DIP(dp, nlink)); lostdir = (mode & IFMT) == IFDIR; pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); pinode(orphan); if (preen && DIP(dp, size) == 0) return (0); if (preen) printf(" (RECONNECTED)\n"); else if (reply("RECONNECT") == 0) { markclean = 0; return (0); } if (parentdir != 0) inoinfo(parentdir)->ino_linkcnt++; if (lfdir == 0) { dp = ginode(ROOTINO); idesc.id_name = lfname; idesc.id_type = DATA; idesc.id_func = findino; idesc.id_number = ROOTINO; if ((ckinode(dp, &idesc) & FOUND) != 0) { lfdir = idesc.id_parent; } else { pwarn("NO lost+found DIRECTORY"); if (preen || reply("CREATE")) { lfdir = allocdir(ROOTINO, (ino_t)0, lfmode); if (lfdir != 0) { if (makeentry(ROOTINO, lfdir, lfname) != 0) { numdirs++; if (preen) printf(" (CREATED)\n"); } else { freedir(lfdir, ROOTINO); lfdir = 0; if (preen) printf("\n"); } } if (lfdir != 0) { reparent(lfdir, ROOTINO); } } } if (lfdir == 0) { pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); markclean = 0; return (0); } } dp = ginode(lfdir); mode = DIP(dp, mode); mode = iswap16(mode); if ((mode & IFMT) != IFDIR) { pfatal("lost+found IS NOT A DIRECTORY"); if (reply("REALLOCATE") == 0) { markclean = 0; return (0); } oldlfdir = lfdir; lfdir = allocdir(ROOTINO, (ino_t)0, lfmode); if (lfdir == 0) { pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); markclean = 0; return (0); } if ((changeino(ROOTINO, lfname, lfdir) & ALTERED) == 0) { pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); markclean = 0; return (0); } inodirty(); reparent(lfdir, ROOTINO); idesc.id_type = ADDR; idesc.id_func = pass4check; idesc.id_number = oldlfdir; adjust(&idesc, inoinfo(oldlfdir)->ino_linkcnt + 1); inoinfo(oldlfdir)->ino_linkcnt = 0; dp = ginode(lfdir); } if (inoinfo(lfdir)->ino_state != DFOUND) { pfatal("SORRY. NO lost+found DIRECTORY\n\n"); markclean = 0; return (0); } (void)lftempname(tempname, orphan); if (makeentry(lfdir, orphan, (name ? name : tempname)) == 0) { pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); printf("\n\n"); markclean = 0; return (0); } inoinfo(orphan)->ino_linkcnt--; if (lostdir) { if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 && parentdir != (ino_t)-1) (void)makeentry(orphan, lfdir, ".."); dp = ginode(lfdir); nlink = DIP(dp, nlink); DIP_SET(dp, nlink, iswap16(iswap16(nlink) + 1)); inodirty(); inoinfo(lfdir)->ino_linkcnt++; reparent(orphan, lfdir); pwarn("DIR I=%llu CONNECTED. ", (unsigned long long)orphan); if (parentdir != (ino_t)-1) printf("PARENT WAS I=%llu\n", (unsigned long long)parentdir); if (preen == 0) printf("\n"); } return (1); } /* * fix an entry in a directory. */ int changeino(ino_t dir, const char *name, ino_t newnum) { struct inodesc idesc; memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = chgino; idesc.id_number = dir; idesc.id_fix = DONTKNOW; idesc.id_name = name; idesc.id_parent = newnum; /* new value for name */ return (ckinode(ginode(dir), &idesc)); } /* * make an entry in a directory */ int makeentry(ino_t parent, ino_t ino, const char *name) { union dinode *dp; struct inodesc idesc; char pathbuf[MAXPATHLEN + 1]; if (parent < ROOTINO || parent >= maxino || ino < ROOTINO || ino >= maxino) return (0); memset(&idesc, 0, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = mkentry; idesc.id_number = parent; idesc.id_parent = ino; /* this is the inode to enter */ idesc.id_fix = DONTKNOW; idesc.id_name = name; dp = ginode(parent); if (iswap64(DIP(dp, size)) % dirblksiz) { DIP_SET(dp, size, iswap64(roundup(iswap64(DIP(dp, size)), dirblksiz))); inodirty(); } if ((ckinode(dp, &idesc) & ALTERED) != 0) return (1); getpathname(pathbuf, sizeof(pathbuf), parent, parent); dp = ginode(parent); if (expanddir(dp, pathbuf) == 0) return (0); return (ckinode(dp, &idesc) & ALTERED); } /* * Attempt to expand the size of a directory */ static int expanddir(union dinode *dp, char *name) { daddr_t lastbn, newblk, dirblk; struct bufarea *bp; char *cp; #if DIRBLKSIZ > APPLEUFS_DIRBLKSIZ char firstblk[DIRBLKSIZ]; #else char firstblk[APPLEUFS_DIRBLKSIZ]; #endif struct ufs1_dinode *dp1 = NULL; struct ufs2_dinode *dp2 = NULL; if (is_ufs2) dp2 = &dp->dp2; else dp1 = &dp->dp1; lastbn = lblkno(sblock, iswap64(DIP(dp, size))); if (lastbn >= NDADDR - 1 || DIP(dp, db[lastbn]) == 0 || DIP(dp, size) == 0) return (0); if ((newblk = allocblk(sblock->fs_frag)) == 0) return (0); if (is_ufs2) { dp2->di_db[lastbn + 1] = dp2->di_db[lastbn]; dp2->di_db[lastbn] = iswap64(newblk); dp2->di_size = iswap64(iswap64(dp2->di_size)+sblock->fs_bsize); dp2->di_blocks = iswap64(iswap64(dp2->di_blocks) + btodb(sblock->fs_bsize)); dirblk = iswap64(dp2->di_db[lastbn + 1]); } else { dp1->di_db[lastbn + 1] = dp1->di_db[lastbn]; dp1->di_db[lastbn] = iswap32((int32_t)newblk); dp1->di_size = iswap64(iswap64(dp1->di_size)+sblock->fs_bsize); dp1->di_blocks = iswap32(iswap32(dp1->di_blocks) + btodb(sblock->fs_bsize)); dirblk = iswap32(dp1->di_db[lastbn + 1]); } bp = getdirblk(dirblk, sblksize(sblock, DIP(dp, size), lastbn + 1)); if (bp->b_errs) goto bad; memmove(firstblk, bp->b_un.b_buf, dirblksiz); bp = getdirblk(newblk, sblock->fs_bsize); if (bp->b_errs) goto bad; memmove(bp->b_un.b_buf, firstblk, dirblksiz); emptydir.dot_reclen = iswap16(dirblksiz); for (cp = &bp->b_un.b_buf[dirblksiz]; cp < &bp->b_un.b_buf[sblock->fs_bsize]; cp += dirblksiz) memmove(cp, &emptydir, sizeof emptydir); dirty(bp); bp = getdirblk(dirblk, sblksize(sblock, DIP(dp, size), lastbn + 1)); if (bp->b_errs) goto bad; memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir); pwarn("NO SPACE LEFT IN %s", name); if (preen) printf(" (EXPANDED)\n"); else if (reply("EXPAND") == 0) goto bad; dirty(bp); inodirty(); return (1); bad: if (is_ufs2) { dp2->di_db[lastbn] = dp2->di_db[lastbn + 1]; dp2->di_db[lastbn + 1] = 0; dp2->di_size = iswap64(iswap64(dp2->di_size)-sblock->fs_bsize); dp2->di_blocks = iswap64(iswap64(dp2->di_blocks) - btodb(sblock->fs_bsize)); } else { dp1->di_db[lastbn] = dp1->di_db[lastbn + 1]; dp1->di_db[lastbn + 1] = 0; dp1->di_size = iswap64(iswap64(dp1->di_size)-sblock->fs_bsize); dp1->di_blocks = iswap32(iswap32(dp1->di_blocks) - btodb(sblock->fs_bsize)); } freeblk(newblk, sblock->fs_frag); markclean = 0; return (0); } /* * allocate a new directory */ ino_t allocdir(ino_t parent, ino_t request, int mode) { ino_t ino; char *cp; union dinode *dp; struct bufarea *bp; struct inoinfo *inp; struct dirtemplate *dirp; daddr_t dirblk; ino = allocino(request, IFDIR|mode); if (ino < ROOTINO) return 0; dirhead.dot_reclen = iswap16(12); dirhead.dotdot_reclen = iswap16(dirblksiz - 12); odirhead.dot_reclen = iswap16(12); odirhead.dotdot_reclen = iswap16(dirblksiz - 12); odirhead.dot_namlen = iswap16(1); odirhead.dotdot_namlen = iswap16(2); if (newinofmt) dirp = &dirhead; else dirp = (struct dirtemplate *)&odirhead; dirp->dot_ino = iswap32(ino); dirp->dotdot_ino = iswap32(parent); dp = ginode(ino); dirblk = is_ufs2 ? iswap64(dp->dp2.di_db[0]) : iswap32(dp->dp1.di_db[0]); bp = getdirblk(dirblk, sblock->fs_fsize); if (bp->b_errs) { freeino(ino); return (0); } memmove(bp->b_un.b_buf, dirp, sizeof(struct dirtemplate)); emptydir.dot_reclen = iswap16(dirblksiz); for (cp = &bp->b_un.b_buf[dirblksiz]; cp < &bp->b_un.b_buf[sblock->fs_fsize]; cp += dirblksiz) memmove(cp, &emptydir, sizeof emptydir); dirty(bp); DIP_SET(dp, nlink, iswap16(2)); inodirty(); if (ino == ROOTINO) { inoinfo(ino)->ino_linkcnt = iswap16(DIP(dp, nlink)); cacheino(dp, ino); return(ino); } if (inoinfo(parent)->ino_state != DSTATE && inoinfo(parent)->ino_state != DFOUND) { freeino(ino); return (0); } cacheino(dp, ino); inp = getinoinfo(ino); inp->i_parent = parent; inp->i_dotdot = parent; inoinfo(ino)->ino_state = inoinfo(parent)->ino_state; if (inoinfo(ino)->ino_state == DSTATE) { inoinfo(ino)->ino_linkcnt = iswap16(DIP(dp, nlink)); inoinfo(parent)->ino_linkcnt++; } dp = ginode(parent); DIP_SET(dp, nlink, iswap16(iswap16(DIP(dp, nlink)) + 1)); inodirty(); return (ino); }
void pass2(void) { struct ext2fs_dinode *dp; struct inoinfo **inpp, *inp; struct inoinfo **inpend; struct inodesc curino; struct ext2fs_dinode dino; char pathbuf[MAXPATHLEN + 1]; switch (statemap[EXT2_ROOTINO]) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) errexit("%s\n", ""); if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(EXT2_ROOTINO); if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; } if (reply("CONTINUE") == 0) errexit("%s\n", ""); break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(EXT2_ROOTINO); if (allocdir(EXT2_ROOTINO, EXT2_ROOTINO, 0755) != EXT2_ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; } if (reply("FIX") == 0) errexit("%s\n", ""); dp = ginode(EXT2_ROOTINO); dp->e2di_mode = htole16((letoh16(dp->e2di_mode) & ~IFMT) | IFDIR); inodirty(); break; case DSTATE: break; default: errexit("BAD STATE %d FOR ROOT INODE\n", statemap[EXT2_ROOTINO]); } /* * Sort the directory list into disk block order. */ qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); /* * Check the integrity of each directory. */ memset(&curino, 0, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_isize == 0) continue; if (inp->i_isize < MINDIRSIZE) { direrror(inp->i_number, "DIRECTORY TOO SHORT"); inp->i_isize = roundup(MINDIRSIZE, sblock.e2fs_bsize); if (reply("FIX") == 1) { dp = ginode(inp->i_number); inossize(dp, inp->i_isize); inodirty(); } } else if ((inp->i_isize & (sblock.e2fs_bsize - 1)) != 0) { getpathname(pathbuf, sizeof pathbuf, inp->i_number, inp->i_number); pwarn("DIRECTORY %s: LENGTH %lu NOT MULTIPLE OF %d", pathbuf, (u_long)inp->i_isize, sblock.e2fs_bsize); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, sblock.e2fs_bsize); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); inossize(dp, inp->i_isize); inodirty(); } } memset(&dino, 0, sizeof(struct ext2fs_dinode)); dino.e2di_mode = htole16(IFDIR); inossize(&dino, inp->i_isize); memcpy(&dino.e2di_blocks[0], &inp->i_blks[0], (size_t)inp->i_numblks); curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(&dino, &curino); } /* * Now that the parents of all directories have been found, * make another pass to verify the value of `..' */ for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_isize == 0) continue; if (inp->i_dotdot == inp->i_parent || inp->i_dotdot == (ino_t)-1) continue; if (inp->i_dotdot == 0) { inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); if (reply("FIX") == 0) continue; (void)makeentry(inp->i_number, inp->i_parent, ".."); lncntp[inp->i_parent]--; continue; } fileerror(inp->i_parent, inp->i_number, "BAD INODE NUMBER FOR '..'"); if (reply("FIX") == 0) continue; lncntp[inp->i_dotdot]++; lncntp[inp->i_parent]--; inp->i_dotdot = inp->i_parent; (void)changeino(inp->i_number, "..", inp->i_parent); } /* * Mark all the directories that can be found from the root. */ propagate(); }
static int pass2check(struct inodesc *idesc) { struct ext2fs_direct *dirp = idesc->id_dirp; struct inoinfo *inp; int n, entrysize, ret = 0; struct ext2fs_dinode *dp; char *errmsg; struct ext2fs_direct proto; char namebuf[MAXPATHLEN + 1]; char pathbuf[MAXPATHLEN + 1]; /* * check for "." */ if (idesc->id_entryno != 0) goto chk1; if (letoh32(dirp->e2d_ino) != 0 && dirp->e2d_namlen == 1 && dirp->e2d_name[0] == '.') { if (letoh32(dirp->e2d_ino) != idesc->id_number) { direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); dirp->e2d_ino = htole32(idesc->id_number); if (reply("FIX") == 1) ret |= ALTERED; } if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) && (dirp->e2d_type != EXT2_FT_DIR)) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); dirp->e2d_type = EXT2_FT_DIR; if (reply("FIX") == 1) ret |= ALTERED; } goto chk1; } direrror(idesc->id_number, "MISSING '.'"); proto.e2d_ino = htole32(idesc->id_number); proto.e2d_namlen = 1; if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) proto.e2d_type = EXT2_FT_DIR; else proto.e2d_type = 0; (void)strlcpy(proto.e2d_name, ".", sizeof proto.e2d_name); entrysize = EXT2FS_DIRSIZ(proto.e2d_namlen); if (letoh32(dirp->e2d_ino) != 0 && strcmp(dirp->e2d_name, "..") != 0) { pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", dirp->e2d_name); } else if (letoh16(dirp->e2d_reclen) < entrysize) { pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); } else if (letoh16(dirp->e2d_reclen) < 2 * entrysize) { proto.e2d_reclen = dirp->e2d_reclen; memcpy(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; } else { n = letoh16(dirp->e2d_reclen) - entrysize; proto.e2d_reclen = htole16(entrysize); memcpy(dirp, &proto, (size_t)entrysize); idesc->id_entryno++; lncntp[letoh32(dirp->e2d_ino)]--; dirp = (struct ext2fs_direct *)((char *)(dirp) + entrysize); memset(dirp, 0, (size_t)n); dirp->e2d_reclen = htole16(n); if (reply("FIX") == 1) ret |= ALTERED; } chk1: if (idesc->id_entryno > 1) goto chk2; inp = getinoinfo(idesc->id_number); proto.e2d_ino = htole32(inp->i_parent); proto.e2d_namlen = 2; if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE)) proto.e2d_type = EXT2_FT_DIR; else proto.e2d_type = 0; (void)strlcpy(proto.e2d_name, "..", sizeof proto.e2d_name); entrysize = EXT2FS_DIRSIZ(2); if (idesc->id_entryno == 0) { n = EXT2FS_DIRSIZ(dirp->e2d_namlen); if (letoh16(dirp->e2d_reclen) < n + entrysize) goto chk2; proto.e2d_reclen = htole16(letoh16(dirp->e2d_reclen) - n); dirp->e2d_reclen = htole16(n); idesc->id_entryno++; lncntp[letoh32(dirp->e2d_ino)]--; dirp = (struct ext2fs_direct *)((char *)(dirp) + n); memset(dirp, 0, (size_t)letoh16(proto.e2d_reclen)); dirp->e2d_reclen = proto.e2d_reclen; } if (letoh32(dirp->e2d_ino) != 0 && dirp->e2d_namlen == 2 && strncmp(dirp->e2d_name, "..", 2) == 0) { inp->i_dotdot = letoh32(dirp->e2d_ino); if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) && dirp->e2d_type != EXT2_FT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); dirp->e2d_type = EXT2_FT_DIR; if (reply("FIX") == 1) ret |= ALTERED; } goto chk2; } if (letoh32(dirp->e2d_ino) != 0 && dirp->e2d_namlen == 1 && strncmp(dirp->e2d_name, ".", 1) != 0) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", dirp->e2d_name); inp->i_dotdot = (ino_t)-1; } else if (letoh16(dirp->e2d_reclen) < entrysize) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); inp->i_dotdot = (ino_t)-1; } else if (inp->i_parent != 0) { /* * We know the parent, so fix now. */ inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); proto.e2d_reclen = dirp->e2d_reclen; memcpy(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; } idesc->id_entryno++; if (letoh32(dirp->e2d_ino) != 0) lncntp[letoh32(dirp->e2d_ino)]--; return (ret|KEEPON); chk2: if (letoh32(dirp->e2d_ino) == 0) return (ret|KEEPON); if (dirp->e2d_namlen <= 2 && dirp->e2d_name[0] == '.' && idesc->id_entryno >= 2) { if (dirp->e2d_namlen == 1) { direrror(idesc->id_number, "EXTRA '.' ENTRY"); dirp->e2d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } if (dirp->e2d_name[1] == '.') { direrror(idesc->id_number, "EXTRA '..' ENTRY"); dirp->e2d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } } idesc->id_entryno++; n = 0; if (letoh32(dirp->e2d_ino) > maxino || (letoh32(dirp->e2d_ino) < EXT2_FIRSTINO && letoh32(dirp->e2d_ino) != EXT2_ROOTINO)) { fileerror(idesc->id_number, letoh32(dirp->e2d_ino), "I OUT OF RANGE"); n = reply("REMOVE"); } else { again: switch (statemap[letoh32(dirp->e2d_ino)]) { case USTATE: if (idesc->id_entryno <= 2) break; fileerror(idesc->id_number, letoh32(dirp->e2d_ino), "UNALLOCATED"); n = reply("REMOVE"); break; case DCLEAR: case FCLEAR: if (idesc->id_entryno <= 2) break; if (statemap[letoh32(dirp->e2d_ino)] == FCLEAR) errmsg = "DUP/BAD"; else if (!preen) errmsg = "ZERO LENGTH DIRECTORY"; else { n = 1; break; } fileerror(idesc->id_number, letoh32(dirp->e2d_ino), errmsg); if ((n = reply("REMOVE")) == 1) break; dp = ginode(letoh32(dirp->e2d_ino)); statemap[letoh32(dirp->e2d_ino)] = (letoh16(dp->e2di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE; lncntp[letoh32(dirp->e2d_ino)] = letoh16(dp->e2di_nlink); goto again; case DSTATE: case DFOUND: inp = getinoinfo(letoh32(dirp->e2d_ino)); if (inp->i_parent != 0 && idesc->id_entryno > 2) { getpathname(pathbuf, sizeof pathbuf, idesc->id_number, idesc->id_number); getpathname(namebuf, sizeof namebuf, letoh32(dirp->e2d_ino), letoh32(dirp->e2d_ino)); pwarn("%s %s %s\n", pathbuf, "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", namebuf); if (preen) printf(" (IGNORED)\n"); else if ((n = reply("REMOVE")) == 1) break; } if (idesc->id_entryno > 2) inp->i_parent = idesc->id_number; /* fall through */ case FSTATE: if (sblock.e2fs.e2fs_rev > E2FS_REV0 && (sblock.e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_FTYPE) && dirp->e2d_type != inot2ext2dt(typemap[letoh32(dirp->e2d_ino)])) { dirp->e2d_type = inot2ext2dt(typemap[letoh32(dirp->e2d_ino)]); fileerror(idesc->id_number, letoh32(dirp->e2d_ino), "BAD TYPE VALUE"); if (reply("FIX") == 1) ret |= ALTERED; } lncntp[letoh32(dirp->e2d_ino)]--; break; default: errexit("BAD STATE %d FOR INODE I=%llu\n", statemap[letoh32(dirp->e2d_ino)], (unsigned long long)letoh32(dirp->e2d_ino)); } } if (n == 0) return (ret|KEEPON); dirp->e2d_ino = 0; return (ret|KEEPON|ALTERED); }
void direrror(ufs1_ino_t ino, char *errmesg) { fileerror(ino, ino, errmesg); }
int main(int eargc, char **eargv) { char fname[255]; char *test; char tdfname[255]; char *tok; char hopt[255]; char hargs[255]; // stupid default values longbase=100.0; latbase=10.0; range=20; // Lets do ARGS argc=eargc; argv=eargv; totalitems=0; totalcoords=0; skippeditems=0; if (argc<2 || Check_Param("-h") || Check_Param("-?")) { showhelp(); exit(0); } if (Check_Param("-f")) fileoutput=1; if (fileoutput) { printf("Polygon E00 to Falcon4 features converter v0.1\n"); printf("(C)opyright 2000 PMC TFW <*****@*****.**>\n"); printf("http://tactical.nekromantix.com\n"); printf("--------------------------------------------------\n"); } test=Get_Next_Option(); while (test) { if (strchr(test,'=')) { // fixme: "Do not never ever use strtok" :-) rmallws(test); tok=strtok(test,"="); if(!tok) continue; strncpy(hopt,tok,254); tok=strtok(NULL,"="); if (!tok) continue; strncpy(hargs,tok,254); if (strncmp(hopt,"-range",6)==0) range=atoi(hargs); else if (strncmp(test,"-long",5)==0) longbase=atol(hargs); else if (strncmp(test,"-lat",4)==0) latbase=atol(hargs); } test=Get_Next_Option(); } test=NULL; // first we try to get TYPE test=Get_Next_Name(); if(!test) exit(1); // erm, not found strncpy(type,test,254); // then we hope for source filename test=Get_Next_Name(); if(!test) exit(1); // not found.. strncpy(fname,test,254); // and from the remaing crap, if there is any, we create output filename // (to be used, when fileoutput=1) test=Get_Next_Name(); while(test) { strncpy(tdfname,test,254); test=Get_Next_Name(); } if (!tdfname) { stripext(fname,test); sprintf(tdfname,"%s.tdf",test); } if (fileoutput) printf("Reading E00 data from: %s\n",fname); if(fileoutput) { tdffile=fopen(tdfname,"wt"); if(!tdffile) fileerror("Error creating tdf..."); printf("Writing TDF data to: %s\n",tdfname); } readstuffs(fname); if (tdffile) fclose(tdffile); if (fileoutput) { printf("\nTotal %ld items %ld coordinates\n",totalitems,totalcoords); printf("Processing completed\n\n"); } return 0; }
int main(int argc, char *argv[]) { char *av0; register i; av0=argv[0]; fprintf(stderr,title); for ( i = 1; i < argc; i++ ) { if ( *argv[i] == '-' ) { switch ( *++argv[i] ) { #ifdef MC6809 case 'O': if ( (shortform = (int *)malloc(sizeof(int)*MAXOPTIM)) == NULL ) { fprintf(stderr,"no core for optimization\n"); break; } optimize++; break; #endif case 'd': debug++; break; case 'l': list++; if ( !argv[i+1] || *argv[i+1] == '-' ) continue; if ( *argv[++i] ) strcpy(lstfile,argv[i]); break; case 'o': object++; if ( !argv[i+1] || *argv[i+1] == '-' ) continue; if ( *argv[++i] ) strcpy(objfile,argv[i]); break; case 's': symbol++; break; case 'v': verbos++; break; case 'x': xref++; break; #ifndef MC6809 case 'X': mc6801++; break; #endif case 0: break; default: fprintf(stderr,"%s: illegal option -%c\n",av0,*argv[i]); exit(1); } } else strcpy(srcfile,argv[i]); } if ( !*srcfile ) { #ifdef MC6809 fprintf(stderr,"usage: %s src_file [-O] [-v] [-s] [-o [obj_file]] [-l [lst_file]]\n",av0); #else fprintf(stderr,"usage: %s src_file [-X] [-v] [-s] [-o [obj_file]] [-l [lst_file]]\n",av0); #endif exit(1); } if ( !*objfile ) { strcpy(objfile,srcfile); strcat(objfile,".o"); } if ( !*lstfile ) { strcpy(lstfile,srcfile); strcat(lstfile,".l"); } initialize(); pass = 1; DEBUG(fprintf(stderr,"enter pass 1\n")) DEBUG(fprintf(stderr,"open %s\n",srcfile)) if ( (srcf = fopen(srcfile,"r")) == NULL ) fileerror(srcfile); if ( verbos ) fprintf(stderr,"%s:\n",srcfile); assemble(); if ( optimize ) { pass = -1; DEBUG(fprintf(stderr,"enter pass 1.5\n")) DEBUG(fprintf(stderr,"open %s\n",srcfile)) do { if ( (srcf = fopen(srcfile,"r")) == NULL ) fileerror(srcfile); if ( verbos ) fprintf(stderr,"%s:\n",srcfile); assemble(); } while ( nchange ); } pass = 2; DEBUG(fprintf(stderr,"enter pass 2\n")) DEBUG(fprintf(stderr,"open %s\n",srcfile)) if ( (srcf = fopen(srcfile,"r")) == NULL ) fileerror(srcfile); if ( verbos ) fprintf(stderr,"%s:\n",srcfile); DEBUG(fprintf(stderr,"open %s\n",lstfile)) if ( list || symbol ) if ( (lstf = fopen(lstfile,"w")) == NULL ) fileerror(lstfile); DEBUG(fprintf(stderr,"open %s\n",objfile)) if ( object ) if ( (objf = fopen(objfile,"w")) == NULL ) fileerror(objfile); assemble(); DEBUG(fprintf(stderr,"close all files\n")) if ( object ) fclose(objf); if ( list || symbol ) fclose(lstf); exit(0); }
static int pass2check(struct inodesc *idesc) { struct direct *dirp = idesc->id_dirp; struct inoinfo *inp; struct inostat *info; int n, entrysize, ret = 0; union dinode *dp; const char *errmsg; struct direct proto; char namebuf[MAXPATHLEN + 1]; char pathbuf[MAXPATHLEN + 1]; /* * If converting, set directory entry type. */ if (!is_ufs2 && doinglevel2 && iswap32(dirp->d_ino) > 0 && iswap32(dirp->d_ino) < maxino) { dirp->d_type = inoinfo(iswap32(dirp->d_ino))->ino_type; ret |= ALTERED; } /* * check for "." */ if (idesc->id_entryno != 0) goto chk1; if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { if (iswap32(dirp->d_ino) != idesc->id_number) { direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); dirp->d_ino = iswap32(idesc->id_number); if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } if (newinofmt && dirp->d_type != DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); dirp->d_type = DT_DIR; if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } goto chk1; } direrror(idesc->id_number, "MISSING '.'"); proto.d_ino = iswap32(idesc->id_number); if (newinofmt) proto.d_type = DT_DIR; else proto.d_type = 0; proto.d_namlen = 1; (void)strlcpy(proto.d_name, ".", sizeof(proto.d_name)); # if BYTE_ORDER == LITTLE_ENDIAN if (!newinofmt && !needswap) { # else if (!newinofmt && needswap) { # endif u_char tmp; tmp = proto.d_type; proto.d_type = proto.d_namlen; proto.d_namlen = tmp; } entrysize = DIRSIZ(0, &proto, 0); if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); markclean = 0; } else if (iswap16(dirp->d_reclen) < entrysize) { pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); markclean = 0; } else if (iswap16(dirp->d_reclen) < 2 * entrysize) { proto.d_reclen = dirp->d_reclen; memmove(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } else { n = iswap16(dirp->d_reclen) - entrysize; proto.d_reclen = iswap16(entrysize); memmove(dirp, &proto, (size_t)entrysize); idesc->id_entryno++; inoinfo(iswap32(dirp->d_ino))->ino_linkcnt--; dirp = (struct direct *)((char *)(dirp) + entrysize); memset(dirp, 0, (size_t)n); dirp->d_reclen = iswap16(n); if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } chk1: if (idesc->id_entryno > 1) goto chk2; inp = getinoinfo(idesc->id_number); proto.d_ino = iswap32(inp->i_parent); if (newinofmt) proto.d_type = DT_DIR; else proto.d_type = 0; proto.d_namlen = 2; (void)strlcpy(proto.d_name, "..", sizeof(proto.d_name)); #if BYTE_ORDER == LITTLE_ENDIAN if (!newinofmt && !needswap) { #else if (!newinofmt && needswap) { #endif u_char tmp; tmp = proto.d_type; proto.d_type = proto.d_namlen; proto.d_namlen = tmp; } entrysize = DIRSIZ(0, &proto, 0); if (idesc->id_entryno == 0) { n = DIRSIZ(0, dirp, 0); if (iswap16(dirp->d_reclen) < n + entrysize) goto chk2; proto.d_reclen = iswap16(iswap16(dirp->d_reclen) - n); dirp->d_reclen = iswap16(n); idesc->id_entryno++; inoinfo(iswap32(dirp->d_ino))->ino_linkcnt--; dirp = (struct direct *)((char *)(dirp) + n); memset(dirp, 0, (size_t)iswap16(proto.d_reclen)); dirp->d_reclen = proto.d_reclen; } if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { inp->i_dotdot = iswap32(dirp->d_ino); if (newinofmt && dirp->d_type != DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); dirp->d_type = DT_DIR; if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } goto chk2; } if (iswap32(dirp->d_ino) != 0 && strcmp(dirp->d_name, ".") != 0) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); inp->i_dotdot = (ino_t)-1; markclean = 0; } else if (iswap16(dirp->d_reclen) < entrysize) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); inp->i_dotdot = (ino_t)-1; markclean = 0; } else if (inp->i_parent != 0) { /* * We know the parent, so fix now. */ inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); proto.d_reclen = dirp->d_reclen; memmove(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } idesc->id_entryno++; if (dirp->d_ino != 0) inoinfo(iswap32(dirp->d_ino))->ino_linkcnt--; return (ret|KEEPON); chk2: if (dirp->d_ino == 0) return (ret|KEEPON); if (dirp->d_namlen <= 2 && dirp->d_name[0] == '.' && idesc->id_entryno >= 2) { if (dirp->d_namlen == 1) { direrror(idesc->id_number, "EXTRA '.' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; return (KEEPON | ret); } if (dirp->d_name[1] == '.') { direrror(idesc->id_number, "EXTRA '..' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; return (KEEPON | ret); } } idesc->id_entryno++; n = 0; if (iswap32(dirp->d_ino) > maxino) { fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); n = reply("REMOVE"); if (n == 0) markclean = 0; } else if (newinofmt && ((iswap32(dirp->d_ino) == WINO && dirp->d_type != DT_WHT) || (iswap32(dirp->d_ino) != WINO && dirp->d_type == DT_WHT))) { fileerror(idesc->id_number, iswap32(dirp->d_ino), "BAD WHITEOUT ENTRY"); dirp->d_ino = iswap32(WINO); dirp->d_type = DT_WHT; if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } else { again: info = inoinfo(iswap32(dirp->d_ino)); switch (info->ino_state) { case USTATE: if (idesc->id_entryno <= 2) break; fileerror(idesc->id_number, iswap32(dirp->d_ino), "UNALLOCATED"); n = reply("REMOVE"); if (n == 0) markclean = 0; break; case DCLEAR: case FCLEAR: if (idesc->id_entryno <= 2) break; if (info->ino_state == FCLEAR) errmsg = "DUP/BAD"; else if (!preen && !usedsoftdep) errmsg = "ZERO LENGTH DIRECTORY"; else { n = 1; break; } fileerror(idesc->id_number, iswap32(dirp->d_ino), errmsg); if ((n = reply("REMOVE")) == 1) break; dp = ginode(iswap32(dirp->d_ino)); info->ino_state = (iswap16(DIP(dp, mode)) & IFMT) == IFDIR ? DSTATE : FSTATE; info->ino_linkcnt = iswap16(DIP(dp, nlink)); goto again; case DSTATE: case DFOUND: inp = getinoinfo(iswap32(dirp->d_ino)); if (inp->i_parent != 0 && idesc->id_entryno > 2) { getpathname(pathbuf, sizeof(pathbuf), idesc->id_number, idesc->id_number); getpathname(namebuf, sizeof(namebuf), iswap32(dirp->d_ino), iswap32(dirp->d_ino)); pwarn("%s %s %s\n", pathbuf, "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", namebuf); if (preen) printf(" (IGNORED)\n"); else if ((n = reply("REMOVE")) == 1) break; } if (idesc->id_entryno > 2) inp->i_parent = idesc->id_number; /* fall through */ case FSTATE: if (newinofmt && dirp->d_type != info->ino_type) { fileerror(idesc->id_number, iswap32(dirp->d_ino), "BAD TYPE VALUE"); dirp->d_type = info->ino_type; if (reply("FIX") == 1) ret |= ALTERED; else markclean = 0; } info->ino_linkcnt--; break; default: errexit("BAD STATE %d FOR INODE I=%d", info->ino_state, iswap32(dirp->d_ino)); } } if (n == 0) return (ret|KEEPON); dirp->d_ino = 0; return (ret|KEEPON|ALTERED); } /* * Routine to sort disk blocks. */ static int blksort(const void *arg1, const void *arg2) { return ((*(const struct inoinfo *const *)arg1)->i_blks[0] - (*(const struct inoinfo *const *)arg2)->i_blks[0]); }
static int pass2check(struct inodesc *idesc) { struct direct *dirp = idesc->id_dirp; struct inoinfo *inp; int n, entrysize, ret = 0; union dinode *dp; char *errmsg; struct direct proto; char namebuf[MAXPATHLEN + 1]; char pathbuf[MAXPATHLEN + 1]; /* * If converting, set directory entry type. */ if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) { dirp->d_type = GET_ITYPE(dirp->d_ino); ret |= ALTERED; } /* * check for "." */ if (idesc->id_entryno != 0) goto chk1; if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { if (dirp->d_ino != idesc->id_number) { direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); dirp->d_ino = idesc->id_number; if (reply("FIX") == 1) ret |= ALTERED; } if (newinofmt && dirp->d_type != DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); dirp->d_type = DT_DIR; if (reply("FIX") == 1) ret |= ALTERED; } goto chk1; } direrror(idesc->id_number, "MISSING '.'"); proto.d_ino = idesc->id_number; if (newinofmt) proto.d_type = DT_DIR; else proto.d_type = 0; proto.d_namlen = 1; (void)strlcpy(proto.d_name, ".", sizeof proto.d_name); # if BYTE_ORDER == LITTLE_ENDIAN if (!newinofmt) { u_char tmp; tmp = proto.d_type; proto.d_type = proto.d_namlen; proto.d_namlen = tmp; } # endif entrysize = DIRSIZ(0, &proto); if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); } else if (dirp->d_reclen < entrysize) { pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); } else if (dirp->d_reclen < 2 * entrysize) { proto.d_reclen = dirp->d_reclen; memcpy(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; } else { n = dirp->d_reclen - entrysize; proto.d_reclen = entrysize; memcpy(dirp, &proto, (size_t)entrysize); idesc->id_entryno++; lncntp[dirp->d_ino]--; dirp = (struct direct *)((char *)(dirp) + entrysize); memset(dirp, 0, (size_t)n); dirp->d_reclen = n; if (reply("FIX") == 1) ret |= ALTERED; } chk1: if (idesc->id_entryno > 1) goto chk2; inp = getinoinfo(idesc->id_number); proto.d_ino = inp->i_parent; if (newinofmt) proto.d_type = DT_DIR; else proto.d_type = 0; proto.d_namlen = 2; (void)strlcpy(proto.d_name, "..", sizeof proto.d_name); # if BYTE_ORDER == LITTLE_ENDIAN if (!newinofmt) { u_char tmp; tmp = proto.d_type; proto.d_type = proto.d_namlen; proto.d_namlen = tmp; } # endif entrysize = DIRSIZ(0, &proto); if (idesc->id_entryno == 0) { n = DIRSIZ(0, dirp); if (dirp->d_reclen < n + entrysize) goto chk2; proto.d_reclen = dirp->d_reclen - n; dirp->d_reclen = n; idesc->id_entryno++; lncntp[dirp->d_ino]--; dirp = (struct direct *)((char *)(dirp) + n); memset(dirp, 0, (size_t)proto.d_reclen); dirp->d_reclen = proto.d_reclen; } if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { inp->i_dotdot = dirp->d_ino; if (newinofmt && dirp->d_type != DT_DIR) { direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); dirp->d_type = DT_DIR; if (reply("FIX") == 1) ret |= ALTERED; } goto chk2; } if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); inp->i_dotdot = -1; } else if (dirp->d_reclen < entrysize) { fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); inp->i_dotdot = -1; } else if (inp->i_parent != 0) { /* * We know the parent, so fix now. */ inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); proto.d_reclen = dirp->d_reclen; memcpy(dirp, &proto, (size_t)entrysize); if (reply("FIX") == 1) ret |= ALTERED; } idesc->id_entryno++; if (dirp->d_ino != 0) lncntp[dirp->d_ino]--; return (ret|KEEPON); chk2: if (dirp->d_ino == 0) return (ret|KEEPON); if (dirp->d_namlen <= 2 && dirp->d_name[0] == '.' && idesc->id_entryno >= 2) { if (dirp->d_namlen == 1) { direrror(idesc->id_number, "EXTRA '.' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } if (dirp->d_name[1] == '.') { direrror(idesc->id_number, "EXTRA '..' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } } idesc->id_entryno++; n = 0; if (dirp->d_ino > maxino) { fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); n = reply("REMOVE"); } else { again: switch (GET_ISTATE(dirp->d_ino)) { case USTATE: if (idesc->id_entryno <= 2) break; fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); n = reply("REMOVE"); break; case DCLEAR: case FCLEAR: if (idesc->id_entryno <= 2) break; if (GET_ISTATE(dirp->d_ino) == FCLEAR) errmsg = "DUP/BAD"; else if (!preen && !usedsoftdep) errmsg = "ZERO LENGTH DIRECTORY"; else { n = 1; break; } fileerror(idesc->id_number, dirp->d_ino, errmsg); if ((n = reply("REMOVE")) == 1) break; dp = ginode(dirp->d_ino); SET_ISTATE(dirp->d_ino, (DIP(dp, di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE); lncntp[dirp->d_ino] = DIP(dp, di_nlink); goto again; case DSTATE: case DFOUND: inp = getinoinfo(dirp->d_ino); if (inp->i_parent != 0 && idesc->id_entryno > 2) { getpathname(pathbuf, sizeof pathbuf, idesc->id_number, idesc->id_number); getpathname(namebuf, sizeof namebuf, dirp->d_ino, dirp->d_ino); pwarn("%s %s %s\n", pathbuf, "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", namebuf); if (preen) { printf (" (REMOVED)\n"); n = 1; break; } if ((n = reply("REMOVE")) == 1) break; } if (idesc->id_entryno > 2) inp->i_parent = idesc->id_number; /* FALLTHROUGH */ case FSTATE: if (newinofmt && dirp->d_type != GET_ITYPE(dirp->d_ino)) { fileerror(idesc->id_number, dirp->d_ino, "BAD TYPE VALUE"); dirp->d_type = GET_ITYPE(dirp->d_ino); if (reply("FIX") == 1) ret |= ALTERED; } lncntp[dirp->d_ino]--; break; default: errexit("BAD STATE %d FOR INODE I=%d\n", GET_ISTATE(dirp->d_ino), dirp->d_ino); } } if (n == 0) return (ret|KEEPON); dirp->d_ino = 0; return (ret|KEEPON|ALTERED); }
void pass2(void) { union dinode *dp; struct inoinfo **inpp, *inp, *pinp; struct inoinfo **inpend; struct inostat *rinfo, *info; struct inodesc curino; union dinode dino; int i, maxblk; char pathbuf[MAXPATHLEN + 1]; rinfo = inoinfo(ROOTINO); switch (rinfo->ino_state) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) { markclean = 0; ckfini(); exit(FSCK_EXIT_CHECK_FAILED); } if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE"); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE"); break; } markclean = 0; if (reply("CONTINUE") == 0) { ckfini(); exit(FSCK_EXIT_CHECK_FAILED); } break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE"); break; } if (reply("FIX") == 0) { markclean = 0; ckfini(); exit(FSCK_EXIT_CHECK_FAILED); } dp = ginode(ROOTINO); DIP_SET(dp, mode, iswap16((iswap16(DIP(dp, mode)) & ~IFMT) | IFDIR)); inodirty(); break; case DSTATE: break; default: errexit("BAD STATE %d FOR ROOT INODE", rinfo->ino_state); } if (newinofmt) { info = inoinfo(WINO); info->ino_state = FSTATE; info->ino_type = DT_WHT; } /* * Sort the directory list into disk block order. */ qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); /* * Check the integrity of each directory. */ memset(&curino, 0, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { if (got_siginfo) { fprintf(stderr, "%s: phase 2: dir %ld of %d (%d%%)\n", cdevname(), (long)(inpp - inpsort), (int)inplast, (int)((inpp - inpsort) * 100 / inplast)); got_siginfo = 0; } #ifdef PROGRESS progress_bar(cdevname(), preen ? NULL : "phase 2", (inpp - inpsort), inplast); #endif /* PROGRESS */ inp = *inpp; if (inp->i_isize == 0) continue; if (inp->i_isize < MINDIRSIZE) { direrror(inp->i_number, "DIRECTORY TOO SHORT"); inp->i_isize = roundup(MINDIRSIZE, dirblksiz); if (reply("FIX") == 1) { dp = ginode(inp->i_number); DIP_SET(dp, size, iswap64(inp->i_isize)); inodirty(); } else markclean = 0; } else if ((inp->i_isize & (dirblksiz - 1)) != 0) { getpathname(pathbuf, sizeof(pathbuf), inp->i_number, inp->i_number); if (usedsoftdep) pfatal("%s %s: LENGTH %lld NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, (long long)inp->i_isize, dirblksiz); else pwarn("%s %s: LENGTH %lld NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, (long long)inp->i_isize, dirblksiz); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, dirblksiz); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); DIP_SET(dp, size, iswap64(inp->i_isize)); inodirty(); } else markclean = 0; } memset(&dino, 0, sizeof dino); dp = &dino; if (!is_ufs2) { dp->dp1.di_mode = iswap16(IFDIR); dp->dp1.di_size = iswap64(inp->i_isize); maxblk = inp->i_numblks < NDADDR ? inp->i_numblks : NDADDR; for (i = 0; i < maxblk; i++) dp->dp1.di_db[i] = inp->i_blks[i]; if (inp->i_numblks > NDADDR) { for (i = 0; i < NIADDR; i++) dp->dp1.di_ib[i] = inp->i_blks[NDADDR + i]; } } else { dp->dp2.di_mode = iswap16(IFDIR); dp->dp2.di_size = iswap64(inp->i_isize); maxblk = inp->i_numblks < NDADDR ? inp->i_numblks : NDADDR; for (i = 0; i < maxblk; i++) dp->dp2.di_db[i] = inp->i_blks[i]; if (inp->i_numblks > NDADDR) { for (i = 0; i < NIADDR; i++) dp->dp2.di_ib[i] = inp->i_blks[NDADDR + i]; } } curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(&dino, &curino); } /* * Byte swapping in directory entries, if needed, has been done. * Now rescan dirs for pass2check() */ if (do_dirswap) { do_dirswap = 0; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_isize == 0) continue; memset(&dino, 0, sizeof dino); if (!is_ufs2) { dino.dp1.di_mode = iswap16(IFDIR); dino.dp1.di_size = iswap64(inp->i_isize); for (i = 0; i < inp->i_numblks; i++) dino.dp1.di_db[i] = inp->i_blks[i]; } else { dino.dp2.di_mode = iswap16(IFDIR); dino.dp2.di_size = iswap64(inp->i_isize); for (i = 0; i < inp->i_numblks; i++) dino.dp2.di_db[i] = inp->i_blks[i]; } curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(&dino, &curino); } } /* * Now that the parents of all directories have been found, * make another pass to verify the value of `..' */ for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_isize == 0) continue; if (inp->i_dotdot == inp->i_parent || inp->i_dotdot == (ino_t)-1) continue; info = inoinfo(inp->i_parent); if (inp->i_dotdot == 0) { inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); if (reply("FIX") == 0) { markclean = 0; continue; } (void)makeentry(inp->i_number, inp->i_parent, ".."); info->ino_linkcnt--; continue; } fileerror(inp->i_parent, inp->i_number, "BAD INODE NUMBER FOR '..'"); if (reply("FIX") == 0) { markclean = 0; continue; } inoinfo(inp->i_dotdot)->ino_linkcnt++; info->ino_linkcnt--; inp->i_dotdot = inp->i_parent; (void)changeino(inp->i_number, "..", inp->i_parent); } /* * Create a list of children for each directory. */ inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; info = inoinfo(inp->i_number); inp->i_child = inp->i_sibling = 0; if (info->ino_state == DFOUND) info->ino_state = DSTATE; } for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_number == ROOTINO) continue; pinp = getinoinfo(inp->i_parent); inp->i_sibling = pinp->i_child; pinp->i_child = inp; } /* * Mark all the directories that can be found from the root. */ propagate(ROOTINO); #ifdef PROGRESS if (!preen) progress_done(); #endif /* PROGRESS */ }
void direrror(ino_t ino, const char *errmesg) { fileerror(ino, ino, errmesg); }
void pass2(void) { union dinode *dp; struct inoinfo **inpp, *inp, *pinp; struct inoinfo **inpend; struct inodesc curino; union dinode dino; char pathbuf[MAXPATHLEN + 1]; int i; switch (GET_ISTATE(ROOTINO)) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) { ckfini(0); errexit("%s", ""); } if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; } if (reply("CONTINUE") == 0) { ckfini(0); errexit("%s", ""); } break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); break; } if (reply("FIX") == 0) { ckfini(0); errexit("%s", ""); } dp = ginode(ROOTINO); DIP_SET(dp, di_mode, DIP(dp, di_mode) & ~IFMT); DIP_SET(dp, di_mode, DIP(dp, di_mode) | IFDIR); inodirty(); break; case DSTATE: break; default: errexit("BAD STATE %d FOR ROOT INODE\n", GET_ISTATE(ROOTINO)); } SET_ISTATE(ROOTINO, DFOUND); /* * Sort the directory list into disk block order. */ qsort(inpsort, (size_t)inplast, sizeof *inpsort, blksort); /* * Check the integrity of each directory. */ memset(&curino, 0, sizeof(struct inodesc)); curino.id_type = DATA; curino.id_func = pass2check; inpend = &inpsort[inplast]; info_pos = 0; info_max = inpend - inpsort; info_fn = pass2_info1; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; info_pos ++; if (inp->i_isize == 0) continue; if (inp->i_isize < MINDIRSIZE) { direrror(inp->i_number, "DIRECTORY TOO SHORT"); inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); if (reply("FIX") == 1) { dp = ginode(inp->i_number); DIP_SET(dp, di_size, inp->i_isize); inodirty(); } } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { getpathname(pathbuf, sizeof pathbuf, inp->i_number, inp->i_number); if (usedsoftdep) pfatal("%s %s: LENGTH %ld NOT MULTIPLE of %d", "DIRECTORY", pathbuf, (long)inp->i_isize, DIRBLKSIZ); else pwarn("%s %s: LENGTH %ld NOT MULTIPLE OF %d", "DIRECTORY", pathbuf, (long)inp->i_isize, DIRBLKSIZ); if (preen) printf(" (ADJUSTED)\n"); inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); if (preen || reply("ADJUST") == 1) { dp = ginode(inp->i_number); DIP_SET(dp, di_size, inp->i_isize); inodirty(); } } memset(&dino, 0, sizeof(union dinode)); dp = &dino; DIP_SET(dp, di_mode, IFDIR); DIP_SET(dp, di_size, inp->i_isize); for (i = 0; i < (inp->i_numblks<NDADDR ? inp->i_numblks : NDADDR); i++) DIP_SET(dp, di_db[i], inp->i_blks[i]); if (inp->i_numblks > NDADDR) for (i = 0; i < NIADDR; i++) DIP_SET(dp, di_ib[i], inp->i_blks[NDADDR + i]); curino.id_number = inp->i_number; curino.id_parent = inp->i_parent; (void)ckinode(dp, &curino); } /* * Now that the parents of all directories have been found, * make another pass to verify the value of `..' */ info_pos = 0; info_fn = pass2_info2; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; info_pos++; if (inp->i_parent == 0 || inp->i_isize == 0) continue; if (inp->i_dotdot == inp->i_parent || inp->i_dotdot == (ino_t)-1) continue; if (inp->i_dotdot == 0) { inp->i_dotdot = inp->i_parent; fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); if (reply("FIX") == 0) continue; (void)makeentry(inp->i_number, inp->i_parent, ".."); lncntp[inp->i_parent]--; continue; } fileerror(inp->i_parent, inp->i_number, "BAD INODE NUMBER FOR '..'"); if (reply("FIX") == 0) continue; lncntp[inp->i_dotdot]++; lncntp[inp->i_parent]--; inp->i_dotdot = inp->i_parent; (void)changeino(inp->i_number, "..", inp->i_parent); } info_fn = NULL; /* * Create a list of children for each directory. */ inpend = &inpsort[inplast]; for (inpp = inpsort; inpp < inpend; inpp++) { inp = *inpp; if (inp->i_parent == 0 || inp->i_number == ROOTINO) continue; pinp = getinoinfo(inp->i_parent); inp->i_parentp = pinp; inp->i_sibling = pinp->i_child; pinp->i_child = inp; } /* * Mark all the directories that can be found from the root. */ propagate(ROOTINO); }