355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Use is subject to license terms.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/* All Rights Reserved */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Copyright (c) 1980, 1986, 1990 The Regents of the University of California.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * All rights reserved.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox *
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#pragma ident "%Z%%M% %I% %E% SMI"
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <stdio.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <stdlib.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/param.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/types.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/sysmacros.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/mntent.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/fs/ufs_fs.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/vnode.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/fs/ufs_inode.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#define _KERNEL
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <sys/fs/ufs_fsdir.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#undef _KERNEL
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include <string.h>
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#include "fsck.h"
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#define MINDIRSIZE (sizeof (struct dirtemplate))
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxstatic int blksort(const void *, const void *);
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcoxstatic int pass2check(struct inodesc *);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxvoid
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcoxpass2(void)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox{
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct dinode *dp, *dp2, *dpattr;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct inoinfo **inpp, *inp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct inoinfo **inpend;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct inodesc curino;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct inodesc ldesc;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct dinode dino;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox char pathbuf[MAXPATHLEN + 1];
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int found;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int dirtype;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox caddr_t errmsg;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct shadowclientinfo *sci;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox switch (statemap[UFSROOTINO] & ~INDELAYD) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case USTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("ROOT INODE UNALLOCATED");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("ALLOCATE") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("Program terminated.");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (allocdir(UFSROOTINO, UFSROOTINO, 0755, 0) != UFSROOTINO)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("CANNOT ALLOCATE ROOT INODE\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DCLEAR:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("DUPS/BAD IN ROOT INODE");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("REALLOCATE") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox freeino(UFSROOTINO, TI_NOPARENT);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (allocdir(UFSROOTINO, UFSROOTINO,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox 0755, 0) != UFSROOTINO)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("CANNOT ALLOCATE ROOT INODE\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("CONTINUE") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("Program terminated.");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case FSTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case FCLEAR:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case FZLINK:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case SSTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case SCLEAR:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("ROOT INODE NOT DIRECTORY");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("REALLOCATE") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox freeino(UFSROOTINO, TI_NOPARENT);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (allocdir(UFSROOTINO, UFSROOTINO, 0755, 0) !=
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox UFSROOTINO)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("CANNOT ALLOCATE ROOT INODE\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ckfini();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("Program terminated.");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(UFSROOTINO);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_mode &= ~IFMT;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_mode |= IFDIR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DSTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DZLINK:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox default:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("BAD STATE 0x%x FOR ROOT INODE\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[UFSROOTINO]);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[UFSROOTINO] = DFOUND;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp = getinoinfo(UFSROOTINO);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp != NULL && inp->i_dotdot != 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox qsort((void *)inpsort, (size_t)inplast, sizeof (*inpsort), blksort);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memset(&dino, 0, sizeof (struct dinode));
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dino.di_mode = IFDIR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inpend = &inpsort[inplast];
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox for (inpp = inpsort; inpp < inpend; inpp++) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp = *inpp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_isize == 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* != DSTATE also covers case of == USTATE */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (((statemap[inp->i_number] & STMASK) != DSTATE) ||
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ((statemap[inp->i_number] & INCLEAR) == INCLEAR))
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_isize < (offset_t)MINDIRSIZE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox direrror(inp->i_number, "DIRECTORY TOO SHORT");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_isize = (offset_t)roundup(MINDIRSIZE, DIRBLKSIZ);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_size = (u_offset_t)inp->i_isize;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((inp->i_isize & (offset_t)(DIRBLKSIZ - 1)) != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox getpathname(pathbuf, inp->i_number, inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pwarn("DIRECTORY %s: LENGTH %lld NOT MULTIPLE OF %d",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pathbuf, (longlong_t)inp->i_isize, DIRBLKSIZ);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_isize = roundup(inp->i_isize,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (offset_t)DIRBLKSIZ);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (preen || reply("ADJUST") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_size =
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (u_offset_t)roundup(inp->i_isize,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (offset_t)DIRBLKSIZ);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (preen)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf(" (ADJUSTED)\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((dp->di_mode & IFMT) == IFATTRDIR &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (dp->di_cflags & IXATTR) == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pwarn("ATTRIBUTE DIRECTORY I=%d MISSING IXATTR FLAG",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (preen || reply("CORRECT") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_cflags |= IXATTR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (preen)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf(" (CORRECTED)\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = &dino;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_size = (u_offset_t)inp->i_isize;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)&dp->di_db[0], (void *)&inp->i_blks[0],
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_blkssize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox init_inodesc(&curino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox curino.id_type = DATA;
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcox curino.id_func = pass2check;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox curino.id_number = inp->i_number;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox curino.id_parent = inp->i_parent;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox curino.id_fix = DONTKNOW;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) ckinode(dp, &curino, CKI_TRAVERSE);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure we mark attrdirs as DFOUND, since they won't
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * be located during normal scan of standard directories.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (curino.id_parent == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dpattr = ginode(inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((dpattr->di_mode & IFMT) == IFATTRDIR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox for (sci = attrclientinfo; sci != NULL;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox sci = sci->next) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (sci->shadow == inp->i_number) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox curino.id_parent =
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox sci->clients->client[0];
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[inp->i_number] =
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox DFOUND;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_parent =
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox curino.id_parent;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Now that the parents of all directories have been found,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * make another pass to verify the value of ..
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox for (inpp = inpsort; inpp < inpend; inpp++) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp = *inpp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_parent == 0 || inp->i_isize == 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((statemap[inp->i_number] & STMASK) == DCLEAR ||
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[inp->i_number] == USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[inp->i_parent] == DFOUND &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox S_IS_DUNFOUND(statemap[inp->i_number])) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[inp->i_number] = DFOUND |
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (statemap[inp->i_number] & INCLEAR);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_dotdot == inp->i_parent ||
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot == (fsck_ino_t)-1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_dotdot == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = inp->i_parent;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, inp->i_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox found = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirtype = (dp->di_mode & IFMT);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirtype == IFATTRDIR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox for (sci = attrclientinfo;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox sci != NULL;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox sci = sci->next) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (sci->shadow == inp->i_number) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_parent =
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox sci->clients->client[0];
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox found = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * We've already proven there's no "..", so this
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * can't create a duplicate.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (makeentry(inp->i_number, inp->i_parent, "..")) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * is it an orphaned attrdir?
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirtype == IFATTRDIR && found == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Throw it into lost+found
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (linkup(inp->i_number, lfdir,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox NULL) == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pwarn(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "Unable to move attrdir I=%d to lost+found\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox maybe_convert_attrdir_to_dir(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirtype == IFDIR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox lncntp[inp->i_parent], -1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_parent, IFDIR,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[inp->i_parent] !=
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * iscorrupt is
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * already set
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(inp->i_parent,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox lncntp[inp->i_parent]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = (fsck_ino_t)-1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp2 = ginode(inp->i_parent);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((dp2->di_mode & IFMT) == IFATTRDIR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, inp->i_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "BAD INODE NUMBER FOR '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg, lncntp[inp->i_dotdot], 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, inp->i_dotdot, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[inp->i_dotdot] != USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* iscorrupt is already set */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(inp->i_dotdot, lncntp[inp->i_dotdot]++);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg, lncntp[inp->i_parent], -1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, inp->i_parent, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[inp->i_parent] != USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* iscorrupt is already set */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox continue;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(inp->i_parent, lncntp[inp->i_parent]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = inp->i_parent;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) changeino(inp->i_number, "..", inp->i_parent);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Mark all the directories that can be found from the root.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox propagate();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox}
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/*
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 *
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#define PASS2B_PROMPT "REMOVE DIRECTORY ENTRY FROM I=%d"
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxstatic int
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcoxpass2check(struct inodesc *idesc)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox{
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct direct *dirp = idesc->id_dirp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct inodesc ldesc;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct inoinfo *inp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox short reclen, entrysize;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int ret = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int act, update_lncntp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct dinode *dp, *pdirp, *attrdirp;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox caddr_t errmsg;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox struct direct proto;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox char namebuf[MAXPATHLEN + 1];
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox char pathbuf[MAXPATHLEN + 1];
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int isattr;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int pdirtype;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int breakout = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox int dontreconnect;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (idesc->id_entryno != 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox goto chk1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * check for "."
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != idesc->id_number) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = idesc->id_number;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox goto chk1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Build up a new one, and make sure there's room to put
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * it where it belongs.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox direrror(idesc->id_number, "MISSING '.'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_ino = idesc->id_number;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_namlen = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) strcpy(proto.d_name, ".");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox entrysize = DIRSIZ(&proto);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_name);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if ((int)dirp->d_reclen < entrysize) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if ((int)dirp->d_reclen < 2 * entrysize) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 *
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Because we don't touch id_entryno, we end up going
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * through the chk2 tests as well.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_reclen = dirp->d_reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)dirp, (void *)&proto,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (size_t)entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 * space.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox *
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 * as well.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox reclen = dirp->d_reclen - entrysize;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_reclen = entrysize;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)dirp, (void *)&proto,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (size_t)entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_entryno++;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg, lncntp[dirp->d_ino], -1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, dirp->d_ino, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[dirp->d_ino] == USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_reclen += reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (ret);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Create the new empty entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* LINTED pointer cast alignment (entrysize is valid) */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp = (struct direct *)((char *)(dirp) + entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memset((void *)dirp, 0, (size_t)reclen);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_reclen = reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox lncntp[idesc->id_number]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxchk1:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (idesc->id_entryno > 1)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox goto chk2;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp = getinoinfo(idesc->id_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp == NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * This is a can't-happen, since inodes get cached before
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * we get called on them.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcox errexit("pass2check got NULL from getinoinfo at chk1 I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_ino = inp->i_parent;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_namlen = 2;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) strcpy(proto.d_name, "..");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox entrysize = DIRSIZ(&proto);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (idesc->id_entryno == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox reclen = DIRSIZ(dirp);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((int)dirp->d_reclen < reclen + entrysize) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Not enough room for inserting a ".." after
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the "." entry.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox goto chk2;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_reclen = dirp->d_reclen - reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_reclen = reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_entryno++;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino > 0 && dirp->d_ino <= maxino) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Account for the link to ourselves.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg, lncntp[dirp->d_ino], -1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, dirp->d_ino, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[dirp->d_ino] == USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 * result.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_reclen += proto.d_reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (ret);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(dirp->d_ino, lncntp[dirp->d_ino]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure the new entry doesn't get interpreted
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * as having actual content.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* LINTED pointer cast alignment (reclen is valid) */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp = (struct direct *)((char *)(dirp) + reclen);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memset((void *)dirp, 0, (size_t)proto.d_reclen);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_reclen = proto.d_reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "I OUT OF RANGE");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0 && inp->i_dotdot == 0 &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox strcmp(dirp->d_name, "..") == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = dirp->d_ino;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox goto chk2;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
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 dirp->d_name);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = (fsck_ino_t)-1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if ((int)dirp->d_reclen < entrysize) {
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 iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_dotdot = (fsck_ino_t)-1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if (inp->i_parent != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * We know the parent, so fix now.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_ino = inp->i_dotdot = inp->i_parent;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_reclen = dirp->d_reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)dirp, (void *)&proto,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (size_t)entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if (inp->i_number == UFSROOTINO) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Always know parent of root inode, so fix now.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_ino = inp->i_dotdot = inp->i_parent = UFSROOTINO;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox proto.d_reclen = dirp->d_reclen;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) memmove((void *)dirp, (void *)&proto, (size_t)entrysize);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_entryno++;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg, lncntp[dirp->d_ino], -1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, dirp->d_ino, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[dirp->d_ino] == USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(dirp->d_ino, lncntp[dirp->d_ino]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (ret|KEEPON);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxchk2:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino == 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (ret|KEEPON);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_namlen <= 2 &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_name[0] == '.' &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_entryno >= 2) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_namlen == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox direrror(idesc->id_number, "EXTRA '.' ENTRY");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (KEEPON | ret);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_name[1] == '.') {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox direrror(idesc->id_number, "EXTRA '..' ENTRY");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (reply("FIX") == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (KEEPON | ret);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Because of this increment, all tests for skipping . and ..
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * below are ``> 2'', not ``> 1'' as would logically be expected.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_entryno++;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = -1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox update_lncntp = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino > maxino || dirp->d_ino == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = (reply(PASS2B_PROMPT, idesc->id_number) == 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxagain:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox update_lncntp = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox switch (statemap[dirp->d_ino] & ~(INDELAYD)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case USTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (idesc->id_entryno <= 2)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino, "UNALLOCATED");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = (reply(PASS2B_PROMPT, idesc->id_number) == 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DCLEAR:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case FCLEAR:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case SCLEAR:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (idesc->id_entryno <= 2)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[dirp->d_ino] == DCLEAR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errmsg = ((dp->di_mode & IFMT) == IFATTRDIR) ?
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "REFERENCE TO ZERO LENGTH ATTRIBUTE DIRECTORY" :
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "REFERENCE TO ZERO LENGTH DIRECTORY";
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp = getinoinfo(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp == NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcox errexit("pass2check found a zero-len "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "reference to bad I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_parent != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "Multiple links to I=%d, link counts wrong, rerun fsck\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if (statemap[dirp->d_ino] == SCLEAR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errmsg = "ZERO LENGTH SHADOW";
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errmsg = "DUP/BAD";
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino, errmsg);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((act = reply(PASS2B_PROMPT, idesc->id_number)) == 1)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Not doing anything about it, so just try
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * again as whatever the base type was.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox *
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * fileerror() invalidated dp. Lint thinks this
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * is unnecessary, but we know better.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[dirp->d_ino] &= STMASK;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(dirp->d_ino, lncntp[dirp->d_ino] = 0);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox goto again;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DSTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DZLINK:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[idesc->id_number] == DFOUND) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[dirp->d_ino] = DFOUND;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* FALLTHROUGH */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case DFOUND:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp = getinoinfo(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp == NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Same can't-happen argument as in the
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * zero-len case above.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
b9a41fd39fb451c441a90e8959cb2dc2db84b497swilcox errexit("pass2check found bad reference to "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "hard-linked directory I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(idesc->id_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (inp->i_parent != 0 && idesc->id_entryno > 2 &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ((dp->di_mode & IFMT) != IFATTRDIR)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * XXX For nested dirs, this can report
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * the same name for both paths.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox getpathname(pathbuf, idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox getpathname(namebuf, dirp->d_ino, dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pwarn(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "%s IS AN EXTRANEOUS HARD LINK TO DIRECTORY %s\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pathbuf, namebuf);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (preen)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf(" (IGNORED)\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox else if ((act = reply(PASS2B_PROMPT,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number)) == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox update_lncntp = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox broke_dir_link = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((idesc->id_entryno > 2) &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (inp->i_extattr != idesc->id_number)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inp->i_parent = idesc->id_number;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /* FALLTHROUGH */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case FSTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case FZLINK:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pdirp = ginode(idesc->id_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pdirtype = (pdirp->di_mode & IFMT);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox isattr = (dp->di_cflags & IXATTR);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = -1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (pdirtype == IFATTRDIR &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (strcmp(dirp->d_name, "..") == 0)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dontreconnect = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dp->di_oeftflag != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox attrdirp = ginode(dp->di_oeftflag);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * is it really an attrdir?
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * if so, then don't do anything.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((attrdirp->di_mode & IFMT) ==
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox IFATTRDIR)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dontreconnect = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Rare corner case - the attrdir's ..
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * points to the attrdir itself.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (dirp->d_ino == idesc->id_number) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dontreconnect = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox lncntp[idesc->id_number]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((dp->di_oeftflag != idesc->id_number) &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (dontreconnect == 0)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "Attribute directory I=%d not "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "attached to file I=%d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number, dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((act = reply("FIX")) == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (debug)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "debug: changing i=%d's oeft from %d ",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_oeftflag);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_oeftflag =
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (debug)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf("to %d\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_oeftflag);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox registershadowclient(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox &attrclientinfo);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (act > 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (KEEPON | ALTERED);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
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 */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((pdirtype == IFATTRDIR) &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ((dp->di_mode & IFMT) == IFDIR))
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox breakout = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((dp->di_mode & IFMT) != IFDIR)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox breakout = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else if ((pdirtype != IFATTRDIR) ||
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (strcmp(dirp->d_name, ".") != 0)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((pdirtype == IFDIR) && isattr) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "File should NOT be marked as "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "extended attribute\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((act = reply("FIX")) == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (debug)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "changing i=%d's cflags from 0x%x to ",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_cflags);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_cflags &= ~IXATTR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (debug)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (void) printf("0x%x\n",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_cflags);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((dp->di_mode & IFMT) ==
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox IFATTRDIR) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_mode &=
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ~IFATTRDIR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_mode |= IFDIR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pdirp = ginode(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (pdirp->di_oeftflag
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox != 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox pdirp->di_oeftflag = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox } else {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (pdirtype == IFATTRDIR &&
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox (isattr == 0)) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "File should BE marked as "
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox "extended attribute\n");
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if ((act = reply("FIX")) == 1) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp = ginode(
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_cflags |= IXATTR;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox /*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Make sure it's a file
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * while we're at it.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_mode &= ~IFMT;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dp->di_mode |= IFREG;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox inodirty();
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (breakout == 0 || dontreconnect == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(dirp->d_ino,
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox lncntp[dirp->d_ino]--);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (act > 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (KEEPON | ALTERED);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox case SSTATE:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errmsg = "ACL IN DIRECTORY";
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox fileerror(idesc->id_number, dirp->d_ino, errmsg);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox act = (reply(PASS2B_PROMPT, idesc->id_number) == 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox break;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox default:
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox errexit("BAD STATE 0x%x FOR INODE I=%d",
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox statemap[dirp->d_ino], dirp->d_ino);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (act == 0) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox iscorrupt = 1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (act <= 0)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (ret|KEEPON);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (update_lncntp) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_RANGE(errmsg, lncntp[idesc->id_number], 1);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (errmsg != NULL) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox LINK_CLEAR(errmsg, idesc->id_number, IFDIR, &ldesc);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox if (statemap[idesc->id_number] == USTATE) {
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox idesc->id_number = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox ret |= ALTERED;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox TRACK_LNCNTP(idesc->id_number, lncntp[idesc->id_number]++);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox }
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox dirp->d_ino = 0;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return (ret|KEEPON|ALTERED);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox}
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox#undef PASS2B_PROMPT
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox/*
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox * Routine to sort disk blocks.
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox */
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxstatic int
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcoxblksort(const void *arg1, const void *arg2)
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox{
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox const struct inoinfo **inpp1 = (const struct inoinfo **)arg1;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox const struct inoinfo **inpp2 = (const struct inoinfo **)arg2;
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox return ((*inpp1)->i_blks[0] - (*inpp2)->i_blks[0]);
355d6bb5e62a215a9bcf820ac85c1fc62bed2f3fswilcox}