355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Use is subject to license terms.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/* All Rights Reserved */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * All rights reserved.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Redistribution and use in source and binary forms are permitted
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * provided that: (1) source distributions retain this entire copyright
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * notice and comment, and (2) distributions including binaries display
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the following acknowledgement: ``This product includes software
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * developed by the University of California, Berkeley and its contributors''
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * in the documentation or other materials provided with the distribution
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * and in all advertising materials mentioning features or use of this
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * software. Neither the name of the University nor the names of its
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * contributors may be used to endorse or promote products derived
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * from this software without specific prior written permission.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#pragma ident "%Z%%M% %I% %E% SMI"
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxstatic int blksort(const void *, const void *);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (allocdir(UFSROOTINO, UFSROOTINO, 0755, 0) != UFSROOTINO)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Technically, we do know who the parent is. However,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * if this is set, then we'll get confused during the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * second-dir-entry-is-dotdot test for the root inode.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Sort the directory list into disk block order. There's no
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * requirement to do this, but it may help improve our i/o times
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * somewhat.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox qsort((void *)inpsort, (size_t)inplast, sizeof (*inpsort), blksort);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Check the integrity of each directory. In general, we treat
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * attribute directories just like normal ones. Only the handling
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * of .. is really different.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* != DSTATE also covers case of == USTATE */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (((statemap[inp->i_number] & STMASK) != DSTATE) ||
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_isize = (offset_t)roundup(MINDIRSIZE, DIRBLKSIZ);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((inp->i_isize & (offset_t)(DIRBLKSIZ - 1)) != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pwarn("DIRECTORY %s: LENGTH %lld NOT MULTIPLE OF %d",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pwarn("ATTRIBUTE DIRECTORY I=%d MISSING IXATTR FLAG",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)&dp->di_db[0], (void *)&inp->i_blks[0],
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure we mark attrdirs as DFOUND, since they won't
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * be located during normal scan of standard directories.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Now that the parents of all directories have been found,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * make another pass to verify the value of ..
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * There are only directories in inpsort[], so only
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * directory-related states need to be checked. There
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * should never be any flags associated with USTATE.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * See if this is an attrdir that we located in pass1.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * i.e. it was on an i_oeftflag of some other inode.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * if it isn't found then we have an orphaned attrdir
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * that needs to be tossed into lost+found.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * We've already proven there's no "..", so this
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * can't create a duplicate.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (makeentry(inp->i_number, inp->i_parent, "..")) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * is it an orphaned attrdir?
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Throw it into lost+found
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "Unable to move attrdir I=%d to lost+found\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * iscorrupt is
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * already set
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "BAD INODE NUMBER FOR '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* iscorrupt is already set */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(inp->i_dotdot, lncntp[inp->i_dotdot]++);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* iscorrupt is already set */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(inp->i_parent, lncntp[inp->i_parent]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) changeino(inp->i_number, "..", inp->i_parent);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Mark all the directories that can be found from the root.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Sanity-check a single directory entry. Which entry is being
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * examined is tracked via idesc->id_entryno. There are two
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * special ones, 0 (.) and 1 (..). Those have to exist in order
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * in the first two locations in the directory, and have the usual
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * properties. All other entries have to not be for either of
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the special two, and the inode they reference has to be
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * reasonable.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * This is only called from dirscan(), which looks for the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * ALTERED flag after each invocation. If it finds it, the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * relevant buffer gets pushed out, so we don't have to worry
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * about it here.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#define PASS2B_PROMPT "REMOVE DIRECTORY ENTRY FROM I=%d"
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * check for "."
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Build up a new one, and make sure there's room to put
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * it where it belongs.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * No room for another entry after us ("." is the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * smallest entry you can have), so just put all
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * of the old entry's space into the new entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Because we don't touch id_entryno, we end up going
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * through the chk2 tests as well.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * There's enough room for an entire additional entry
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * after this, so create the "." entry and follow it
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * with an empty entry that covers the rest of the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * The increment of id_entryno means we'll skip the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * "." case of chk1, doing the ".." tests instead.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Since we know that there's not a ".." where it
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * should be (because we just created an empty entry
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * there), that's the best way of getting it recreated
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure the link count is in range before updating
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * it. This makes the assumption that the link count
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * for this inode included one for ".", even though
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * there wasn't a "." entry. Even if that's not true,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * it's a reasonable working hypothesis, and the link
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * count verification done in pass4 will fix it for
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * us anyway.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * The inode got zapped, so reset the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * directory entry. Extend it to also
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * cover the space we were going to make
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * into a new entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Create the new empty entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* LINTED pointer cast alignment (entrysize is valid) */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp = (struct direct *)((char *)(dirp) + entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Did the user want us to create a new "."? This
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * query assumes that the direrror(MISSING) was the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * last thing printed, so if the LINK_RANGE() check
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * fails, it can't pass through here.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * XXX The next few lines are needed whether we're processing "."
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * or "..". However, there are some extra steps still needed
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * for the former, hence the big block of code for
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * id_entryno == 0. Alternatively, there could be a label just
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * before this comment, and everything through the end of that
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * block moved there. In some ways, that might make the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * control flow more logical (factoring out to separate functions
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * would be even better).
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * This is a can't-happen, since inodes get cached before
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * we get called on them.
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcox errexit("pass2check got NULL from getinoinfo at chk1 I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * We may not actually need to split things up, but if
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * there's room to do so, we should, as that implies
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * that the "." entry is larger than it is supposed
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * to be, and therefore there's something wrong, albeit
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * possibly harmlessly so.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Not enough room for inserting a ".." after
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the "." entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * There's enough room for an entire additional entry
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * after "."'s, so split it up. There's no reason "."
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * should be bigger than the minimum, so shrink it to
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * fit, too. Since by the time we're done with this
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * part, dirp will be pointing at where ".." should be,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * update id_entryno to show that that's the entry
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * we're on.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Account for the link to ourselves.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * We were going to split the entry
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * up, but the link count overflowed.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Since we got rid of the inode,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * we need to also zap the directory
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * entry, and restoring the original
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * state of things is the least-bad
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure the new entry doesn't get interpreted
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * as having actual content.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* LINTED pointer cast alignment (reclen is valid) */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memset((void *)dirp, 0, (size_t)proto.d_reclen);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Everything was fine, up until we realized that
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the indicated inode was impossible. By clearing
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * d_ino here, we'll trigger the recreation of it
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * down below, using i_parent. Unlike the other
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * half of this if(), we're everything so it shows
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * that we're still on the "." entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "I OUT OF RANGE");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Record this ".." inode, but only if we haven't seen one before.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * If this isn't the first, it'll get cleared below, and so we
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * want to remember the entry that'll still be around later.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* XXX Same consideration as immediately above. */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * We know the parent, so fix now.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Lint won't be quiet about d_reclen being set but not
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * used. It apparently doesn't understand the implications
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * of calling memmove(), and won't believe us that it's ok.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Always know parent of root inode, so fix now.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_ino = inp->i_dotdot = inp->i_parent = UFSROOTINO;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Lint won't be quiet about d_reclen being set but not
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * used. It apparently doesn't understand the implications
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * of calling memmove(), and won't believe us that it's ok.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)dirp, (void *)&proto, (size_t)entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Because of this increment, all tests for skipping . and ..
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * below are ``> 2'', not ``> 1'' as would logically be expected.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * The obvious check would be for d_ino < UFSROOTINO. However,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * 1 is a valid inode number. Although it isn't currently used,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * as it was once the bad block list, there's nothing to prevent
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * it from acquiring a new purpose in the future. So, don't
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * arbitrarily disallow it. We don't test for <= zero, because
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * d_ino is unsigned.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = (reply(PASS2B_PROMPT, idesc->id_number) == 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = (reply(PASS2B_PROMPT, idesc->id_number) == 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "REFERENCE TO ZERO LENGTH ATTRIBUTE DIRECTORY" :
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "REFERENCE TO ZERO LENGTH DIRECTORY";
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * The inode doesn't exist, as all
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * should be cached by now. This
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * gets caught by the range check
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * above, and so it is a can't-happen
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * at this point.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "reference to bad I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "Multiple links to I=%d, link counts wrong, rerun fsck\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * In theory, this is a can't-happen,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * because shadows don't appear in directory
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * entries. However, an inode might've
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * been reused without a stale directory
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * entry having been cleared, so check
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * for it just in case. We'll check for
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the no-dir-entry shadows in pass3b().
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((act = reply(PASS2B_PROMPT, idesc->id_number)) == 1)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Not doing anything about it, so just try
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * again as whatever the base type was.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * fileerror() invalidated dp. Lint thinks this
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * is unnecessary, but we know better.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* FALLTHROUGH */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * This is encouraging the best-practice of not
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * hard-linking directories. It's legal (see POSIX),
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * but not a good idea. So, don't consider it an
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * instance of corruption, but offer to nuke it.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Same can't-happen argument as in the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * zero-len case above.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "hard-linked directory I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * XXX For nested dirs, this can report
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the same name for both paths.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* FALLTHROUGH */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * There's nothing to do for normal file-like
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * things. Extended attributes come through
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * here as well, though, and for them, .. may point
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * to a file. In this situation we don't want
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * to decrement link count as it was already
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * decremented when the entry was seen in the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * directory it actually lives in.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * is it really an attrdir?
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * if so, then don't do anything.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Rare corner case - the attrdir's ..
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * points to the attrdir itself.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Lets see if we have an orphaned attrdir
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * that thinks it belongs to this file.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Only re-connect it if the current
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * attrdir is 0 or not an attrdir.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "Attribute directory I=%d not "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "attached to file I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "debug: changing i=%d's oeft from %d ",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * This can only be true if we've modified
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * an inode/xattr connection, and we
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * don't keep track of those in the link
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * counts. So, skipping the checks just
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * after this is not a problem.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Don't screw up link counts for directories.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * If we aren't careful we can perform
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * an extra decrement, since the .. of
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * an attrdir could be either a file or a
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * directory. If it's a file then its link
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * should be correct after it is seen when the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * directory it lives in scanned.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "File should NOT be marked as "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "extended attribute\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "changing i=%d's cflags from 0x%x to ",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "File should BE marked as "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "extended attribute\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure it's a file
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * while we're at it.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = (reply(PASS2B_PROMPT, idesc->id_number) == 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (act == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, idesc->id_number, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(idesc->id_number, lncntp[idesc->id_number]++);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Routine to sort disk blocks.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox const struct inoinfo **inpp1 = (const struct inoinfo **)arg1;