pass2.c revision 23799
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1986, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3523675Speterstatic const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95"; 361558Srgrimes#endif /* not lint */ 371558Srgrimes 381558Srgrimes#include <sys/param.h> 391558Srgrimes#include <sys/time.h> 4023675Speter 411558Srgrimes#include <ufs/ufs/dinode.h> 421558Srgrimes#include <ufs/ufs/dir.h> 431558Srgrimes#include <ufs/ffs/fs.h> 4423799Sbde 4523675Speter#include <err.h> 461558Srgrimes#include <string.h> 4723675Speter 481558Srgrimes#include "fsck.h" 491558Srgrimes 501558Srgrimes#define MINDIRSIZE (sizeof (struct dirtemplate)) 511558Srgrimes 5223675Speterstatic int blksort __P((const void *, const void *)); 5323675Speterstatic int pass2check __P((struct inodesc *)); 541558Srgrimes 557585Sbdevoid 561558Srgrimespass2() 571558Srgrimes{ 581558Srgrimes register struct dinode *dp; 591558Srgrimes register struct inoinfo **inpp, *inp; 601558Srgrimes struct inoinfo **inpend; 611558Srgrimes struct inodesc curino; 621558Srgrimes struct dinode dino; 631558Srgrimes char pathbuf[MAXPATHLEN + 1]; 641558Srgrimes 651558Srgrimes switch (statemap[ROOTINO]) { 661558Srgrimes 671558Srgrimes case USTATE: 681558Srgrimes pfatal("ROOT INODE UNALLOCATED"); 691558Srgrimes if (reply("ALLOCATE") == 0) 7023675Speter exit(EEXIT); 711558Srgrimes if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 7223675Speter errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 731558Srgrimes break; 741558Srgrimes 751558Srgrimes case DCLEAR: 761558Srgrimes pfatal("DUPS/BAD IN ROOT INODE"); 771558Srgrimes if (reply("REALLOCATE")) { 781558Srgrimes freeino(ROOTINO); 791558Srgrimes if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 8023675Speter errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 811558Srgrimes break; 821558Srgrimes } 831558Srgrimes if (reply("CONTINUE") == 0) 8423675Speter exit(EEXIT); 851558Srgrimes break; 861558Srgrimes 871558Srgrimes case FSTATE: 881558Srgrimes case FCLEAR: 891558Srgrimes pfatal("ROOT INODE NOT DIRECTORY"); 901558Srgrimes if (reply("REALLOCATE")) { 911558Srgrimes freeino(ROOTINO); 921558Srgrimes if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 9323675Speter errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 941558Srgrimes break; 951558Srgrimes } 961558Srgrimes if (reply("FIX") == 0) 9723675Speter exit(EEXIT); 981558Srgrimes dp = ginode(ROOTINO); 991558Srgrimes dp->di_mode &= ~IFMT; 1001558Srgrimes dp->di_mode |= IFDIR; 1011558Srgrimes inodirty(); 1021558Srgrimes break; 1031558Srgrimes 1041558Srgrimes case DSTATE: 1051558Srgrimes break; 1061558Srgrimes 1071558Srgrimes default: 10823675Speter errx(EEXIT, "BAD STATE %d FOR ROOT INODE", statemap[ROOTINO]); 1091558Srgrimes } 1101558Srgrimes statemap[ROOTINO] = DFOUND; 11123675Speter if (newinofmt) { 11223675Speter statemap[WINO] = FSTATE; 11323675Speter typemap[WINO] = DT_WHT; 11423675Speter } 1151558Srgrimes /* 1161558Srgrimes * Sort the directory list into disk block order. 1171558Srgrimes */ 1181558Srgrimes qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); 1191558Srgrimes /* 1201558Srgrimes * Check the integrity of each directory. 1211558Srgrimes */ 12223675Speter memset(&curino, 0, sizeof(struct inodesc)); 1231558Srgrimes curino.id_type = DATA; 1241558Srgrimes curino.id_func = pass2check; 1251558Srgrimes dp = &dino; 1261558Srgrimes inpend = &inpsort[inplast]; 1271558Srgrimes for (inpp = inpsort; inpp < inpend; inpp++) { 1281558Srgrimes inp = *inpp; 1291558Srgrimes if (inp->i_isize == 0) 1301558Srgrimes continue; 1311558Srgrimes if (inp->i_isize < MINDIRSIZE) { 1321558Srgrimes direrror(inp->i_number, "DIRECTORY TOO SHORT"); 1331558Srgrimes inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); 1341558Srgrimes if (reply("FIX") == 1) { 1351558Srgrimes dp = ginode(inp->i_number); 1361558Srgrimes dp->di_size = inp->i_isize; 1371558Srgrimes inodirty(); 1381558Srgrimes dp = &dino; 1391558Srgrimes } 1401558Srgrimes } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { 1411558Srgrimes getpathname(pathbuf, inp->i_number, inp->i_number); 1421558Srgrimes pwarn("DIRECTORY %s: LENGTH %d NOT MULTIPLE OF %d", 1431558Srgrimes pathbuf, inp->i_isize, DIRBLKSIZ); 1441558Srgrimes if (preen) 1451558Srgrimes printf(" (ADJUSTED)\n"); 1461558Srgrimes inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); 1471558Srgrimes if (preen || reply("ADJUST") == 1) { 1481558Srgrimes dp = ginode(inp->i_number); 1491558Srgrimes dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); 1501558Srgrimes inodirty(); 1511558Srgrimes dp = &dino; 1521558Srgrimes } 1531558Srgrimes } 15423675Speter memset(&dino, 0, sizeof(struct dinode)); 1551558Srgrimes dino.di_mode = IFDIR; 1561558Srgrimes dp->di_size = inp->i_isize; 15723675Speter memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks); 1581558Srgrimes curino.id_number = inp->i_number; 1591558Srgrimes curino.id_parent = inp->i_parent; 1601558Srgrimes (void)ckinode(dp, &curino); 1611558Srgrimes } 1621558Srgrimes /* 1631558Srgrimes * Now that the parents of all directories have been found, 1641558Srgrimes * make another pass to verify the value of `..' 1651558Srgrimes */ 1661558Srgrimes for (inpp = inpsort; inpp < inpend; inpp++) { 1671558Srgrimes inp = *inpp; 1681558Srgrimes if (inp->i_parent == 0 || inp->i_isize == 0) 1691558Srgrimes continue; 1701558Srgrimes if (statemap[inp->i_parent] == DFOUND && 1711558Srgrimes statemap[inp->i_number] == DSTATE) 1721558Srgrimes statemap[inp->i_number] = DFOUND; 1731558Srgrimes if (inp->i_dotdot == inp->i_parent || 1741558Srgrimes inp->i_dotdot == (ino_t)-1) 1751558Srgrimes continue; 1761558Srgrimes if (inp->i_dotdot == 0) { 1771558Srgrimes inp->i_dotdot = inp->i_parent; 1781558Srgrimes fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); 1791558Srgrimes if (reply("FIX") == 0) 1801558Srgrimes continue; 1811558Srgrimes (void)makeentry(inp->i_number, inp->i_parent, ".."); 1821558Srgrimes lncntp[inp->i_parent]--; 1831558Srgrimes continue; 1841558Srgrimes } 1851558Srgrimes fileerror(inp->i_parent, inp->i_number, 1861558Srgrimes "BAD INODE NUMBER FOR '..'"); 1871558Srgrimes if (reply("FIX") == 0) 1881558Srgrimes continue; 1891558Srgrimes lncntp[inp->i_dotdot]++; 1901558Srgrimes lncntp[inp->i_parent]--; 1911558Srgrimes inp->i_dotdot = inp->i_parent; 1921558Srgrimes (void)changeino(inp->i_number, "..", inp->i_parent); 1931558Srgrimes } 1941558Srgrimes /* 1951558Srgrimes * Mark all the directories that can be found from the root. 1961558Srgrimes */ 1971558Srgrimes propagate(); 1981558Srgrimes} 1991558Srgrimes 20023675Speterstatic int 2011558Srgrimespass2check(idesc) 2021558Srgrimes struct inodesc *idesc; 2031558Srgrimes{ 2041558Srgrimes register struct direct *dirp = idesc->id_dirp; 2051558Srgrimes register struct inoinfo *inp; 2061558Srgrimes int n, entrysize, ret = 0; 2071558Srgrimes struct dinode *dp; 2081558Srgrimes char *errmsg; 2091558Srgrimes struct direct proto; 2101558Srgrimes char namebuf[MAXPATHLEN + 1]; 2111558Srgrimes char pathbuf[MAXPATHLEN + 1]; 2121558Srgrimes 2131558Srgrimes /* 2141558Srgrimes * If converting, set directory entry type. 2151558Srgrimes */ 2161558Srgrimes if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) { 2171558Srgrimes dirp->d_type = typemap[dirp->d_ino]; 2181558Srgrimes ret |= ALTERED; 2191558Srgrimes } 2208871Srgrimes /* 2211558Srgrimes * check for "." 2221558Srgrimes */ 2231558Srgrimes if (idesc->id_entryno != 0) 2241558Srgrimes goto chk1; 2251558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { 2261558Srgrimes if (dirp->d_ino != idesc->id_number) { 2271558Srgrimes direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); 2281558Srgrimes dirp->d_ino = idesc->id_number; 2291558Srgrimes if (reply("FIX") == 1) 2301558Srgrimes ret |= ALTERED; 2311558Srgrimes } 2321558Srgrimes if (newinofmt && dirp->d_type != DT_DIR) { 2331558Srgrimes direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); 2341558Srgrimes dirp->d_type = DT_DIR; 2351558Srgrimes if (reply("FIX") == 1) 2361558Srgrimes ret |= ALTERED; 2371558Srgrimes } 2381558Srgrimes goto chk1; 2391558Srgrimes } 2401558Srgrimes direrror(idesc->id_number, "MISSING '.'"); 2411558Srgrimes proto.d_ino = idesc->id_number; 2421558Srgrimes if (newinofmt) 2431558Srgrimes proto.d_type = DT_DIR; 2441558Srgrimes else 2451558Srgrimes proto.d_type = 0; 2461558Srgrimes proto.d_namlen = 1; 2471558Srgrimes (void)strcpy(proto.d_name, "."); 24823675Speter# if BYTE_ORDER == LITTLE_ENDIAN 24923675Speter if (!newinofmt) { 25023675Speter u_char tmp; 25123675Speter 25223675Speter tmp = proto.d_type; 25323675Speter proto.d_type = proto.d_namlen; 25423675Speter proto.d_namlen = tmp; 25523675Speter } 25623675Speter# endif 2571558Srgrimes entrysize = DIRSIZ(0, &proto); 2581558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { 2591558Srgrimes pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", 2601558Srgrimes dirp->d_name); 2611558Srgrimes } else if (dirp->d_reclen < entrysize) { 2621558Srgrimes pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); 2631558Srgrimes } else if (dirp->d_reclen < 2 * entrysize) { 2641558Srgrimes proto.d_reclen = dirp->d_reclen; 26523675Speter memmove(dirp, &proto, (size_t)entrysize); 2661558Srgrimes if (reply("FIX") == 1) 2671558Srgrimes ret |= ALTERED; 2681558Srgrimes } else { 2691558Srgrimes n = dirp->d_reclen - entrysize; 2701558Srgrimes proto.d_reclen = entrysize; 27123675Speter memmove(dirp, &proto, (size_t)entrysize); 2721558Srgrimes idesc->id_entryno++; 2731558Srgrimes lncntp[dirp->d_ino]--; 2741558Srgrimes dirp = (struct direct *)((char *)(dirp) + entrysize); 27523675Speter memset(dirp, 0, (size_t)n); 2761558Srgrimes dirp->d_reclen = n; 2771558Srgrimes if (reply("FIX") == 1) 2781558Srgrimes ret |= ALTERED; 2791558Srgrimes } 2801558Srgrimeschk1: 2811558Srgrimes if (idesc->id_entryno > 1) 2821558Srgrimes goto chk2; 2831558Srgrimes inp = getinoinfo(idesc->id_number); 2841558Srgrimes proto.d_ino = inp->i_parent; 2851558Srgrimes if (newinofmt) 2861558Srgrimes proto.d_type = DT_DIR; 2871558Srgrimes else 2881558Srgrimes proto.d_type = 0; 2891558Srgrimes proto.d_namlen = 2; 2901558Srgrimes (void)strcpy(proto.d_name, ".."); 29123675Speter# if BYTE_ORDER == LITTLE_ENDIAN 29223675Speter if (!newinofmt) { 29323675Speter u_char tmp; 29423675Speter 29523675Speter tmp = proto.d_type; 29623675Speter proto.d_type = proto.d_namlen; 29723675Speter proto.d_namlen = tmp; 29823675Speter } 29923675Speter# endif 3001558Srgrimes entrysize = DIRSIZ(0, &proto); 3011558Srgrimes if (idesc->id_entryno == 0) { 3021558Srgrimes n = DIRSIZ(0, dirp); 3031558Srgrimes if (dirp->d_reclen < n + entrysize) 3041558Srgrimes goto chk2; 3051558Srgrimes proto.d_reclen = dirp->d_reclen - n; 3061558Srgrimes dirp->d_reclen = n; 3071558Srgrimes idesc->id_entryno++; 3081558Srgrimes lncntp[dirp->d_ino]--; 3091558Srgrimes dirp = (struct direct *)((char *)(dirp) + n); 31023675Speter memset(dirp, 0, (size_t)proto.d_reclen); 3111558Srgrimes dirp->d_reclen = proto.d_reclen; 3121558Srgrimes } 3131558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { 3141558Srgrimes inp->i_dotdot = dirp->d_ino; 3151558Srgrimes if (newinofmt && dirp->d_type != DT_DIR) { 3161558Srgrimes direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); 3171558Srgrimes dirp->d_type = DT_DIR; 3181558Srgrimes if (reply("FIX") == 1) 3191558Srgrimes ret |= ALTERED; 3201558Srgrimes } 3211558Srgrimes goto chk2; 3221558Srgrimes } 3231558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { 3241558Srgrimes fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 3251558Srgrimes pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", 3261558Srgrimes dirp->d_name); 3271558Srgrimes inp->i_dotdot = (ino_t)-1; 3281558Srgrimes } else if (dirp->d_reclen < entrysize) { 3291558Srgrimes fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 3301558Srgrimes pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); 3311558Srgrimes inp->i_dotdot = (ino_t)-1; 3321558Srgrimes } else if (inp->i_parent != 0) { 3331558Srgrimes /* 3341558Srgrimes * We know the parent, so fix now. 3351558Srgrimes */ 3361558Srgrimes inp->i_dotdot = inp->i_parent; 3371558Srgrimes fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 3381558Srgrimes proto.d_reclen = dirp->d_reclen; 33923675Speter memmove(dirp, &proto, (size_t)entrysize); 3401558Srgrimes if (reply("FIX") == 1) 3411558Srgrimes ret |= ALTERED; 3421558Srgrimes } 3431558Srgrimes idesc->id_entryno++; 3441558Srgrimes if (dirp->d_ino != 0) 3451558Srgrimes lncntp[dirp->d_ino]--; 3461558Srgrimes return (ret|KEEPON); 3471558Srgrimeschk2: 3481558Srgrimes if (dirp->d_ino == 0) 3491558Srgrimes return (ret|KEEPON); 3501558Srgrimes if (dirp->d_namlen <= 2 && 3511558Srgrimes dirp->d_name[0] == '.' && 3521558Srgrimes idesc->id_entryno >= 2) { 3531558Srgrimes if (dirp->d_namlen == 1) { 3541558Srgrimes direrror(idesc->id_number, "EXTRA '.' ENTRY"); 3551558Srgrimes dirp->d_ino = 0; 3561558Srgrimes if (reply("FIX") == 1) 3571558Srgrimes ret |= ALTERED; 3581558Srgrimes return (KEEPON | ret); 3591558Srgrimes } 3601558Srgrimes if (dirp->d_name[1] == '.') { 3611558Srgrimes direrror(idesc->id_number, "EXTRA '..' ENTRY"); 3621558Srgrimes dirp->d_ino = 0; 3631558Srgrimes if (reply("FIX") == 1) 3641558Srgrimes ret |= ALTERED; 3651558Srgrimes return (KEEPON | ret); 3661558Srgrimes } 3671558Srgrimes } 3681558Srgrimes idesc->id_entryno++; 3691558Srgrimes n = 0; 3701558Srgrimes if (dirp->d_ino > maxino) { 3711558Srgrimes fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); 3721558Srgrimes n = reply("REMOVE"); 37323675Speter } else if (newinofmt && 37423675Speter ((dirp->d_ino == WINO && dirp->d_type != DT_WHT) || 37523675Speter (dirp->d_ino != WINO && dirp->d_type == DT_WHT))) { 37623675Speter fileerror(idesc->id_number, dirp->d_ino, "BAD WHITEOUT ENTRY"); 37723675Speter dirp->d_ino = WINO; 37823675Speter dirp->d_type = DT_WHT; 37923675Speter if (reply("FIX") == 1) 38023675Speter ret |= ALTERED; 3811558Srgrimes } else { 3821558Srgrimesagain: 3831558Srgrimes switch (statemap[dirp->d_ino]) { 3841558Srgrimes case USTATE: 3851558Srgrimes if (idesc->id_entryno <= 2) 3861558Srgrimes break; 3871558Srgrimes fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); 3881558Srgrimes n = reply("REMOVE"); 3891558Srgrimes break; 3901558Srgrimes 3911558Srgrimes case DCLEAR: 3921558Srgrimes case FCLEAR: 3931558Srgrimes if (idesc->id_entryno <= 2) 3941558Srgrimes break; 3951558Srgrimes if (statemap[dirp->d_ino] == FCLEAR) 3961558Srgrimes errmsg = "DUP/BAD"; 3971558Srgrimes else if (!preen) 3981558Srgrimes errmsg = "ZERO LENGTH DIRECTORY"; 3991558Srgrimes else { 4001558Srgrimes n = 1; 4011558Srgrimes break; 4021558Srgrimes } 4031558Srgrimes fileerror(idesc->id_number, dirp->d_ino, errmsg); 4041558Srgrimes if ((n = reply("REMOVE")) == 1) 4051558Srgrimes break; 4061558Srgrimes dp = ginode(dirp->d_ino); 4071558Srgrimes statemap[dirp->d_ino] = 4081558Srgrimes (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE; 4091558Srgrimes lncntp[dirp->d_ino] = dp->di_nlink; 4101558Srgrimes goto again; 4111558Srgrimes 4121558Srgrimes case DSTATE: 4131558Srgrimes if (statemap[idesc->id_number] == DFOUND) 4141558Srgrimes statemap[dirp->d_ino] = DFOUND; 4151558Srgrimes /* fall through */ 4161558Srgrimes 4171558Srgrimes case DFOUND: 4181558Srgrimes inp = getinoinfo(dirp->d_ino); 4191558Srgrimes if (inp->i_parent != 0 && idesc->id_entryno > 2) { 4201558Srgrimes getpathname(pathbuf, idesc->id_number, 4211558Srgrimes idesc->id_number); 4221558Srgrimes getpathname(namebuf, dirp->d_ino, dirp->d_ino); 4231558Srgrimes pwarn("%s %s %s\n", pathbuf, 4241558Srgrimes "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", 4251558Srgrimes namebuf); 4261558Srgrimes if (preen) 4271558Srgrimes printf(" (IGNORED)\n"); 4281558Srgrimes else if ((n = reply("REMOVE")) == 1) 4291558Srgrimes break; 4301558Srgrimes } 4311558Srgrimes if (idesc->id_entryno > 2) 4321558Srgrimes inp->i_parent = idesc->id_number; 4331558Srgrimes /* fall through */ 4341558Srgrimes 4351558Srgrimes case FSTATE: 4361558Srgrimes if (newinofmt && dirp->d_type != typemap[dirp->d_ino]) { 4371558Srgrimes fileerror(idesc->id_number, dirp->d_ino, 4381558Srgrimes "BAD TYPE VALUE"); 4391558Srgrimes dirp->d_type = typemap[dirp->d_ino]; 4401558Srgrimes if (reply("FIX") == 1) 4411558Srgrimes ret |= ALTERED; 4421558Srgrimes } 4431558Srgrimes lncntp[dirp->d_ino]--; 4441558Srgrimes break; 4451558Srgrimes 4461558Srgrimes default: 44723675Speter errx(EEXIT, "BAD STATE %d FOR INODE I=%d", 4481558Srgrimes statemap[dirp->d_ino], dirp->d_ino); 4491558Srgrimes } 4501558Srgrimes } 4511558Srgrimes if (n == 0) 4521558Srgrimes return (ret|KEEPON); 4531558Srgrimes dirp->d_ino = 0; 4541558Srgrimes return (ret|KEEPON|ALTERED); 4551558Srgrimes} 4561558Srgrimes 4571558Srgrimes/* 4581558Srgrimes * Routine to sort disk blocks. 4591558Srgrimes */ 46023675Speterstatic int 46123675Speterblksort(arg1, arg2) 46223675Speter const void *arg1, *arg2; 4631558Srgrimes{ 4641558Srgrimes 46523675Speter return ((*(struct inoinfo **)arg1)->i_blks[0] - 46623675Speter (*(struct inoinfo **)arg2)->i_blks[0]); 4671558Srgrimes} 468