- itmp = *ip;
- itmp.i_size = 0;
- for (i = 0; i < NADDR; i++)
- itmp.i_un.i_addr[i] = 0;
- itmp.i_flag |= ICHG|IUPD;
- iupdat(&itmp, &time, &time, 1);
- ip->i_flag &= ~(IUPD|IACC|ICHG);
+ osize = oip->i_size;
+ offset = blkoff(fs, length);
+ if (offset == 0) {
+ oip->i_size = length;
+ } else {
+ lbn = lblkno(fs, length);
+ bn = fsbtodb(fs, bmap(oip, lbn, B_WRITE, offset));
+ if (u.u_error || (long)bn < 0)
+ return;
+ oip->i_size = length;
+ size = blksize(fs, oip, lbn);
+ count = howmany(size, CLBYTES);
+ dev = oip->i_dev;
+ for (i = 0; i < count; i++)
+#ifdef SECSIZE
+ munhash(dev, bn + i * CLBYTES / fs->fs_dbsize);
+#else SECSIZE
+ munhash(dev, bn + i * CLBYTES / DEV_BSIZE);
+#endif SECSIZE
+ bp = bread(dev, bn, size);
+ if (bp->b_flags & B_ERROR) {
+ u.u_error = EIO;
+ oip->i_size = osize;
+ brelse(bp);
+ return;
+ }
+ bzero(bp->b_un.b_addr + offset, (unsigned)(size - offset));
+ bdwrite(bp);
+ }
+ /*
+ * Update 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.
+ */
+ tip = *oip;
+ tip.i_size = osize;
+ 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_flag |= ICHG|IUPD;
+ syncip(oip);