xref: /freebsd/sbin/fsck_ffs/dir.c (revision 8fae3551ec46402adf7ab034cf9e02bcbc7ca8ee)
18fae3551SRodney W. Grimes /*
28fae3551SRodney W. Grimes  * Copyright (c) 1980, 1986, 1993
38fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
48fae3551SRodney W. Grimes  *
58fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
68fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
78fae3551SRodney W. Grimes  * are met:
88fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
98fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
108fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
118fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
128fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
138fae3551SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
148fae3551SRodney W. Grimes  *    must display the following acknowledgement:
158fae3551SRodney W. Grimes  *	This product includes software developed by the University of
168fae3551SRodney W. Grimes  *	California, Berkeley and its contributors.
178fae3551SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
188fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
198fae3551SRodney W. Grimes  *    without specific prior written permission.
208fae3551SRodney W. Grimes  *
218fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318fae3551SRodney W. Grimes  * SUCH DAMAGE.
328fae3551SRodney W. Grimes  */
338fae3551SRodney W. Grimes 
348fae3551SRodney W. Grimes #ifndef lint
358fae3551SRodney W. Grimes static char sccsid[] = "@(#)dir.c	8.1 (Berkeley) 6/5/93";
368fae3551SRodney W. Grimes #endif /* not lint */
378fae3551SRodney W. Grimes 
388fae3551SRodney W. Grimes #include <sys/param.h>
398fae3551SRodney W. Grimes #include <sys/time.h>
408fae3551SRodney W. Grimes #include <ufs/ufs/dinode.h>
418fae3551SRodney W. Grimes #include <ufs/ufs/dir.h>
428fae3551SRodney W. Grimes #include <ufs/ffs/fs.h>
438fae3551SRodney W. Grimes #include <stdlib.h>
448fae3551SRodney W. Grimes #include <string.h>
458fae3551SRodney W. Grimes #include "fsck.h"
468fae3551SRodney W. Grimes 
478fae3551SRodney W. Grimes char	*lfname = "lost+found";
488fae3551SRodney W. Grimes int	lfmode = 01777;
498fae3551SRodney W. Grimes struct	dirtemplate emptydir = { 0, DIRBLKSIZ };
508fae3551SRodney W. Grimes struct	dirtemplate dirhead = {
518fae3551SRodney W. Grimes 	0, 12, DT_DIR, 1, ".",
528fae3551SRodney W. Grimes 	0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
538fae3551SRodney W. Grimes };
548fae3551SRodney W. Grimes struct	odirtemplate odirhead = {
558fae3551SRodney W. Grimes 	0, 12, 1, ".",
568fae3551SRodney W. Grimes 	0, DIRBLKSIZ - 12, 2, ".."
578fae3551SRodney W. Grimes };
588fae3551SRodney W. Grimes 
598fae3551SRodney W. Grimes struct direct	*fsck_readdir();
608fae3551SRodney W. Grimes struct bufarea	*getdirblk();
618fae3551SRodney W. Grimes 
628fae3551SRodney W. Grimes /*
638fae3551SRodney W. Grimes  * Propagate connected state through the tree.
648fae3551SRodney W. Grimes  */
658fae3551SRodney W. Grimes propagate()
668fae3551SRodney W. Grimes {
678fae3551SRodney W. Grimes 	register struct inoinfo **inpp, *inp;
688fae3551SRodney W. Grimes 	struct inoinfo **inpend;
698fae3551SRodney W. Grimes 	long change;
708fae3551SRodney W. Grimes 
718fae3551SRodney W. Grimes 	inpend = &inpsort[inplast];
728fae3551SRodney W. Grimes 	do {
738fae3551SRodney W. Grimes 		change = 0;
748fae3551SRodney W. Grimes 		for (inpp = inpsort; inpp < inpend; inpp++) {
758fae3551SRodney W. Grimes 			inp = *inpp;
768fae3551SRodney W. Grimes 			if (inp->i_parent == 0)
778fae3551SRodney W. Grimes 				continue;
788fae3551SRodney W. Grimes 			if (statemap[inp->i_parent] == DFOUND &&
798fae3551SRodney W. Grimes 			    statemap[inp->i_number] == DSTATE) {
808fae3551SRodney W. Grimes 				statemap[inp->i_number] = DFOUND;
818fae3551SRodney W. Grimes 				change++;
828fae3551SRodney W. Grimes 			}
838fae3551SRodney W. Grimes 		}
848fae3551SRodney W. Grimes 	} while (change > 0);
858fae3551SRodney W. Grimes }
868fae3551SRodney W. Grimes 
878fae3551SRodney W. Grimes /*
888fae3551SRodney W. Grimes  * Scan each entry in a directory block.
898fae3551SRodney W. Grimes  */
908fae3551SRodney W. Grimes dirscan(idesc)
918fae3551SRodney W. Grimes 	register struct inodesc *idesc;
928fae3551SRodney W. Grimes {
938fae3551SRodney W. Grimes 	register struct direct *dp;
948fae3551SRodney W. Grimes 	register struct bufarea *bp;
958fae3551SRodney W. Grimes 	int dsize, n;
968fae3551SRodney W. Grimes 	long blksiz;
978fae3551SRodney W. Grimes 	char dbuf[DIRBLKSIZ];
988fae3551SRodney W. Grimes 
998fae3551SRodney W. Grimes 	if (idesc->id_type != DATA)
1008fae3551SRodney W. Grimes 		errexit("wrong type to dirscan %d\n", idesc->id_type);
1018fae3551SRodney W. Grimes 	if (idesc->id_entryno == 0 &&
1028fae3551SRodney W. Grimes 	    (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0)
1038fae3551SRodney W. Grimes 		idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ);
1048fae3551SRodney W. Grimes 	blksiz = idesc->id_numfrags * sblock.fs_fsize;
1058fae3551SRodney W. Grimes 	if (chkrange(idesc->id_blkno, idesc->id_numfrags)) {
1068fae3551SRodney W. Grimes 		idesc->id_filesize -= blksiz;
1078fae3551SRodney W. Grimes 		return (SKIP);
1088fae3551SRodney W. Grimes 	}
1098fae3551SRodney W. Grimes 	idesc->id_loc = 0;
1108fae3551SRodney W. Grimes 	for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) {
1118fae3551SRodney W. Grimes 		dsize = dp->d_reclen;
1128fae3551SRodney W. Grimes 		bcopy((char *)dp, dbuf, (size_t)dsize);
1138fae3551SRodney W. Grimes #		if (BYTE_ORDER == LITTLE_ENDIAN)
1148fae3551SRodney W. Grimes 			if (!newinofmt) {
1158fae3551SRodney W. Grimes 				struct direct *tdp = (struct direct *)dbuf;
1168fae3551SRodney W. Grimes 				u_char tmp;
1178fae3551SRodney W. Grimes 
1188fae3551SRodney W. Grimes 				tmp = tdp->d_namlen;
1198fae3551SRodney W. Grimes 				tdp->d_namlen = tdp->d_type;
1208fae3551SRodney W. Grimes 				tdp->d_type = tmp;
1218fae3551SRodney W. Grimes 			}
1228fae3551SRodney W. Grimes #		endif
1238fae3551SRodney W. Grimes 		idesc->id_dirp = (struct direct *)dbuf;
1248fae3551SRodney W. Grimes 		if ((n = (*idesc->id_func)(idesc)) & ALTERED) {
1258fae3551SRodney W. Grimes #			if (BYTE_ORDER == LITTLE_ENDIAN)
1268fae3551SRodney W. Grimes 				if (!newinofmt && !doinglevel2) {
1278fae3551SRodney W. Grimes 					struct direct *tdp;
1288fae3551SRodney W. Grimes 					u_char tmp;
1298fae3551SRodney W. Grimes 
1308fae3551SRodney W. Grimes 					tdp = (struct direct *)dbuf;
1318fae3551SRodney W. Grimes 					tmp = tdp->d_namlen;
1328fae3551SRodney W. Grimes 					tdp->d_namlen = tdp->d_type;
1338fae3551SRodney W. Grimes 					tdp->d_type = tmp;
1348fae3551SRodney W. Grimes 				}
1358fae3551SRodney W. Grimes #			endif
1368fae3551SRodney W. Grimes 			bp = getdirblk(idesc->id_blkno, blksiz);
1378fae3551SRodney W. Grimes 			bcopy(dbuf, bp->b_un.b_buf + idesc->id_loc - dsize,
1388fae3551SRodney W. Grimes 			    (size_t)dsize);
1398fae3551SRodney W. Grimes 			dirty(bp);
1408fae3551SRodney W. Grimes 			sbdirty();
1418fae3551SRodney W. Grimes 		}
1428fae3551SRodney W. Grimes 		if (n & STOP)
1438fae3551SRodney W. Grimes 			return (n);
1448fae3551SRodney W. Grimes 	}
1458fae3551SRodney W. Grimes 	return (idesc->id_filesize > 0 ? KEEPON : STOP);
1468fae3551SRodney W. Grimes }
1478fae3551SRodney W. Grimes 
1488fae3551SRodney W. Grimes /*
1498fae3551SRodney W. Grimes  * get next entry in a directory.
1508fae3551SRodney W. Grimes  */
1518fae3551SRodney W. Grimes struct direct *
1528fae3551SRodney W. Grimes fsck_readdir(idesc)
1538fae3551SRodney W. Grimes 	register struct inodesc *idesc;
1548fae3551SRodney W. Grimes {
1558fae3551SRodney W. Grimes 	register struct direct *dp, *ndp;
1568fae3551SRodney W. Grimes 	register struct bufarea *bp;
1578fae3551SRodney W. Grimes 	long size, blksiz, fix, dploc;
1588fae3551SRodney W. Grimes 
1598fae3551SRodney W. Grimes 	blksiz = idesc->id_numfrags * sblock.fs_fsize;
1608fae3551SRodney W. Grimes 	bp = getdirblk(idesc->id_blkno, blksiz);
1618fae3551SRodney W. Grimes 	if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 &&
1628fae3551SRodney W. Grimes 	    idesc->id_loc < blksiz) {
1638fae3551SRodney W. Grimes 		dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
1648fae3551SRodney W. Grimes 		if (dircheck(idesc, dp))
1658fae3551SRodney W. Grimes 			goto dpok;
1668fae3551SRodney W. Grimes 		fix = dofix(idesc, "DIRECTORY CORRUPTED");
1678fae3551SRodney W. Grimes 		bp = getdirblk(idesc->id_blkno, blksiz);
1688fae3551SRodney W. Grimes 		dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
1698fae3551SRodney W. Grimes 		dp->d_reclen = DIRBLKSIZ;
1708fae3551SRodney W. Grimes 		dp->d_ino = 0;
1718fae3551SRodney W. Grimes 		dp->d_type = 0;
1728fae3551SRodney W. Grimes 		dp->d_namlen = 0;
1738fae3551SRodney W. Grimes 		dp->d_name[0] = '\0';
1748fae3551SRodney W. Grimes 		if (fix)
1758fae3551SRodney W. Grimes 			dirty(bp);
1768fae3551SRodney W. Grimes 		idesc->id_loc += DIRBLKSIZ;
1778fae3551SRodney W. Grimes 		idesc->id_filesize -= DIRBLKSIZ;
1788fae3551SRodney W. Grimes 		return (dp);
1798fae3551SRodney W. Grimes 	}
1808fae3551SRodney W. Grimes dpok:
1818fae3551SRodney W. Grimes 	if (idesc->id_filesize <= 0 || idesc->id_loc >= blksiz)
1828fae3551SRodney W. Grimes 		return NULL;
1838fae3551SRodney W. Grimes 	dploc = idesc->id_loc;
1848fae3551SRodney W. Grimes 	dp = (struct direct *)(bp->b_un.b_buf + dploc);
1858fae3551SRodney W. Grimes 	idesc->id_loc += dp->d_reclen;
1868fae3551SRodney W. Grimes 	idesc->id_filesize -= dp->d_reclen;
1878fae3551SRodney W. Grimes 	if ((idesc->id_loc % DIRBLKSIZ) == 0)
1888fae3551SRodney W. Grimes 		return (dp);
1898fae3551SRodney W. Grimes 	ndp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
1908fae3551SRodney W. Grimes 	if (idesc->id_loc < blksiz && idesc->id_filesize > 0 &&
1918fae3551SRodney W. Grimes 	    dircheck(idesc, ndp) == 0) {
1928fae3551SRodney W. Grimes 		size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
1938fae3551SRodney W. Grimes 		idesc->id_loc += size;
1948fae3551SRodney W. Grimes 		idesc->id_filesize -= size;
1958fae3551SRodney W. Grimes 		fix = dofix(idesc, "DIRECTORY CORRUPTED");
1968fae3551SRodney W. Grimes 		bp = getdirblk(idesc->id_blkno, blksiz);
1978fae3551SRodney W. Grimes 		dp = (struct direct *)(bp->b_un.b_buf + dploc);
1988fae3551SRodney W. Grimes 		dp->d_reclen += size;
1998fae3551SRodney W. Grimes 		if (fix)
2008fae3551SRodney W. Grimes 			dirty(bp);
2018fae3551SRodney W. Grimes 	}
2028fae3551SRodney W. Grimes 	return (dp);
2038fae3551SRodney W. Grimes }
2048fae3551SRodney W. Grimes 
2058fae3551SRodney W. Grimes /*
2068fae3551SRodney W. Grimes  * Verify that a directory entry is valid.
2078fae3551SRodney W. Grimes  * This is a superset of the checks made in the kernel.
2088fae3551SRodney W. Grimes  */
2098fae3551SRodney W. Grimes dircheck(idesc, dp)
2108fae3551SRodney W. Grimes 	struct inodesc *idesc;
2118fae3551SRodney W. Grimes 	register struct direct *dp;
2128fae3551SRodney W. Grimes {
2138fae3551SRodney W. Grimes 	register int size;
2148fae3551SRodney W. Grimes 	register char *cp;
2158fae3551SRodney W. Grimes 	u_char namlen, type;
2168fae3551SRodney W. Grimes 	int spaceleft;
2178fae3551SRodney W. Grimes 
2188fae3551SRodney W. Grimes 	size = DIRSIZ(!newinofmt, dp);
2198fae3551SRodney W. Grimes 	spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ);
2208fae3551SRodney W. Grimes #	if (BYTE_ORDER == LITTLE_ENDIAN)
2218fae3551SRodney W. Grimes 		if (!newinofmt) {
2228fae3551SRodney W. Grimes 			type = dp->d_namlen;
2238fae3551SRodney W. Grimes 			namlen = dp->d_type;
2248fae3551SRodney W. Grimes 		} else {
2258fae3551SRodney W. Grimes 			namlen = dp->d_namlen;
2268fae3551SRodney W. Grimes 			type = dp->d_type;
2278fae3551SRodney W. Grimes 		}
2288fae3551SRodney W. Grimes #	else
2298fae3551SRodney W. Grimes 		namlen = dp->d_namlen;
2308fae3551SRodney W. Grimes 		type = dp->d_type;
2318fae3551SRodney W. Grimes #	endif
2328fae3551SRodney W. Grimes 	if (dp->d_ino < maxino &&
2338fae3551SRodney W. Grimes 	    dp->d_reclen != 0 &&
2348fae3551SRodney W. Grimes 	    dp->d_reclen <= spaceleft &&
2358fae3551SRodney W. Grimes 	    (dp->d_reclen & 0x3) == 0 &&
2368fae3551SRodney W. Grimes 	    dp->d_reclen >= size &&
2378fae3551SRodney W. Grimes 	    idesc->id_filesize >= size &&
2388fae3551SRodney W. Grimes 	    namlen <= MAXNAMLEN &&
2398fae3551SRodney W. Grimes 	    type <= 15) {
2408fae3551SRodney W. Grimes 		if (dp->d_ino == 0)
2418fae3551SRodney W. Grimes 			return (1);
2428fae3551SRodney W. Grimes 		for (cp = dp->d_name, size = 0; size < namlen; size++)
2438fae3551SRodney W. Grimes 			if (*cp == 0 || (*cp++ == '/'))
2448fae3551SRodney W. Grimes 				return (0);
2458fae3551SRodney W. Grimes 		if (*cp == 0)
2468fae3551SRodney W. Grimes 			return (1);
2478fae3551SRodney W. Grimes 	}
2488fae3551SRodney W. Grimes 	return (0);
2498fae3551SRodney W. Grimes }
2508fae3551SRodney W. Grimes 
2518fae3551SRodney W. Grimes direrror(ino, errmesg)
2528fae3551SRodney W. Grimes 	ino_t ino;
2538fae3551SRodney W. Grimes 	char *errmesg;
2548fae3551SRodney W. Grimes {
2558fae3551SRodney W. Grimes 
2568fae3551SRodney W. Grimes 	fileerror(ino, ino, errmesg);
2578fae3551SRodney W. Grimes }
2588fae3551SRodney W. Grimes 
2598fae3551SRodney W. Grimes fileerror(cwd, ino, errmesg)
2608fae3551SRodney W. Grimes 	ino_t cwd, ino;
2618fae3551SRodney W. Grimes 	char *errmesg;
2628fae3551SRodney W. Grimes {
2638fae3551SRodney W. Grimes 	register struct dinode *dp;
2648fae3551SRodney W. Grimes 	char pathbuf[MAXPATHLEN + 1];
2658fae3551SRodney W. Grimes 
2668fae3551SRodney W. Grimes 	pwarn("%s ", errmesg);
2678fae3551SRodney W. Grimes 	pinode(ino);
2688fae3551SRodney W. Grimes 	printf("\n");
2698fae3551SRodney W. Grimes 	getpathname(pathbuf, cwd, ino);
2708fae3551SRodney W. Grimes 	if (ino < ROOTINO || ino > maxino) {
2718fae3551SRodney W. Grimes 		pfatal("NAME=%s\n", pathbuf);
2728fae3551SRodney W. Grimes 		return;
2738fae3551SRodney W. Grimes 	}
2748fae3551SRodney W. Grimes 	dp = ginode(ino);
2758fae3551SRodney W. Grimes 	if (ftypeok(dp))
2768fae3551SRodney W. Grimes 		pfatal("%s=%s\n",
2778fae3551SRodney W. Grimes 		    (dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE", pathbuf);
2788fae3551SRodney W. Grimes 	else
2798fae3551SRodney W. Grimes 		pfatal("NAME=%s\n", pathbuf);
2808fae3551SRodney W. Grimes }
2818fae3551SRodney W. Grimes 
2828fae3551SRodney W. Grimes adjust(idesc, lcnt)
2838fae3551SRodney W. Grimes 	register struct inodesc *idesc;
2848fae3551SRodney W. Grimes 	short lcnt;
2858fae3551SRodney W. Grimes {
2868fae3551SRodney W. Grimes 	register struct dinode *dp;
2878fae3551SRodney W. Grimes 
2888fae3551SRodney W. Grimes 	dp = ginode(idesc->id_number);
2898fae3551SRodney W. Grimes 	if (dp->di_nlink == lcnt) {
2908fae3551SRodney W. Grimes 		if (linkup(idesc->id_number, (ino_t)0) == 0)
2918fae3551SRodney W. Grimes 			clri(idesc, "UNREF", 0);
2928fae3551SRodney W. Grimes 	} else {
2938fae3551SRodney W. Grimes 		pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname :
2948fae3551SRodney W. Grimes 			((dp->di_mode & IFMT) == IFDIR ? "DIR" : "FILE"));
2958fae3551SRodney W. Grimes 		pinode(idesc->id_number);
2968fae3551SRodney W. Grimes 		printf(" COUNT %d SHOULD BE %d",
2978fae3551SRodney W. Grimes 			dp->di_nlink, dp->di_nlink - lcnt);
2988fae3551SRodney W. Grimes 		if (preen) {
2998fae3551SRodney W. Grimes 			if (lcnt < 0) {
3008fae3551SRodney W. Grimes 				printf("\n");
3018fae3551SRodney W. Grimes 				pfatal("LINK COUNT INCREASING");
3028fae3551SRodney W. Grimes 			}
3038fae3551SRodney W. Grimes 			printf(" (ADJUSTED)\n");
3048fae3551SRodney W. Grimes 		}
3058fae3551SRodney W. Grimes 		if (preen || reply("ADJUST") == 1) {
3068fae3551SRodney W. Grimes 			dp->di_nlink -= lcnt;
3078fae3551SRodney W. Grimes 			inodirty();
3088fae3551SRodney W. Grimes 		}
3098fae3551SRodney W. Grimes 	}
3108fae3551SRodney W. Grimes }
3118fae3551SRodney W. Grimes 
3128fae3551SRodney W. Grimes mkentry(idesc)
3138fae3551SRodney W. Grimes 	struct inodesc *idesc;
3148fae3551SRodney W. Grimes {
3158fae3551SRodney W. Grimes 	register struct direct *dirp = idesc->id_dirp;
3168fae3551SRodney W. Grimes 	struct direct newent;
3178fae3551SRodney W. Grimes 	int newlen, oldlen;
3188fae3551SRodney W. Grimes 
3198fae3551SRodney W. Grimes 	newent.d_namlen = strlen(idesc->id_name);
3208fae3551SRodney W. Grimes 	newlen = DIRSIZ(0, &newent);
3218fae3551SRodney W. Grimes 	if (dirp->d_ino != 0)
3228fae3551SRodney W. Grimes 		oldlen = DIRSIZ(0, dirp);
3238fae3551SRodney W. Grimes 	else
3248fae3551SRodney W. Grimes 		oldlen = 0;
3258fae3551SRodney W. Grimes 	if (dirp->d_reclen - oldlen < newlen)
3268fae3551SRodney W. Grimes 		return (KEEPON);
3278fae3551SRodney W. Grimes 	newent.d_reclen = dirp->d_reclen - oldlen;
3288fae3551SRodney W. Grimes 	dirp->d_reclen = oldlen;
3298fae3551SRodney W. Grimes 	dirp = (struct direct *)(((char *)dirp) + oldlen);
3308fae3551SRodney W. Grimes 	dirp->d_ino = idesc->id_parent;	/* ino to be entered is in id_parent */
3318fae3551SRodney W. Grimes 	if (newinofmt)
3328fae3551SRodney W. Grimes 		dirp->d_type = typemap[idesc->id_parent];
3338fae3551SRodney W. Grimes 	else
3348fae3551SRodney W. Grimes 		dirp->d_type = 0;
3358fae3551SRodney W. Grimes 	dirp->d_reclen = newent.d_reclen;
3368fae3551SRodney W. Grimes 	dirp->d_namlen = newent.d_namlen;
3378fae3551SRodney W. Grimes 	bcopy(idesc->id_name, dirp->d_name, (size_t)dirp->d_namlen + 1);
3388fae3551SRodney W. Grimes 	return (ALTERED|STOP);
3398fae3551SRodney W. Grimes }
3408fae3551SRodney W. Grimes 
3418fae3551SRodney W. Grimes chgino(idesc)
3428fae3551SRodney W. Grimes 	struct inodesc *idesc;
3438fae3551SRodney W. Grimes {
3448fae3551SRodney W. Grimes 	register struct direct *dirp = idesc->id_dirp;
3458fae3551SRodney W. Grimes 
3468fae3551SRodney W. Grimes 	if (bcmp(dirp->d_name, idesc->id_name, (int)dirp->d_namlen + 1))
3478fae3551SRodney W. Grimes 		return (KEEPON);
3488fae3551SRodney W. Grimes 	dirp->d_ino = idesc->id_parent;
3498fae3551SRodney W. Grimes 	if (newinofmt)
3508fae3551SRodney W. Grimes 		dirp->d_type = typemap[idesc->id_parent];
3518fae3551SRodney W. Grimes 	else
3528fae3551SRodney W. Grimes 		dirp->d_type = 0;
3538fae3551SRodney W. Grimes 	return (ALTERED|STOP);
3548fae3551SRodney W. Grimes }
3558fae3551SRodney W. Grimes 
3568fae3551SRodney W. Grimes linkup(orphan, parentdir)
3578fae3551SRodney W. Grimes 	ino_t orphan;
3588fae3551SRodney W. Grimes 	ino_t parentdir;
3598fae3551SRodney W. Grimes {
3608fae3551SRodney W. Grimes 	register struct dinode *dp;
3618fae3551SRodney W. Grimes 	int lostdir;
3628fae3551SRodney W. Grimes 	ino_t oldlfdir;
3638fae3551SRodney W. Grimes 	struct inodesc idesc;
3648fae3551SRodney W. Grimes 	char tempname[BUFSIZ];
3658fae3551SRodney W. Grimes 	extern int pass4check();
3668fae3551SRodney W. Grimes 
3678fae3551SRodney W. Grimes 	bzero((char *)&idesc, sizeof(struct inodesc));
3688fae3551SRodney W. Grimes 	dp = ginode(orphan);
3698fae3551SRodney W. Grimes 	lostdir = (dp->di_mode & IFMT) == IFDIR;
3708fae3551SRodney W. Grimes 	pwarn("UNREF %s ", lostdir ? "DIR" : "FILE");
3718fae3551SRodney W. Grimes 	pinode(orphan);
3728fae3551SRodney W. Grimes 	if (preen && dp->di_size == 0)
3738fae3551SRodney W. Grimes 		return (0);
3748fae3551SRodney W. Grimes 	if (preen)
3758fae3551SRodney W. Grimes 		printf(" (RECONNECTED)\n");
3768fae3551SRodney W. Grimes 	else
3778fae3551SRodney W. Grimes 		if (reply("RECONNECT") == 0)
3788fae3551SRodney W. Grimes 			return (0);
3798fae3551SRodney W. Grimes 	if (lfdir == 0) {
3808fae3551SRodney W. Grimes 		dp = ginode(ROOTINO);
3818fae3551SRodney W. Grimes 		idesc.id_name = lfname;
3828fae3551SRodney W. Grimes 		idesc.id_type = DATA;
3838fae3551SRodney W. Grimes 		idesc.id_func = findino;
3848fae3551SRodney W. Grimes 		idesc.id_number = ROOTINO;
3858fae3551SRodney W. Grimes 		if ((ckinode(dp, &idesc) & FOUND) != 0) {
3868fae3551SRodney W. Grimes 			lfdir = idesc.id_parent;
3878fae3551SRodney W. Grimes 		} else {
3888fae3551SRodney W. Grimes 			pwarn("NO lost+found DIRECTORY");
3898fae3551SRodney W. Grimes 			if (preen || reply("CREATE")) {
3908fae3551SRodney W. Grimes 				lfdir = allocdir(ROOTINO, (ino_t)0, lfmode);
3918fae3551SRodney W. Grimes 				if (lfdir != 0) {
3928fae3551SRodney W. Grimes 					if (makeentry(ROOTINO, lfdir, lfname) != 0) {
3938fae3551SRodney W. Grimes 						if (preen)
3948fae3551SRodney W. Grimes 							printf(" (CREATED)\n");
3958fae3551SRodney W. Grimes 					} else {
3968fae3551SRodney W. Grimes 						freedir(lfdir, ROOTINO);
3978fae3551SRodney W. Grimes 						lfdir = 0;
3988fae3551SRodney W. Grimes 						if (preen)
3998fae3551SRodney W. Grimes 							printf("\n");
4008fae3551SRodney W. Grimes 					}
4018fae3551SRodney W. Grimes 				}
4028fae3551SRodney W. Grimes 			}
4038fae3551SRodney W. Grimes 		}
4048fae3551SRodney W. Grimes 		if (lfdir == 0) {
4058fae3551SRodney W. Grimes 			pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
4068fae3551SRodney W. Grimes 			printf("\n\n");
4078fae3551SRodney W. Grimes 			return (0);
4088fae3551SRodney W. Grimes 		}
4098fae3551SRodney W. Grimes 	}
4108fae3551SRodney W. Grimes 	dp = ginode(lfdir);
4118fae3551SRodney W. Grimes 	if ((dp->di_mode & IFMT) != IFDIR) {
4128fae3551SRodney W. Grimes 		pfatal("lost+found IS NOT A DIRECTORY");
4138fae3551SRodney W. Grimes 		if (reply("REALLOCATE") == 0)
4148fae3551SRodney W. Grimes 			return (0);
4158fae3551SRodney W. Grimes 		oldlfdir = lfdir;
4168fae3551SRodney W. Grimes 		if ((lfdir = allocdir(ROOTINO, (ino_t)0, lfmode)) == 0) {
4178fae3551SRodney W. Grimes 			pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
4188fae3551SRodney W. Grimes 			return (0);
4198fae3551SRodney W. Grimes 		}
4208fae3551SRodney W. Grimes 		if ((changeino(ROOTINO, lfname, lfdir) & ALTERED) == 0) {
4218fae3551SRodney W. Grimes 			pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
4228fae3551SRodney W. Grimes 			return (0);
4238fae3551SRodney W. Grimes 		}
4248fae3551SRodney W. Grimes 		inodirty();
4258fae3551SRodney W. Grimes 		idesc.id_type = ADDR;
4268fae3551SRodney W. Grimes 		idesc.id_func = pass4check;
4278fae3551SRodney W. Grimes 		idesc.id_number = oldlfdir;
4288fae3551SRodney W. Grimes 		adjust(&idesc, lncntp[oldlfdir] + 1);
4298fae3551SRodney W. Grimes 		lncntp[oldlfdir] = 0;
4308fae3551SRodney W. Grimes 		dp = ginode(lfdir);
4318fae3551SRodney W. Grimes 	}
4328fae3551SRodney W. Grimes 	if (statemap[lfdir] != DFOUND) {
4338fae3551SRodney W. Grimes 		pfatal("SORRY. NO lost+found DIRECTORY\n\n");
4348fae3551SRodney W. Grimes 		return (0);
4358fae3551SRodney W. Grimes 	}
4368fae3551SRodney W. Grimes 	(void)lftempname(tempname, orphan);
4378fae3551SRodney W. Grimes 	if (makeentry(lfdir, orphan, tempname) == 0) {
4388fae3551SRodney W. Grimes 		pfatal("SORRY. NO SPACE IN lost+found DIRECTORY");
4398fae3551SRodney W. Grimes 		printf("\n\n");
4408fae3551SRodney W. Grimes 		return (0);
4418fae3551SRodney W. Grimes 	}
4428fae3551SRodney W. Grimes 	lncntp[orphan]--;
4438fae3551SRodney W. Grimes 	if (lostdir) {
4448fae3551SRodney W. Grimes 		if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
4458fae3551SRodney W. Grimes 		    parentdir != (ino_t)-1)
4468fae3551SRodney W. Grimes 			(void)makeentry(orphan, lfdir, "..");
4478fae3551SRodney W. Grimes 		dp = ginode(lfdir);
4488fae3551SRodney W. Grimes 		dp->di_nlink++;
4498fae3551SRodney W. Grimes 		inodirty();
4508fae3551SRodney W. Grimes 		lncntp[lfdir]++;
4518fae3551SRodney W. Grimes 		pwarn("DIR I=%lu CONNECTED. ", orphan);
4528fae3551SRodney W. Grimes 		if (parentdir != (ino_t)-1)
4538fae3551SRodney W. Grimes 			printf("PARENT WAS I=%lu\n", parentdir);
4548fae3551SRodney W. Grimes 		if (preen == 0)
4558fae3551SRodney W. Grimes 			printf("\n");
4568fae3551SRodney W. Grimes 	}
4578fae3551SRodney W. Grimes 	return (1);
4588fae3551SRodney W. Grimes }
4598fae3551SRodney W. Grimes 
4608fae3551SRodney W. Grimes /*
4618fae3551SRodney W. Grimes  * fix an entry in a directory.
4628fae3551SRodney W. Grimes  */
4638fae3551SRodney W. Grimes changeino(dir, name, newnum)
4648fae3551SRodney W. Grimes 	ino_t dir;
4658fae3551SRodney W. Grimes 	char *name;
4668fae3551SRodney W. Grimes 	ino_t newnum;
4678fae3551SRodney W. Grimes {
4688fae3551SRodney W. Grimes 	struct inodesc idesc;
4698fae3551SRodney W. Grimes 
4708fae3551SRodney W. Grimes 	bzero((char *)&idesc, sizeof(struct inodesc));
4718fae3551SRodney W. Grimes 	idesc.id_type = DATA;
4728fae3551SRodney W. Grimes 	idesc.id_func = chgino;
4738fae3551SRodney W. Grimes 	idesc.id_number = dir;
4748fae3551SRodney W. Grimes 	idesc.id_fix = DONTKNOW;
4758fae3551SRodney W. Grimes 	idesc.id_name = name;
4768fae3551SRodney W. Grimes 	idesc.id_parent = newnum;	/* new value for name */
4778fae3551SRodney W. Grimes 	return (ckinode(ginode(dir), &idesc));
4788fae3551SRodney W. Grimes }
4798fae3551SRodney W. Grimes 
4808fae3551SRodney W. Grimes /*
4818fae3551SRodney W. Grimes  * make an entry in a directory
4828fae3551SRodney W. Grimes  */
4838fae3551SRodney W. Grimes makeentry(parent, ino, name)
4848fae3551SRodney W. Grimes 	ino_t parent, ino;
4858fae3551SRodney W. Grimes 	char *name;
4868fae3551SRodney W. Grimes {
4878fae3551SRodney W. Grimes 	struct dinode *dp;
4888fae3551SRodney W. Grimes 	struct inodesc idesc;
4898fae3551SRodney W. Grimes 	char pathbuf[MAXPATHLEN + 1];
4908fae3551SRodney W. Grimes 
4918fae3551SRodney W. Grimes 	if (parent < ROOTINO || parent >= maxino ||
4928fae3551SRodney W. Grimes 	    ino < ROOTINO || ino >= maxino)
4938fae3551SRodney W. Grimes 		return (0);
4948fae3551SRodney W. Grimes 	bzero((char *)&idesc, sizeof(struct inodesc));
4958fae3551SRodney W. Grimes 	idesc.id_type = DATA;
4968fae3551SRodney W. Grimes 	idesc.id_func = mkentry;
4978fae3551SRodney W. Grimes 	idesc.id_number = parent;
4988fae3551SRodney W. Grimes 	idesc.id_parent = ino;	/* this is the inode to enter */
4998fae3551SRodney W. Grimes 	idesc.id_fix = DONTKNOW;
5008fae3551SRodney W. Grimes 	idesc.id_name = name;
5018fae3551SRodney W. Grimes 	dp = ginode(parent);
5028fae3551SRodney W. Grimes 	if (dp->di_size % DIRBLKSIZ) {
5038fae3551SRodney W. Grimes 		dp->di_size = roundup(dp->di_size, DIRBLKSIZ);
5048fae3551SRodney W. Grimes 		inodirty();
5058fae3551SRodney W. Grimes 	}
5068fae3551SRodney W. Grimes 	if ((ckinode(dp, &idesc) & ALTERED) != 0)
5078fae3551SRodney W. Grimes 		return (1);
5088fae3551SRodney W. Grimes 	getpathname(pathbuf, parent, parent);
5098fae3551SRodney W. Grimes 	dp = ginode(parent);
5108fae3551SRodney W. Grimes 	if (expanddir(dp, pathbuf) == 0)
5118fae3551SRodney W. Grimes 		return (0);
5128fae3551SRodney W. Grimes 	return (ckinode(dp, &idesc) & ALTERED);
5138fae3551SRodney W. Grimes }
5148fae3551SRodney W. Grimes 
5158fae3551SRodney W. Grimes /*
5168fae3551SRodney W. Grimes  * Attempt to expand the size of a directory
5178fae3551SRodney W. Grimes  */
5188fae3551SRodney W. Grimes expanddir(dp, name)
5198fae3551SRodney W. Grimes 	register struct dinode *dp;
5208fae3551SRodney W. Grimes 	char *name;
5218fae3551SRodney W. Grimes {
5228fae3551SRodney W. Grimes 	daddr_t lastbn, newblk;
5238fae3551SRodney W. Grimes 	register struct bufarea *bp;
5248fae3551SRodney W. Grimes 	char *cp, firstblk[DIRBLKSIZ];
5258fae3551SRodney W. Grimes 
5268fae3551SRodney W. Grimes 	lastbn = lblkno(&sblock, dp->di_size);
5278fae3551SRodney W. Grimes 	if (lastbn >= NDADDR - 1 || dp->di_db[lastbn] == 0 || dp->di_size == 0)
5288fae3551SRodney W. Grimes 		return (0);
5298fae3551SRodney W. Grimes 	if ((newblk = allocblk(sblock.fs_frag)) == 0)
5308fae3551SRodney W. Grimes 		return (0);
5318fae3551SRodney W. Grimes 	dp->di_db[lastbn + 1] = dp->di_db[lastbn];
5328fae3551SRodney W. Grimes 	dp->di_db[lastbn] = newblk;
5338fae3551SRodney W. Grimes 	dp->di_size += sblock.fs_bsize;
5348fae3551SRodney W. Grimes 	dp->di_blocks += btodb(sblock.fs_bsize);
5358fae3551SRodney W. Grimes 	bp = getdirblk(dp->di_db[lastbn + 1],
5368fae3551SRodney W. Grimes 		(long)dblksize(&sblock, dp, lastbn + 1));
5378fae3551SRodney W. Grimes 	if (bp->b_errs)
5388fae3551SRodney W. Grimes 		goto bad;
5398fae3551SRodney W. Grimes 	bcopy(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
5408fae3551SRodney W. Grimes 	bp = getdirblk(newblk, sblock.fs_bsize);
5418fae3551SRodney W. Grimes 	if (bp->b_errs)
5428fae3551SRodney W. Grimes 		goto bad;
5438fae3551SRodney W. Grimes 	bcopy(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
5448fae3551SRodney W. Grimes 	for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
5458fae3551SRodney W. Grimes 	     cp < &bp->b_un.b_buf[sblock.fs_bsize];
5468fae3551SRodney W. Grimes 	     cp += DIRBLKSIZ)
5478fae3551SRodney W. Grimes 		bcopy((char *)&emptydir, cp, sizeof emptydir);
5488fae3551SRodney W. Grimes 	dirty(bp);
5498fae3551SRodney W. Grimes 	bp = getdirblk(dp->di_db[lastbn + 1],
5508fae3551SRodney W. Grimes 		(long)dblksize(&sblock, dp, lastbn + 1));
5518fae3551SRodney W. Grimes 	if (bp->b_errs)
5528fae3551SRodney W. Grimes 		goto bad;
5538fae3551SRodney W. Grimes 	bcopy((char *)&emptydir, bp->b_un.b_buf, sizeof emptydir);
5548fae3551SRodney W. Grimes 	pwarn("NO SPACE LEFT IN %s", name);
5558fae3551SRodney W. Grimes 	if (preen)
5568fae3551SRodney W. Grimes 		printf(" (EXPANDED)\n");
5578fae3551SRodney W. Grimes 	else if (reply("EXPAND") == 0)
5588fae3551SRodney W. Grimes 		goto bad;
5598fae3551SRodney W. Grimes 	dirty(bp);
5608fae3551SRodney W. Grimes 	inodirty();
5618fae3551SRodney W. Grimes 	return (1);
5628fae3551SRodney W. Grimes bad:
5638fae3551SRodney W. Grimes 	dp->di_db[lastbn] = dp->di_db[lastbn + 1];
5648fae3551SRodney W. Grimes 	dp->di_db[lastbn + 1] = 0;
5658fae3551SRodney W. Grimes 	dp->di_size -= sblock.fs_bsize;
5668fae3551SRodney W. Grimes 	dp->di_blocks -= btodb(sblock.fs_bsize);
5678fae3551SRodney W. Grimes 	freeblk(newblk, sblock.fs_frag);
5688fae3551SRodney W. Grimes 	return (0);
5698fae3551SRodney W. Grimes }
5708fae3551SRodney W. Grimes 
5718fae3551SRodney W. Grimes /*
5728fae3551SRodney W. Grimes  * allocate a new directory
5738fae3551SRodney W. Grimes  */
5748fae3551SRodney W. Grimes allocdir(parent, request, mode)
5758fae3551SRodney W. Grimes 	ino_t parent, request;
5768fae3551SRodney W. Grimes 	int mode;
5778fae3551SRodney W. Grimes {
5788fae3551SRodney W. Grimes 	ino_t ino;
5798fae3551SRodney W. Grimes 	char *cp;
5808fae3551SRodney W. Grimes 	struct dinode *dp;
5818fae3551SRodney W. Grimes 	register struct bufarea *bp;
5828fae3551SRodney W. Grimes 	struct dirtemplate *dirp;
5838fae3551SRodney W. Grimes 
5848fae3551SRodney W. Grimes 	ino = allocino(request, IFDIR|mode);
5858fae3551SRodney W. Grimes 	if (newinofmt)
5868fae3551SRodney W. Grimes 		dirp = &dirhead;
5878fae3551SRodney W. Grimes 	else
5888fae3551SRodney W. Grimes 		dirp = (struct dirtemplate *)&odirhead;
5898fae3551SRodney W. Grimes 	dirp->dot_ino = ino;
5908fae3551SRodney W. Grimes 	dirp->dotdot_ino = parent;
5918fae3551SRodney W. Grimes 	dp = ginode(ino);
5928fae3551SRodney W. Grimes 	bp = getdirblk(dp->di_db[0], sblock.fs_fsize);
5938fae3551SRodney W. Grimes 	if (bp->b_errs) {
5948fae3551SRodney W. Grimes 		freeino(ino);
5958fae3551SRodney W. Grimes 		return (0);
5968fae3551SRodney W. Grimes 	}
5978fae3551SRodney W. Grimes 	bcopy((char *)dirp, bp->b_un.b_buf, sizeof(struct dirtemplate));
5988fae3551SRodney W. Grimes 	for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
5998fae3551SRodney W. Grimes 	     cp < &bp->b_un.b_buf[sblock.fs_fsize];
6008fae3551SRodney W. Grimes 	     cp += DIRBLKSIZ)
6018fae3551SRodney W. Grimes 		bcopy((char *)&emptydir, cp, sizeof emptydir);
6028fae3551SRodney W. Grimes 	dirty(bp);
6038fae3551SRodney W. Grimes 	dp->di_nlink = 2;
6048fae3551SRodney W. Grimes 	inodirty();
6058fae3551SRodney W. Grimes 	if (ino == ROOTINO) {
6068fae3551SRodney W. Grimes 		lncntp[ino] = dp->di_nlink;
6078fae3551SRodney W. Grimes 		cacheino(dp, ino);
6088fae3551SRodney W. Grimes 		return(ino);
6098fae3551SRodney W. Grimes 	}
6108fae3551SRodney W. Grimes 	if (statemap[parent] != DSTATE && statemap[parent] != DFOUND) {
6118fae3551SRodney W. Grimes 		freeino(ino);
6128fae3551SRodney W. Grimes 		return (0);
6138fae3551SRodney W. Grimes 	}
6148fae3551SRodney W. Grimes 	cacheino(dp, ino);
6158fae3551SRodney W. Grimes 	statemap[ino] = statemap[parent];
6168fae3551SRodney W. Grimes 	if (statemap[ino] == DSTATE) {
6178fae3551SRodney W. Grimes 		lncntp[ino] = dp->di_nlink;
6188fae3551SRodney W. Grimes 		lncntp[parent]++;
6198fae3551SRodney W. Grimes 	}
6208fae3551SRodney W. Grimes 	dp = ginode(parent);
6218fae3551SRodney W. Grimes 	dp->di_nlink++;
6228fae3551SRodney W. Grimes 	inodirty();
6238fae3551SRodney W. Grimes 	return (ino);
6248fae3551SRodney W. Grimes }
6258fae3551SRodney W. Grimes 
6268fae3551SRodney W. Grimes /*
6278fae3551SRodney W. Grimes  * free a directory inode
6288fae3551SRodney W. Grimes  */
6298fae3551SRodney W. Grimes freedir(ino, parent)
6308fae3551SRodney W. Grimes 	ino_t ino, parent;
6318fae3551SRodney W. Grimes {
6328fae3551SRodney W. Grimes 	struct dinode *dp;
6338fae3551SRodney W. Grimes 
6348fae3551SRodney W. Grimes 	if (ino != parent) {
6358fae3551SRodney W. Grimes 		dp = ginode(parent);
6368fae3551SRodney W. Grimes 		dp->di_nlink--;
6378fae3551SRodney W. Grimes 		inodirty();
6388fae3551SRodney W. Grimes 	}
6398fae3551SRodney W. Grimes 	freeino(ino);
6408fae3551SRodney W. Grimes }
6418fae3551SRodney W. Grimes 
6428fae3551SRodney W. Grimes /*
6438fae3551SRodney W. Grimes  * generate a temporary name for the lost+found directory.
6448fae3551SRodney W. Grimes  */
6458fae3551SRodney W. Grimes lftempname(bufp, ino)
6468fae3551SRodney W. Grimes 	char *bufp;
6478fae3551SRodney W. Grimes 	ino_t ino;
6488fae3551SRodney W. Grimes {
6498fae3551SRodney W. Grimes 	register ino_t in;
6508fae3551SRodney W. Grimes 	register char *cp;
6518fae3551SRodney W. Grimes 	int namlen;
6528fae3551SRodney W. Grimes 
6538fae3551SRodney W. Grimes 	cp = bufp + 2;
6548fae3551SRodney W. Grimes 	for (in = maxino; in > 0; in /= 10)
6558fae3551SRodney W. Grimes 		cp++;
6568fae3551SRodney W. Grimes 	*--cp = 0;
6578fae3551SRodney W. Grimes 	namlen = cp - bufp;
6588fae3551SRodney W. Grimes 	in = ino;
6598fae3551SRodney W. Grimes 	while (cp > bufp) {
6608fae3551SRodney W. Grimes 		*--cp = (in % 10) + '0';
6618fae3551SRodney W. Grimes 		in /= 10;
6628fae3551SRodney W. Grimes 	}
6638fae3551SRodney W. Grimes 	*cp = '#';
6648fae3551SRodney W. Grimes 	return (namlen);
6658fae3551SRodney W. Grimes }
6668fae3551SRodney W. Grimes 
6678fae3551SRodney W. Grimes /*
6688fae3551SRodney W. Grimes  * Get a directory block.
6698fae3551SRodney W. Grimes  * Insure that it is held until another is requested.
6708fae3551SRodney W. Grimes  */
6718fae3551SRodney W. Grimes struct bufarea *
6728fae3551SRodney W. Grimes getdirblk(blkno, size)
6738fae3551SRodney W. Grimes 	daddr_t blkno;
6748fae3551SRodney W. Grimes 	long size;
6758fae3551SRodney W. Grimes {
6768fae3551SRodney W. Grimes 
6778fae3551SRodney W. Grimes 	if (pdirbp != 0)
6788fae3551SRodney W. Grimes 		pdirbp->b_flags &= ~B_INUSE;
6798fae3551SRodney W. Grimes 	pdirbp = getdatablk(blkno, size);
6808fae3551SRodney W. Grimes 	return (pdirbp);
6818fae3551SRodney W. Grimes }
682