FreeBSD/sbin/fsck_ffs/dir.c
/*
 * Attempt to expand the size of a directory
 */
Attempt to expand the size of a directory
Attempt to expand the size of a directory
static int
expanddir(union dinode *dp, char *name)
{
	ufs2_daddr_t lastbn, newblk;
	struct bufarea *bp;
	char *cp, firstblk[DIRBLKSIZ];
	lastbn = lblkno(&sblock, DIP(dp, di_size));
	if (lastbn >= NDADDR - 1 || DIP(dp, di_db[lastbn]) == 0 ||
	    DIP(dp, di_size) == 0)
		return (0);
	if ((newblk = allocblk(sblock.fs_frag)) == 0)
		return (0);
	DIP_SET(dp, di_db[lastbn + 1], DIP(dp, di_db[lastbn]));
	DIP_SET(dp, di_db[lastbn], newblk);
	DIP_SET(dp, di_size, DIP(dp, di_size) + sblock.fs_bsize);
	DIP_SET(dp, di_blocks, DIP(dp, di_blocks) + btodb(sblock.fs_bsize));
	bp = getdirblk(DIP(dp, di_db[lastbn + 1]),
		sblksize(&sblock, DIP(dp, di_size), lastbn + 1));
	if (bp->b_errs)
		goto bad;
	memmove(firstblk, bp->b_un.b_buf, DIRBLKSIZ);
	bp = getdirblk(newblk, sblock.fs_bsize);
	if (bp->b_errs)
		goto bad;
	memmove(bp->b_un.b_buf, firstblk, DIRBLKSIZ);
	for (cp = &bp->b_un.b_buf[DIRBLKSIZ];
	     cp < &bp->b_un.b_buf[sblock.fs_bsize];
	     cp += DIRBLKSIZ)
		memmove(cp, &emptydir, sizeof emptydir);
	dirty(bp);
	bp = getdirblk(DIP(dp, di_db[lastbn + 1]),
		sblksize(&sblock, DIP(dp, di_size), lastbn + 1));
	if (bp->b_errs)
		goto bad;
	memmove(bp->b_un.b_buf, &emptydir, sizeof emptydir);
	pwarn("NO SPACE LEFT IN %s", name);
	if (preen)
		printf(" (EXPANDED)\n");
	else if (reply("EXPAND") == 0)
		goto bad;
	dirty(bp);
	inodirty();
	return (1);
bad:
	DIP_SET(dp, di_db[lastbn], DIP(dp, di_db[lastbn + 1]));
	DIP_SET(dp, di_db[lastbn + 1], 0);
	DIP_SET(dp, di_size, DIP(dp, di_size) - sblock.fs_bsize);
	DIP_SET(dp, di_blocks, DIP(dp, di_blocks) - btodb(sblock.fs_bsize));
	freeblk(newblk, sblock.fs_frag);
	return (0);
}
static int expanddir ( union dinode * dp , char * name ) { ufs2_daddr_t lastbn , newblk ; struct bufarea * bp ; char * cp , firstblk [ DIRBLKSIZ ] ; lastbn = lblkno ( & sblock , DIP ( dp , di_size ) ) ; if ( lastbn >= NDADDR - 1 || DIP ( dp , di_db [ lastbn ] ) == 0 || DIP ( dp , di_size ) == 0 ) return ( 0 ) ; if ( ( newblk = allocblk ( sblock . fs_frag ) ) == 0 ) return ( 0 ) ; DIP_SET ( dp , di_db [ lastbn + 1 ] , DIP ( dp , di_db [ lastbn ] ) ) ; DIP_SET ( dp , di_db [ lastbn ] , newblk ) ; DIP_SET ( dp , di_size , DIP ( dp , di_size ) + sblock . fs_bsize ) ; DIP_SET ( dp , di_blocks , DIP ( dp , di_blocks ) + btodb ( sblock . fs_bsize ) ) ; bp = getdirblk ( DIP ( dp , di_db [ lastbn + 1 ] ) , sblksize ( & sblock , DIP ( dp , di_size ) , lastbn + 1 ) ) ; if ( bp -> b_errs ) goto bad ; memmove ( firstblk , bp -> b_un . b_buf , DIRBLKSIZ ) ; bp = getdirblk ( newblk , sblock . fs_bsize ) ; if ( bp -> b_errs ) goto bad ; memmove ( bp -> b_un . b_buf , firstblk , DIRBLKSIZ ) ; for ( cp = & bp -> b_un . b_buf [ DIRBLKSIZ ] ; cp < & bp -> b_un . b_buf [ sblock . fs_bsize ] ; cp += DIRBLKSIZ ) memmove ( cp , & emptydir , sizeof emptydir ) ; dirty ( bp ) ; bp = getdirblk ( DIP ( dp , di_db [ lastbn + 1 ] ) , sblksize ( & sblock , DIP ( dp , di_size ) , lastbn + 1 ) ) ; if ( bp -> b_errs ) goto bad ; memmove ( bp -> b_un . b_buf , & emptydir , sizeof emptydir ) ; pwarn ( " " , name ) ; if ( preen ) printf ( " \n " ) ; else if ( reply ( " " ) == 0 ) goto bad ; dirty ( bp ) ; inodirty ( ) ; return ( 1 ) ; bad : DIP_SET ( dp , di_db [ lastbn ] , DIP ( dp , di_db [ lastbn + 1 ] ) ) ; DIP_SET ( dp , di_db [ lastbn + 1 ] , 0 ) ; DIP_SET ( dp , di_size , DIP ( dp , di_size ) - sblock . fs_bsize ) ; DIP_SET ( dp , di_blocks , DIP ( dp , di_blocks ) - btodb ( sblock . fs_bsize ) ) ; freeblk ( newblk , sblock . fs_frag ) ; return ( 0 ) ; }
Attempt to expand the size of a directory
Attempt to expand the size of a directory