-}
-
-#define SINGLE 0 /* index of single indirect block */
-#define DOUBLE 1 /* index of double indirect block */
-#define TRIPLE 2 /* index of triple indirect block */
-/*
- * Truncate the inode ip to at most
- * length size. Free affected disk
- * blocks -- the blocks of the file
- * are removed in reverse order.
- *
- * NB: triple indirect blocks are untested.
- */
-itrunc(oip, length)
- struct inode *oip;
- u_long length;
-{
- register i;
- register daddr_t lastblock;
- daddr_t bn, lastiblock[NIADDR];
- register struct fs *fs;
- register struct inode *ip;
- struct inode tip;
- long blocksreleased = 0, nblocks;
- long indirtrunc();
- int level;
-
- if (oip->i_size <= length) {
- oip->i_flag |= ICHG|IUPD;
- iupdat(oip, &time, &time, 1);
- return;
- }
- /*
- * Calculate index into inode's block list of
- * last direct and indirect blocks (if any)
- * which we want to keep. Lastblock is -1 when
- * the file is truncated to 0.
- */
- fs = oip->i_fs;
- lastblock = lblkno(fs, length + fs->fs_bsize - 1) - 1;
- lastiblock[SINGLE] = lastblock - NDADDR;
- lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs);
- lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs);
- nblocks = btodb(fs->fs_bsize);
- /*
- * Update size of file and block pointers
- * on disk before we start freeing blocks.
- * If we crash before free'ing blocks below,
- * the blocks will be returned to the free list.
- * lastiblock values are also normalized to -1
- * for calls to indirtrunc below.
- * (? fsck doesn't check validity of pointers in indirect blocks)
- */
- tip = *oip;
- for (level = TRIPLE; level >= SINGLE; level--)
- if (lastiblock[level] < 0) {
- oip->i_ib[level] = 0;
- lastiblock[level] = -1;
- }
- for (i = NDADDR - 1; i > lastblock; i--)
- oip->i_db[i] = 0;
- oip->i_size = length;
- oip->i_flag |= ICHG|IUPD;
- iupdat(oip, &time, &time, 1);
- ip = &tip;
-
- /*
- * Indirect blocks first.
- */
- for (level = TRIPLE; level >= SINGLE; level--) {
- bn = ip->i_ib[level];
- if (bn != 0) {
- blocksreleased +=
- indirtrunc(ip, bn, lastiblock[level], level);
- if (lastiblock[level] < 0) {
- ip->i_ib[level] = 0;
- free(ip, bn, (off_t)fs->fs_bsize);
- blocksreleased += nblocks;
- }
- }
- if (lastiblock[level] >= 0)
- goto done;