aboutsummaryrefslogtreecommitdiff
path: root/linux/fs/truncate.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/fs/truncate.c')
-rw-r--r--linux/fs/truncate.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/linux/fs/truncate.c b/linux/fs/truncate.c
new file mode 100644
index 0000000..fd82db8
--- /dev/null
+++ b/linux/fs/truncate.c
@@ -0,0 +1,59 @@
+#include <linux/sched.h>
+
+#include <sys/stat.h>
+
+static void free_ind(int dev,int block)
+{
+ struct buffer_head * bh;
+ unsigned short * p;
+ int i;
+
+ if (!block)
+ return;
+ if (bh=bread(dev,block)) {
+ p = (unsigned short *) bh->b_data;
+ for (i=0;i<512;i++,p++)
+ if (*p)
+ free_block(dev,*p);
+ brelse(bh);
+ }
+ free_block(dev,block);
+}
+
+static void free_dind(int dev,int block)
+{
+ struct buffer_head * bh;
+ unsigned short * p;
+ int i;
+
+ if (!block)
+ return;
+ if (bh=bread(dev,block)) {
+ p = (unsigned short *) bh->b_data;
+ for (i=0;i<512;i++,p++)
+ if (*p)
+ free_ind(dev,*p);
+ brelse(bh);
+ }
+ free_block(dev,block);
+}
+
+void truncate(struct m_inode * inode)
+{
+ int i;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
+ return;
+ for (i=0;i<7;i++)
+ if (inode->i_zone[i]) {
+ free_block(inode->i_dev,inode->i_zone[i]);
+ inode->i_zone[i]=0;
+ }
+ free_ind(inode->i_dev,inode->i_zone[7]);
+ free_dind(inode->i_dev,inode->i_zone[8]);
+ inode->i_zone[7] = inode->i_zone[8] = 0;
+ inode->i_size = 0;
+ inode->i_dirt = 1;
+ inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+