pass2.c revision 102411
167910Sbrian/* 267910Sbrian * Copyright (c) 1980, 1986, 1993 367910Sbrian * The Regents of the University of California. All rights reserved. 467910Sbrian * 567910Sbrian * Redistribution and use in source and binary forms, with or without 667910Sbrian * modification, are permitted provided that the following conditions 767910Sbrian * are met: 867910Sbrian * 1. Redistributions of source code must retain the above copyright 967910Sbrian * notice, this list of conditions and the following disclaimer. 1067910Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1167910Sbrian * notice, this list of conditions and the following disclaimer in the 1267910Sbrian * documentation and/or other materials provided with the distribution. 1367910Sbrian * 3. All advertising materials mentioning features or use of this software 1467910Sbrian * must display the following acknowledgement: 1567910Sbrian * This product includes software developed by the University of 1667910Sbrian * California, Berkeley and its contributors. 1767910Sbrian * 4. Neither the name of the University nor the names of its contributors 1867910Sbrian * may be used to endorse or promote products derived from this software 1967910Sbrian * without specific prior written permission. 2067910Sbrian * 2167910Sbrian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2267910Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2367910Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2467910Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2567910Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2667910Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2767910Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2867910Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2998132Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3067910Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3198132Sbrian * SUCH DAMAGE. 3298132Sbrian */ 3396402Sbrian 3498132Sbrian#if 0 3598132Sbrian#ifndef lint 3693462Sbrianstatic const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95"; 3767910Sbrian#endif /* not lint */ 3867910Sbrian#endif 3996768Sbrian 4067910Sbrian#include <sys/cdefs.h> 4167910Sbrian__FBSDID("$FreeBSD: head/sbin/fsck_ffs/pass2.c 102411 2002-08-25 13:10:45Z charnier $"); 4267910Sbrian 4367910Sbrian#include <sys/param.h> 4467910Sbrian 4567910Sbrian#include <ufs/ufs/dinode.h> 4667910Sbrian#include <ufs/ufs/dir.h> 4767910Sbrian#include <ufs/ffs/fs.h> 4867910Sbrian 4967910Sbrian#include <err.h> 5067910Sbrian#include <stdint.h> 5167910Sbrian#include <string.h> 5272025Sbrian 5372025Sbrian#include "fsck.h" 5472025Sbrian 5567910Sbrian#define MINDIRSIZE (sizeof (struct dirtemplate)) 5672025Sbrian 5767910Sbrianstatic int blksort(const void *, const void *); 5883403Sbrianstatic int pass2check(struct inodesc *); 5998132Sbrian 6098132Sbrianvoid 6198132Sbrianpass2(void) 6298132Sbrian{ 6398132Sbrian union dinode *dp; 6498132Sbrian struct inoinfo **inpp, *inp; 6598132Sbrian struct inoinfo **inpend; 6698132Sbrian struct inodesc curino; 6798132Sbrian union dinode dino; 6898132Sbrian int i; 6998132Sbrian char pathbuf[MAXPATHLEN + 1]; 7098132Sbrian 7198132Sbrian switch (inoinfo(ROOTINO)->ino_state) { 7267910Sbrian 7367910Sbrian case USTATE: 7467910Sbrian pfatal("ROOT INODE UNALLOCATED"); 7567910Sbrian if (reply("ALLOCATE") == 0) { 7667910Sbrian ckfini(0); 7767910Sbrian exit(EEXIT); 7867910Sbrian } 7967910Sbrian if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 8078411Sbrian errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 8178411Sbrian break; 8278411Sbrian 8378411Sbrian case DCLEAR: 8478411Sbrian pfatal("DUPS/BAD IN ROOT INODE"); 8578411Sbrian if (reply("REALLOCATE")) { 8678411Sbrian freeino(ROOTINO); 8778411Sbrian if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 8879376Sbrian errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 8979376Sbrian break; 9079376Sbrian } 9179376Sbrian if (reply("CONTINUE") == 0) { 9279376Sbrian ckfini(0); 9379376Sbrian exit(EEXIT); 9479376Sbrian } 9578411Sbrian break; 9667910Sbrian 9778411Sbrian case FSTATE: 9878411Sbrian case FCLEAR: 9978411Sbrian pfatal("ROOT INODE NOT DIRECTORY"); 10078411Sbrian if (reply("REALLOCATE")) { 101134789Sbrian freeino(ROOTINO); 10278411Sbrian if (allocdir(ROOTINO, ROOTINO, 0755) != ROOTINO) 10378411Sbrian errx(EEXIT, "CANNOT ALLOCATE ROOT INODE"); 10478411Sbrian break; 10578411Sbrian } 10667910Sbrian if (reply("FIX") == 0) { 10767910Sbrian ckfini(0); 10867910Sbrian exit(EEXIT); 10968461Sbrian } 11067910Sbrian dp = ginode(ROOTINO); 11167910Sbrian DIP(dp, di_mode) &= ~IFMT; 11278411Sbrian DIP(dp, di_mode) |= IFDIR; 11378411Sbrian inodirty(); 11478411Sbrian break; 11578411Sbrian 11667910Sbrian case DSTATE: 11767910Sbrian break; 11878411Sbrian 11978411Sbrian default: 12078411Sbrian errx(EEXIT, "BAD STATE %d FOR ROOT INODE", 12178411Sbrian inoinfo(ROOTINO)->ino_state); 12278411Sbrian } 12378411Sbrian inoinfo(ROOTINO)->ino_state = DFOUND; 12478411Sbrian inoinfo(WINO)->ino_state = FSTATE; 12578411Sbrian inoinfo(WINO)->ino_type = DT_WHT; 12678411Sbrian /* 12778411Sbrian * Sort the directory list into disk block order. 12867910Sbrian */ 12967910Sbrian qsort((char *)inpsort, (size_t)inplast, sizeof *inpsort, blksort); 13067912Sbrian /* 13167912Sbrian * Check the integrity of each directory. 13267912Sbrian */ 13367910Sbrian memset(&curino, 0, sizeof(struct inodesc)); 13467910Sbrian curino.id_type = DATA; 13567910Sbrian curino.id_func = pass2check; 13667910Sbrian inpend = &inpsort[inplast]; 13767910Sbrian for (inpp = inpsort; inpp < inpend; inpp++) { 13867910Sbrian if (got_siginfo) { 13967910Sbrian printf("%s: phase 2: dir %td of %d (%d%%)\n", cdevname, 14096544Sbrian inpp - inpsort, (int)inplast, 14167910Sbrian (int)((inpp - inpsort) * 100 / inplast)); 14267910Sbrian got_siginfo = 0; 14367910Sbrian } 14467912Sbrian inp = *inpp; 14567912Sbrian if (inp->i_isize == 0) 14667912Sbrian continue; 14767910Sbrian if (inp->i_isize < MINDIRSIZE) { 14867910Sbrian direrror(inp->i_number, "DIRECTORY TOO SHORT"); 14967910Sbrian inp->i_isize = roundup(MINDIRSIZE, DIRBLKSIZ); 15067910Sbrian if (reply("FIX") == 1) { 15167910Sbrian dp = ginode(inp->i_number); 15267910Sbrian DIP(dp, di_size) = inp->i_isize; 15367910Sbrian inodirty(); 15467910Sbrian } 15567910Sbrian } else if ((inp->i_isize & (DIRBLKSIZ - 1)) != 0) { 15667910Sbrian getpathname(pathbuf, inp->i_number, inp->i_number); 15767910Sbrian if (usedsoftdep) 158134789Sbrian pfatal("%s %s: LENGTH %jd NOT MULTIPLE OF %d", 159134789Sbrian "DIRECTORY", pathbuf, 16067910Sbrian (intmax_t)inp->i_isize, DIRBLKSIZ); 16167910Sbrian else 16267910Sbrian pwarn("%s %s: LENGTH %jd NOT MULTIPLE OF %d", 16378411Sbrian "DIRECTORY", pathbuf, 16478411Sbrian (intmax_t)inp->i_isize, DIRBLKSIZ); 16567910Sbrian if (preen) 16667910Sbrian printf(" (ADJUSTED)\n"); 16767910Sbrian inp->i_isize = roundup(inp->i_isize, DIRBLKSIZ); 16878411Sbrian if (preen || reply("ADJUST") == 1) { 16967910Sbrian dp = ginode(inp->i_number); 17067910Sbrian DIP(dp, di_size) = 171256574Skevlo roundup(inp->i_isize, DIRBLKSIZ); 17267910Sbrian inodirty(); 17378411Sbrian } 17478411Sbrian } 17567910Sbrian dp = &dino; 17667910Sbrian memset(dp, 0, sizeof(struct ufs2_dinode)); 17767910Sbrian DIP(dp, di_mode) = IFDIR; 17867910Sbrian DIP(dp, di_size) = inp->i_isize; 17967910Sbrian for (i = 0; 18067910Sbrian i < (inp->i_numblks<NDADDR ? inp->i_numblks : NDADDR); 18167910Sbrian i++) 18267910Sbrian DIP(dp, di_db[i]) = inp->i_blks[i]; 18367910Sbrian if (inp->i_numblks > NDADDR) 18478411Sbrian for (i = 0; i < NIADDR; i++) 18578411Sbrian DIP(dp, di_ib[i]) = inp->i_blks[NDADDR + i]; 18667910Sbrian curino.id_number = inp->i_number; 18778411Sbrian curino.id_parent = inp->i_parent; 18878411Sbrian (void)ckinode(dp, &curino); 18978411Sbrian } 19078411Sbrian /* 19178411Sbrian * Now that the parents of all directories have been found, 19278411Sbrian * make another pass to verify the value of `..' 19378411Sbrian */ 19478411Sbrian for (inpp = inpsort; inpp < inpend; inpp++) { 19578411Sbrian inp = *inpp; 19678411Sbrian if (inp->i_parent == 0 || inp->i_isize == 0) 19778411Sbrian continue; 19878411Sbrian if (inoinfo(inp->i_parent)->ino_state == DFOUND && 19978411Sbrian inoinfo(inp->i_number)->ino_state == DSTATE) 20078411Sbrian inoinfo(inp->i_number)->ino_state = DFOUND; 20178411Sbrian if (inp->i_dotdot == inp->i_parent || 20278411Sbrian inp->i_dotdot == (ino_t)-1) 20378411Sbrian continue; 20478411Sbrian if (inp->i_dotdot == 0) { 20578411Sbrian inp->i_dotdot = inp->i_parent; 20678411Sbrian fileerror(inp->i_parent, inp->i_number, "MISSING '..'"); 20778411Sbrian if (reply("FIX") == 0) 20867910Sbrian continue; 20983403Sbrian (void)makeentry(inp->i_number, inp->i_parent, ".."); 21067910Sbrian inoinfo(inp->i_parent)->ino_linkcnt--; 21167910Sbrian continue; 21267910Sbrian } 21367910Sbrian fileerror(inp->i_parent, inp->i_number, 21467910Sbrian "BAD INODE NUMBER FOR '..'"); 21567910Sbrian if (reply("FIX") == 0) 21667910Sbrian continue; 21767910Sbrian inoinfo(inp->i_dotdot)->ino_linkcnt++; 21867910Sbrian inoinfo(inp->i_parent)->ino_linkcnt--; 21978411Sbrian inp->i_dotdot = inp->i_parent; 22078411Sbrian (void)changeino(inp->i_number, "..", inp->i_parent); 22167910Sbrian } 22278411Sbrian /* 22367910Sbrian * Mark all the directories that can be found from the root. 22478411Sbrian */ 22578411Sbrian propagate(); 22678411Sbrian} 22767910Sbrian 22867912Sbrianstatic int 22978411Sbrianpass2check(struct inodesc *idesc) 23067910Sbrian{ 23167910Sbrian struct direct *dirp = idesc->id_dirp; 23267910Sbrian struct inoinfo *inp; 23367910Sbrian int n, entrysize, ret = 0; 23467910Sbrian union dinode *dp; 235134789Sbrian const char *errmsg; 23667910Sbrian struct direct proto; 23778411Sbrian char namebuf[MAXPATHLEN + 1]; 23867910Sbrian char pathbuf[MAXPATHLEN + 1]; 23967910Sbrian 24067910Sbrian /* 24167910Sbrian * check for "." 24267910Sbrian */ 24367910Sbrian if (idesc->id_entryno != 0) 24467910Sbrian goto chk1; 24567910Sbrian if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { 24678411Sbrian if (dirp->d_ino != idesc->id_number) { 24767910Sbrian direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'"); 24867910Sbrian dirp->d_ino = idesc->id_number; 24978411Sbrian if (reply("FIX") == 1) 25078411Sbrian ret |= ALTERED; 25167910Sbrian } 25267910Sbrian if (dirp->d_type != DT_DIR) { 25367910Sbrian direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'"); 25467910Sbrian dirp->d_type = DT_DIR; 25567910Sbrian if (reply("FIX") == 1) 25667910Sbrian ret |= ALTERED; 25778411Sbrian } 25878411Sbrian goto chk1; 25978411Sbrian } 26078411Sbrian direrror(idesc->id_number, "MISSING '.'"); 26178411Sbrian proto.d_ino = idesc->id_number; 26267910Sbrian proto.d_type = DT_DIR; 26367910Sbrian proto.d_namlen = 1; 26467910Sbrian (void)strcpy(proto.d_name, "."); 26567910Sbrian entrysize = DIRSIZ(0, &proto); 26678411Sbrian if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { 26778411Sbrian pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", 26878411Sbrian dirp->d_name); 26978411Sbrian } else if (dirp->d_reclen < entrysize) { 27078411Sbrian pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); 27178411Sbrian } else if (dirp->d_reclen < 2 * entrysize) { 27278411Sbrian proto.d_reclen = dirp->d_reclen; 27367910Sbrian memmove(dirp, &proto, (size_t)entrysize); 27467910Sbrian if (reply("FIX") == 1) 27578411Sbrian ret |= ALTERED; 27678411Sbrian } else { 27778411Sbrian n = dirp->d_reclen - entrysize; 27878411Sbrian proto.d_reclen = entrysize; 27978411Sbrian memmove(dirp, &proto, (size_t)entrysize); 28078411Sbrian idesc->id_entryno++; 28178411Sbrian inoinfo(dirp->d_ino)->ino_linkcnt--; 28278411Sbrian dirp = (struct direct *)((char *)(dirp) + entrysize); 28378411Sbrian memset(dirp, 0, (size_t)n); 28478411Sbrian dirp->d_reclen = n; 28578411Sbrian if (reply("FIX") == 1) 28678411Sbrian ret |= ALTERED; 28778411Sbrian } 28878411Sbrianchk1: 28978411Sbrian if (idesc->id_entryno > 1) 29078411Sbrian goto chk2; 29178411Sbrian inp = getinoinfo(idesc->id_number); 29278411Sbrian proto.d_ino = inp->i_parent; 29378411Sbrian proto.d_type = DT_DIR; 29478411Sbrian proto.d_namlen = 2; 29578411Sbrian (void)strcpy(proto.d_name, ".."); 29679376Sbrian entrysize = DIRSIZ(0, &proto); 29779376Sbrian if (idesc->id_entryno == 0) { 29878411Sbrian n = DIRSIZ(0, dirp); 29978411Sbrian if (dirp->d_reclen < n + entrysize) 30078411Sbrian goto chk2; 30178411Sbrian proto.d_reclen = dirp->d_reclen - n; 30278411Sbrian dirp->d_reclen = n; 30378411Sbrian idesc->id_entryno++; 30478411Sbrian inoinfo(dirp->d_ino)->ino_linkcnt--; 30578411Sbrian dirp = (struct direct *)((char *)(dirp) + n); 30678411Sbrian memset(dirp, 0, (size_t)proto.d_reclen); 30767910Sbrian dirp->d_reclen = proto.d_reclen; 30878411Sbrian } 30978411Sbrian if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { 31078411Sbrian inp->i_dotdot = dirp->d_ino; 31178411Sbrian if (dirp->d_type != DT_DIR) { 31278411Sbrian direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'"); 31378411Sbrian dirp->d_type = DT_DIR; 31478411Sbrian if (reply("FIX") == 1) 31582411Sbrian ret |= ALTERED; 31682411Sbrian } 31778411Sbrian goto chk2; 31878411Sbrian } 31978411Sbrian if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { 32078411Sbrian fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 32178411Sbrian pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", 32278411Sbrian dirp->d_name); 32378411Sbrian inp->i_dotdot = (ino_t)-1; 32478411Sbrian } else if (dirp->d_reclen < entrysize) { 32578411Sbrian fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 32678411Sbrian pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); 32778411Sbrian inp->i_dotdot = (ino_t)-1; 32878411Sbrian } else if (inp->i_parent != 0) { 32978411Sbrian /* 33078411Sbrian * We know the parent, so fix now. 33178411Sbrian */ 33278411Sbrian inp->i_dotdot = inp->i_parent; 33378411Sbrian fileerror(inp->i_parent, idesc->id_number, "MISSING '..'"); 33478411Sbrian proto.d_reclen = dirp->d_reclen; 33578411Sbrian memmove(dirp, &proto, (size_t)entrysize); 33678411Sbrian if (reply("FIX") == 1) 33778411Sbrian ret |= ALTERED; 33878411Sbrian } 33978411Sbrian idesc->id_entryno++; 34078411Sbrian if (dirp->d_ino != 0) 34178411Sbrian inoinfo(dirp->d_ino)->ino_linkcnt--; 34278411Sbrian return (ret|KEEPON); 34378411Sbrianchk2: 34478411Sbrian if (dirp->d_ino == 0) 34578411Sbrian return (ret|KEEPON); 34678411Sbrian if (dirp->d_namlen <= 2 && 34778411Sbrian dirp->d_name[0] == '.' && 34878411Sbrian idesc->id_entryno >= 2) { 34978411Sbrian if (dirp->d_namlen == 1) { 35078411Sbrian direrror(idesc->id_number, "EXTRA '.' ENTRY"); 35178411Sbrian dirp->d_ino = 0; 35278411Sbrian if (reply("FIX") == 1) 35378411Sbrian ret |= ALTERED; 35478411Sbrian return (KEEPON | ret); 35578411Sbrian } 35678411Sbrian if (dirp->d_name[1] == '.') { 35767910Sbrian direrror(idesc->id_number, "EXTRA '..' ENTRY"); 35867910Sbrian dirp->d_ino = 0; 35967910Sbrian if (reply("FIX") == 1) 36067910Sbrian ret |= ALTERED; 36167910Sbrian return (KEEPON | ret); 36278411Sbrian } 36378411Sbrian } 36467910Sbrian idesc->id_entryno++; 36578411Sbrian n = 0; 36678411Sbrian if (dirp->d_ino > maxino) { 36778411Sbrian fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE"); 36867910Sbrian n = reply("REMOVE"); 36978411Sbrian } else if (((dirp->d_ino == WINO && dirp->d_type != DT_WHT) || 37067910Sbrian (dirp->d_ino != WINO && dirp->d_type == DT_WHT))) { 37167910Sbrian fileerror(idesc->id_number, dirp->d_ino, "BAD WHITEOUT ENTRY"); 37267910Sbrian dirp->d_ino = WINO; 37367910Sbrian dirp->d_type = DT_WHT; 37467910Sbrian if (reply("FIX") == 1) 375134789Sbrian ret |= ALTERED; 376134789Sbrian } else { 37767910Sbrianagain: 378134789Sbrian switch (inoinfo(dirp->d_ino)->ino_state) { 37967910Sbrian case USTATE: 38067910Sbrian if (idesc->id_entryno <= 2) 38167910Sbrian break; 38294894Sbrian fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED"); 38367910Sbrian n = reply("REMOVE"); 38478411Sbrian break; 38583403Sbrian 38678411Sbrian case DCLEAR: 38792221Sbrian case FCLEAR: 38878411Sbrian if (idesc->id_entryno <= 2) 38983403Sbrian break; 39092221Sbrian if (inoinfo(dirp->d_ino)->ino_state == FCLEAR) 39192221Sbrian errmsg = "DUP/BAD"; 39292221Sbrian else if (!preen && !usedsoftdep) 39378411Sbrian errmsg = "ZERO LENGTH DIRECTORY"; 39492221Sbrian else { 39592221Sbrian n = 1; 39678411Sbrian break; 39778411Sbrian } 39878411Sbrian fileerror(idesc->id_number, dirp->d_ino, errmsg); 39992221Sbrian if ((n = reply("REMOVE")) == 1) 40092221Sbrian break; 40178411Sbrian dp = ginode(dirp->d_ino); 40278411Sbrian inoinfo(dirp->d_ino)->ino_state = 40378411Sbrian (DIP(dp, di_mode) & IFMT) == IFDIR ? DSTATE : FSTATE; 40492221Sbrian inoinfo(dirp->d_ino)->ino_linkcnt = DIP(dp, di_nlink); 40592221Sbrian goto again; 40678411Sbrian 40778411Sbrian case DSTATE: 40878411Sbrian if (inoinfo(idesc->id_number)->ino_state == DFOUND) 40992221Sbrian inoinfo(dirp->d_ino)->ino_state = DFOUND; 41092221Sbrian /* FALLTHROUGH */ 41178411Sbrian 41278411Sbrian case DFOUND: 41378411Sbrian inp = getinoinfo(dirp->d_ino); 41478411Sbrian if (inp->i_parent != 0 && idesc->id_entryno > 2) { 41592221Sbrian getpathname(pathbuf, idesc->id_number, 41692221Sbrian idesc->id_number); 41792221Sbrian getpathname(namebuf, dirp->d_ino, dirp->d_ino); 41878411Sbrian pwarn("%s%s%s %s %s\n", pathbuf, 41978411Sbrian (strcmp(pathbuf, "/") == 0 ? "" : "/"), 42092221Sbrian dirp->d_name, 42192221Sbrian "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", 42278411Sbrian namebuf); 42378411Sbrian if (cursnapshot != 0) 42478411Sbrian break; 42578411Sbrian if (preen) { 42667910Sbrian printf(" (REMOVED)\n"); 42767910Sbrian n = 1; 42867910Sbrian break; 42972025Sbrian } 43072025Sbrian if ((n = reply("REMOVE")) == 1) 43172025Sbrian break; 43272025Sbrian } 43398966Sbrian if (idesc->id_entryno > 2) 43498966Sbrian inp->i_parent = idesc->id_number; 43572025Sbrian /* FALLTHROUGH */ 43698966Sbrian 43798966Sbrian case FSTATE: 43898966Sbrian if (dirp->d_type != inoinfo(dirp->d_ino)->ino_type) { 43998966Sbrian fileerror(idesc->id_number, dirp->d_ino, 44098966Sbrian "BAD TYPE VALUE"); 44198966Sbrian dirp->d_type = inoinfo(dirp->d_ino)->ino_type; 44298966Sbrian if (reply("FIX") == 1) 44398966Sbrian ret |= ALTERED; 44498966Sbrian } 44598966Sbrian inoinfo(dirp->d_ino)->ino_linkcnt--; 44698966Sbrian break; 44798966Sbrian 44898966Sbrian default: 44998966Sbrian errx(EEXIT, "BAD STATE %d FOR INODE I=%d", 45098966Sbrian inoinfo(dirp->d_ino)->ino_state, dirp->d_ino); 45198966Sbrian } 45298966Sbrian } 45372025Sbrian if (n == 0) 45472025Sbrian return (ret|KEEPON); 45572025Sbrian dirp->d_ino = 0; 45672025Sbrian return (ret|KEEPON|ALTERED); 45778411Sbrian} 45878411Sbrian 45978411Sbrian/* 46098132Sbrian * Routine to sort disk blocks. 46198132Sbrian */ 46298132Sbrianstatic int 46398132Sbrianblksort(const void *arg1, const void *arg2) 46498132Sbrian{ 46598132Sbrian 46698132Sbrian return ((*(struct inoinfo * const *)arg1)->i_blks[0] - 46798132Sbrian (*(struct inoinfo * const *)arg2)->i_blks[0]); 46898132Sbrian} 46978411Sbrian