pass2.c revision 41477
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 3541477Sjulian#if 0 3623675Speterstatic const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95"; 3741477Sjulian#endif 3841477Sjulianstatic const char rcsid[] = 3941477Sjulian "$Id: pass2.c,v 1.7 1998/06/15 07:07:18 charnier Exp $"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 421558Srgrimes#include <sys/param.h> 4323675Speter 441558Srgrimes#include <ufs/ufs/dinode.h> 451558Srgrimes#include <ufs/ufs/dir.h> 4623799Sbde 4723675Speter#include <err.h> 481558Srgrimes#include <string.h> 4923675Speter 501558Srgrimes#include "fsck.h" 511558Srgrimes 521558Srgrimes#define MINDIRSIZE (sizeof (struct dirtemplate)) 531558Srgrimes 5423675Speterstatic int blksort __P((const void *, const void *)); 5523675Speterstatic int pass2check __P((struct inodesc *)); 561558Srgrimes 577585Sbdevoid 581558Srgrimespass2() 591558Srgrimes{ 601558Srgrimes register struct dinode *dp; 611558Srgrimes register struct inoinfo **inpp, *inp; 621558Srgrimes struct inoinfo **inpend; 631558Srgrimes struct inodesc curino; 641558Srgrimes struct dinode dino; 651558Srgrimes char pathbuf[MAXPATHLEN + 1]; 661558Srgrimes 6741474Sjulian switch (inoinfo(ROOTINO)->ino_state) { 681558Srgrimes 691558Srgrimes case USTATE: 701558Srgrimes pfatal("ROOT INODE UNALLOCATED"); 7134266Sjulian if (reply("ALLOCATE") == 0) { 7234266Sjulian ckfini(0); 7323675Speter exit(EEXIT); 7434266Sjulian } 751558Srgrimes if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 7623675Speter errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 771558Srgrimes break; 781558Srgrimes 791558Srgrimes case DCLEAR: 801558Srgrimes pfatal("DUPS/BAD IN ROOT INODE"); 811558Srgrimes if (reply("REALLOCATE")) { 821558Srgrimes freeino(ROOTINO); 831558Srgrimes if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 8423675Speter errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 851558Srgrimes break; 861558Srgrimes } 8734266Sjulian if (reply("CONTINUE") == 0) { 8834266Sjulian ckfini(0); 8923675Speter exit(EEXIT); 9034266Sjulian } 911558Srgrimes break; 921558Srgrimes 931558Srgrimes case FSTATE: 941558Srgrimes case FCLEAR: 951558Srgrimes pfatal("ROOT INODE NOT DIRECTORY"); 961558Srgrimes if (reply("REALLOCATE")) { 971558Srgrimes freeino(ROOTINO); 981558Srgrimes if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 9923675Speter errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 1001558Srgrimes break; 1011558Srgrimes } 10234266Sjulian if (reply("FIX") == 0) { 10334266Sjulian ckfini(0); 10423675Speter exit(EEXIT); 10534266Sjulian } 1061558Srgrimes dp = ginode(ROOTINO); 1071558Srgrimes dp->di_mode &= ~IFMT; 1081558Srgrimes dp->di_mode |= IFDIR; 1091558Srgrimes inodirty(); 1101558Srgrimes break; 1111558Srgrimes 1121558Srgrimes case DSTATE: 1131558Srgrimes break; 1141558Srgrimes 1151558Srgrimes default: 11641474Sjulian errx(EEXIT, "BAD STATE %d FOR ROOT INODE", 11741474Sjulian inoinfo(ROOTINO)->ino_state); 1181558Srgrimes } 11941474Sjulian inoinfo(ROOTINO)->ino_state = DFOUND; 12023675Speter if (newinofmt) { 12141474Sjulian inoinfo(WINO)->ino_state = FSTATE; 12241474Sjulian inoinfo(WINO)->ino_type = DT_WHT; 12323675Speter } 1241558Srgrimes /* 1251558Srgrimes * Sort the directory list into disk block order. 1261558Srgrimes */ 1271558Srgrimes qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); 1281558Srgrimes /* 1291558Srgrimes * Check the integrity of each directory. 1301558Srgrimes */ 13123675Speter memset(&curino, 0, sizeof(struct inodesc)); 1321558Srgrimes curino.id_type = DATA; 1331558Srgrimes curino.id_func = pass2check; 1341558Srgrimes dp = &dino; 1351558Srgrimes inpend = &inpsort[inplast]; 1361558Srgrimes for (inpp = inpsort; inpp < inpend; inpp++) { 1371558Srgrimes inp = *inpp; 1381558Srgrimes if (inp->i_isize == 0) 1391558Srgrimes continue; 1401558Srgrimes if (inp->i_isize < MINDIRSIZE) { 1411558Srgrimes direrror(inp->i_number, "DIRECTORY TOO SHORT"); 1421558Srgrimes inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); 1431558Srgrimes if (reply("FIX") == 1) { 1441558Srgrimes dp = ginode(inp->i_number); 1451558Srgrimes dp->di_size = inp->i_isize; 1461558Srgrimes inodirty(); 1471558Srgrimes dp = &dino; 1481558Srgrimes } 1491558Srgrimes } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { 1501558Srgrimes getpathname(pathbuf, inp->i_number, inp->i_number); 15134266Sjulian if (usedsoftdep) 15234266Sjulian pfatal("%s %s: LENGTH %d NOT MULTIPLE OF %d", 15334266Sjulian "DIRECTORY", pathbuf, inp->i_isize, 15434266Sjulian DIRBLKSIZ); 15534266Sjulian else 15634266Sjulian pwarn("%s %s: LENGTH %d NOT MULTIPLE OF %d", 15734266Sjulian "DIRECTORY", pathbuf, inp->i_isize, 15834266Sjulian DIRBLKSIZ); 1591558Srgrimes if (preen) 1601558Srgrimes printf(" (ADJUSTED)\n"); 1611558Srgrimes inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); 1621558Srgrimes if (preen || reply("ADJUST") == 1) { 1631558Srgrimes dp = ginode(inp->i_number); 1641558Srgrimes dp->di_size = roundup(inp->i_isize, DIRBLKSIZ); 1651558Srgrimes inodirty(); 1661558Srgrimes dp = &dino; 1671558Srgrimes } 1681558Srgrimes } 16923675Speter memset(&dino, 0, sizeof(struct dinode)); 1701558Srgrimes dino.di_mode = IFDIR; 1711558Srgrimes dp->di_size = inp->i_isize; 17223675Speter memmove(&dp->di_db[0], &inp->i_blks[0], (size_t)inp->i_numblks); 1731558Srgrimes curino.id_number = inp->i_number; 1741558Srgrimes curino.id_parent = inp->i_parent; 1751558Srgrimes (void)ckinode(dp, &curino); 1761558Srgrimes } 1771558Srgrimes /* 1781558Srgrimes * Now that the parents of all directories have been found, 1791558Srgrimes * make another pass to verify the value of `..' 1801558Srgrimes */ 1811558Srgrimes for (inpp = inpsort; inpp < inpend; inpp++) { 1821558Srgrimes inp = *inpp; 1831558Srgrimes if (inp->i_parent == 0 || inp->i_isize == 0) 1841558Srgrimes continue; 18541474Sjulian if (inoinfo(inp->i_parent)->ino_state == DFOUND && 18641474Sjulian inoinfo(inp->i_number)->ino_state == DSTATE) 18741474Sjulian inoinfo(inp->i_number)->ino_state = DFOUND; 1881558Srgrimes if (inp->i_dotdot == inp->i_parent || 1891558Srgrimes inp->i_dotdot == (ino_t)-1) 1901558Srgrimes continue; 1911558Srgrimes if (inp->i_dotdot == 0) { 1921558Srgrimes inp->i_dotdot = inp->i_parent; 1931558Srgrimes fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); 1941558Srgrimes if (reply("FIX") == 0) 1951558Srgrimes continue; 1961558Srgrimes (void)makeentry(inp->i_number, inp->i_parent, ".."); 19741474Sjulian inoinfo(inp->i_parent)->ino_linkcnt--; 1981558Srgrimes continue; 1991558Srgrimes } 2001558Srgrimes fileerror(inp->i_parent, inp->i_number, 2011558Srgrimes "BAD INODE NUMBER FOR '..'"); 2021558Srgrimes if (reply("FIX") == 0) 2031558Srgrimes continue; 20441474Sjulian inoinfo(inp->i_dotdot)->ino_linkcnt++; 20541474Sjulian inoinfo(inp->i_parent)->ino_linkcnt--; 2061558Srgrimes inp->i_dotdot = inp->i_parent; 2071558Srgrimes (void)changeino(inp->i_number, "..", inp->i_parent); 2081558Srgrimes } 2091558Srgrimes /* 2101558Srgrimes * Mark all the directories that can be found from the root. 2111558Srgrimes */ 2121558Srgrimes propagate(); 2131558Srgrimes} 2141558Srgrimes 21523675Speterstatic int 2161558Srgrimespass2check(idesc) 2171558Srgrimes struct inodesc *idesc; 2181558Srgrimes{ 2191558Srgrimes register struct direct *dirp = idesc->id_dirp; 2201558Srgrimes register struct inoinfo *inp; 2211558Srgrimes int n, entrysize, ret = 0; 2221558Srgrimes struct dinode *dp; 2231558Srgrimes char *errmsg; 2241558Srgrimes struct direct proto; 2251558Srgrimes char namebuf[MAXPATHLEN + 1]; 2261558Srgrimes char pathbuf[MAXPATHLEN + 1]; 2271558Srgrimes 2281558Srgrimes /* 2291558Srgrimes * If converting, set directory entry type. 2301558Srgrimes */ 2311558Srgrimes if (doinglevel2 && dirp->d_ino > 0 && dirp->d_ino < maxino) { 23241474Sjulian dirp->d_type = inoinfo(dirp->d_ino)->ino_type; 2331558Srgrimes ret |= ALTERED; 2341558Srgrimes } 2358871Srgrimes /* 2361558Srgrimes * check for "." 2371558Srgrimes */ 2381558Srgrimes if (idesc->id_entryno != 0) 2391558Srgrimes goto chk1; 2401558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { 2411558Srgrimes if (dirp->d_ino != idesc->id_number) { 2421558Srgrimes direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); 2431558Srgrimes dirp->d_ino = idesc->id_number; 2441558Srgrimes if (reply("FIX") == 1) 2451558Srgrimes ret |= ALTERED; 2461558Srgrimes } 2471558Srgrimes if (newinofmt && dirp->d_type != DT_DIR) { 2481558Srgrimes direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); 2491558Srgrimes dirp->d_type = DT_DIR; 2501558Srgrimes if (reply("FIX") == 1) 2511558Srgrimes ret |= ALTERED; 2521558Srgrimes } 2531558Srgrimes goto chk1; 2541558Srgrimes } 2551558Srgrimes direrror(idesc->id_number, "MISSING '.'"); 2561558Srgrimes proto.d_ino = idesc->id_number; 2571558Srgrimes if (newinofmt) 2581558Srgrimes proto.d_type = DT_DIR; 2591558Srgrimes else 2601558Srgrimes proto.d_type = 0; 2611558Srgrimes proto.d_namlen = 1; 2621558Srgrimes (void)strcpy(proto.d_name, "."); 26323675Speter# if BYTE_ORDER == LITTLE_ENDIAN 26423675Speter if (!newinofmt) { 26523675Speter u_char tmp; 26623675Speter 26723675Speter tmp = proto.d_type; 26823675Speter proto.d_type = proto.d_namlen; 26923675Speter proto.d_namlen = tmp; 27023675Speter } 27123675Speter# endif 2721558Srgrimes entrysize = DIRSIZ(0, &proto); 2731558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { 2741558Srgrimes pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", 2751558Srgrimes dirp->d_name); 2761558Srgrimes } else if (dirp->d_reclen < entrysize) { 2771558Srgrimes pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); 2781558Srgrimes } else if (dirp->d_reclen < 2 * entrysize) { 2791558Srgrimes proto.d_reclen = dirp->d_reclen; 28023675Speter memmove(dirp, &proto, (size_t)entrysize); 2811558Srgrimes if (reply("FIX") == 1) 2821558Srgrimes ret |= ALTERED; 2831558Srgrimes } else { 2841558Srgrimes n = dirp->d_reclen - entrysize; 2851558Srgrimes proto.d_reclen = entrysize; 28623675Speter memmove(dirp, &proto, (size_t)entrysize); 2871558Srgrimes idesc->id_entryno++; 28841474Sjulian inoinfo(dirp->d_ino)->ino_linkcnt--; 2891558Srgrimes dirp = (struct direct *)((char *)(dirp) + entrysize); 29023675Speter memset(dirp, 0, (size_t)n); 2911558Srgrimes dirp->d_reclen = n; 2921558Srgrimes if (reply("FIX") == 1) 2931558Srgrimes ret |= ALTERED; 2941558Srgrimes } 2951558Srgrimeschk1: 2961558Srgrimes if (idesc->id_entryno > 1) 2971558Srgrimes goto chk2; 2981558Srgrimes inp = getinoinfo(idesc->id_number); 2991558Srgrimes proto.d_ino = inp->i_parent; 3001558Srgrimes if (newinofmt) 3011558Srgrimes proto.d_type = DT_DIR; 3021558Srgrimes else 3031558Srgrimes proto.d_type = 0; 3041558Srgrimes proto.d_namlen = 2; 3051558Srgrimes (void)strcpy(proto.d_name, ".."); 30623675Speter# if BYTE_ORDER == LITTLE_ENDIAN 30723675Speter if (!newinofmt) { 30823675Speter u_char tmp; 30923675Speter 31023675Speter tmp = proto.d_type; 31123675Speter proto.d_type = proto.d_namlen; 31223675Speter proto.d_namlen = tmp; 31323675Speter } 31423675Speter# endif 3151558Srgrimes entrysize = DIRSIZ(0, &proto); 3161558Srgrimes if (idesc->id_entryno == 0) { 3171558Srgrimes n = DIRSIZ(0, dirp); 3181558Srgrimes if (dirp->d_reclen < n + entrysize) 3191558Srgrimes goto chk2; 3201558Srgrimes proto.d_reclen = dirp->d_reclen - n; 3211558Srgrimes dirp->d_reclen = n; 3221558Srgrimes idesc->id_entryno++; 32341474Sjulian inoinfo(dirp->d_ino)->ino_linkcnt--; 3241558Srgrimes dirp = (struct direct *)((char *)(dirp) + n); 32523675Speter memset(dirp, 0, (size_t)proto.d_reclen); 3261558Srgrimes dirp->d_reclen = proto.d_reclen; 3271558Srgrimes } 3281558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { 3291558Srgrimes inp->i_dotdot = dirp->d_ino; 3301558Srgrimes if (newinofmt && dirp->d_type != DT_DIR) { 3311558Srgrimes direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); 3321558Srgrimes dirp->d_type = DT_DIR; 3331558Srgrimes if (reply("FIX") == 1) 3341558Srgrimes ret |= ALTERED; 3351558Srgrimes } 3361558Srgrimes goto chk2; 3371558Srgrimes } 3381558Srgrimes if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { 3391558Srgrimes fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 3401558Srgrimes pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", 3411558Srgrimes dirp->d_name); 3421558Srgrimes inp->i_dotdot = (ino_t)-1; 3431558Srgrimes } else if (dirp->d_reclen < entrysize) { 3441558Srgrimes fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 3451558Srgrimes pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); 3461558Srgrimes inp->i_dotdot = (ino_t)-1; 3471558Srgrimes } else if (inp->i_parent != 0) { 3481558Srgrimes /* 3491558Srgrimes * We know the parent, so fix now. 3501558Srgrimes */ 3511558Srgrimes inp->i_dotdot = inp->i_parent; 3521558Srgrimes fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 3531558Srgrimes proto.d_reclen = dirp->d_reclen; 35423675Speter memmove(dirp, &proto, (size_t)entrysize); 3551558Srgrimes if (reply("FIX") == 1) 3561558Srgrimes ret |= ALTERED; 3571558Srgrimes } 3581558Srgrimes idesc->id_entryno++; 3591558Srgrimes if (dirp->d_ino != 0) 36041474Sjulian inoinfo(dirp->d_ino)->ino_linkcnt--; 3611558Srgrimes return (ret|KEEPON); 3621558Srgrimeschk2: 3631558Srgrimes if (dirp->d_ino == 0) 3641558Srgrimes return (ret|KEEPON); 3651558Srgrimes if (dirp->d_namlen <= 2 && 3661558Srgrimes dirp->d_name[0] == '.' && 3671558Srgrimes idesc->id_entryno >= 2) { 3681558Srgrimes if (dirp->d_namlen == 1) { 3691558Srgrimes direrror(idesc->id_number, "EXTRA '.' ENTRY"); 3701558Srgrimes dirp->d_ino = 0; 3711558Srgrimes if (reply("FIX") == 1) 3721558Srgrimes ret |= ALTERED; 3731558Srgrimes return (KEEPON | ret); 3741558Srgrimes } 3751558Srgrimes if (dirp->d_name[1] == '.') { 3761558Srgrimes direrror(idesc->id_number, "EXTRA '..' ENTRY"); 3771558Srgrimes dirp->d_ino = 0; 3781558Srgrimes if (reply("FIX") == 1) 3791558Srgrimes ret |= ALTERED; 3801558Srgrimes return (KEEPON | ret); 3811558Srgrimes } 3821558Srgrimes } 3831558Srgrimes idesc->id_entryno++; 3841558Srgrimes n = 0; 3851558Srgrimes if (dirp->d_ino > maxino) { 3861558Srgrimes fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); 3871558Srgrimes n = reply("REMOVE"); 38823675Speter } else if (newinofmt && 38923675Speter ((dirp->d_ino == WINO && dirp->d_type != DT_WHT) || 39023675Speter (dirp->d_ino != WINO && dirp->d_type == DT_WHT))) { 39123675Speter fileerror(idesc->id_number, dirp->d_ino, "BAD WHITEOUT ENTRY"); 39223675Speter dirp->d_ino = WINO; 39323675Speter dirp->d_type = DT_WHT; 39423675Speter if (reply("FIX") == 1) 39523675Speter ret |= ALTERED; 3961558Srgrimes } else { 3971558Srgrimesagain: 39841474Sjulian switch (inoinfo(dirp->d_ino)->ino_state) { 3991558Srgrimes case USTATE: 4001558Srgrimes if (idesc->id_entryno <= 2) 4011558Srgrimes break; 4021558Srgrimes fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); 4031558Srgrimes n = reply("REMOVE"); 4041558Srgrimes break; 4051558Srgrimes 4061558Srgrimes case DCLEAR: 4071558Srgrimes case FCLEAR: 4081558Srgrimes if (idesc->id_entryno <= 2) 4091558Srgrimes break; 41041474Sjulian if (inoinfo(dirp->d_ino)->ino_state == FCLEAR) 4111558Srgrimes errmsg = "DUP/BAD"; 41234266Sjulian else if (!preen && !usedsoftdep) 4131558Srgrimes errmsg = "ZERO LENGTH DIRECTORY"; 4141558Srgrimes else { 4151558Srgrimes n = 1; 4161558Srgrimes break; 4171558Srgrimes } 4181558Srgrimes fileerror(idesc->id_number, dirp->d_ino, errmsg); 4191558Srgrimes if ((n = reply("REMOVE")) == 1) 4201558Srgrimes break; 4211558Srgrimes dp = ginode(dirp->d_ino); 42241474Sjulian inoinfo(dirp->d_ino)->ino_state = 4231558Srgrimes (dp->di_mode & IFMT) == IFDIR ? DSTATE : FSTATE; 42441474Sjulian inoinfo(dirp->d_ino)->ino_linkcnt = dp->di_nlink; 4251558Srgrimes goto again; 4261558Srgrimes 4271558Srgrimes case DSTATE: 42841474Sjulian if (inoinfo(idesc->id_number)->ino_state == DFOUND) 42941474Sjulian inoinfo(dirp->d_ino)->ino_state = DFOUND; 4301558Srgrimes /* fall through */ 4311558Srgrimes 4321558Srgrimes case DFOUND: 4331558Srgrimes inp = getinoinfo(dirp->d_ino); 4341558Srgrimes if (inp->i_parent != 0 && idesc->id_entryno > 2) { 4351558Srgrimes getpathname(pathbuf, idesc->id_number, 4361558Srgrimes idesc->id_number); 4371558Srgrimes getpathname(namebuf, dirp->d_ino, dirp->d_ino); 4381558Srgrimes pwarn("%s %s %s\n", pathbuf, 4391558Srgrimes "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", 4401558Srgrimes namebuf); 44134266Sjulian if (preen) { 44234266Sjulian printf(" (REMOVED)\n"); 44341474Sjulian n = 1; 44441474Sjulian break; 44534266Sjulian } 44641474Sjulian if ((n = reply("REMOVE")) == 1) 4471558Srgrimes break; 4481558Srgrimes } 4491558Srgrimes if (idesc->id_entryno > 2) 4501558Srgrimes inp->i_parent = idesc->id_number; 4511558Srgrimes /* fall through */ 4521558Srgrimes 4531558Srgrimes case FSTATE: 45441474Sjulian if (newinofmt && 45541474Sjulian dirp->d_type != inoinfo(dirp->d_ino)->ino_type) { 4561558Srgrimes fileerror(idesc->id_number, dirp->d_ino, 4571558Srgrimes "BAD TYPE VALUE"); 45841474Sjulian dirp->d_type = inoinfo(dirp->d_ino)->ino_type; 4591558Srgrimes if (reply("FIX") == 1) 4601558Srgrimes ret |= ALTERED; 4611558Srgrimes } 46241474Sjulian inoinfo(dirp->d_ino)->ino_linkcnt--; 4631558Srgrimes break; 4641558Srgrimes 4651558Srgrimes default: 46623675Speter errx(EEXIT, "BAD STATE %d FOR INODE I=%d", 46741474Sjulian inoinfo(dirp->d_ino)->ino_state, dirp->d_ino); 4681558Srgrimes } 4691558Srgrimes } 4701558Srgrimes if (n == 0) 4711558Srgrimes return (ret|KEEPON); 4721558Srgrimes dirp->d_ino = 0; 4731558Srgrimes return (ret|KEEPON|ALTERED); 4741558Srgrimes} 4751558Srgrimes 4761558Srgrimes/* 4771558Srgrimes * Routine to sort disk blocks. 4781558Srgrimes */ 47923675Speterstatic int 48023675Speterblksort(arg1, arg2) 48123675Speter const void *arg1, *arg2; 4821558Srgrimes{ 4831558Srgrimes 48423675Speter return ((*(struct inoinfo **)arg1)->i_blks[0] - 48523675Speter (*(struct inoinfo **)arg2)->i_blks[0]); 4861558Srgrimes} 487