patch-2.1.44 linux/fs/ext2/symlink.c

Next file: linux/fs/fat/misc.c
Previous file: linux/fs/ext2/super.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.43/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
@@ -25,6 +25,7 @@
 #include <linux/stat.h>
 
 static int ext2_readlink (struct inode *, char *, int);
+static struct dentry *ext2_follow_link(struct inode *, struct dentry *);
 
 /*
  * symlinks can't do much...
@@ -41,6 +42,7 @@
 	NULL,			/* mknod */
 	NULL,			/* rename */
 	ext2_readlink,		/* readlink */
+	ext2_follow_link,	/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -49,26 +51,50 @@
 	NULL			/* smap */
 };
 
+static struct dentry * ext2_follow_link(struct inode * inode, struct dentry *base)
+{
+	int error;
+	struct buffer_head * bh = NULL;
+	char * link;
+
+	link = (char *) inode->u.ext2_i.i_data;
+	if (inode->i_blocks) {
+		if (!(bh = ext2_bread (inode, 0, 0, &error))) {
+			dput(base);
+			return ERR_PTR(-EIO);
+		}
+		link = bh->b_data;
+	}
+	if (!IS_RDONLY(inode)) {
+		inode->i_atime = CURRENT_TIME;
+		inode->i_dirt = 1;
+	}
+	base = lookup_dentry(link, base, 1);
+	if (bh)
+		brelse(bh);
+	return base;
+}
+
 static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
 {
 	struct buffer_head * bh = NULL;
 	char * link;
-	int i, err;
+	int i;
 
 	if (buflen > inode->i_sb->s_blocksize - 1)
 		buflen = inode->i_sb->s_blocksize - 1;
+
+	link = (char *) inode->u.ext2_i.i_data;
 	if (inode->i_blocks) {
+		int err;
 		bh = ext2_bread (inode, 0, 0, &err);
 		if (!bh) {
-			iput (inode);
 			if(err < 0) /* indicate type of error */
 				return err;
 			return 0;
 		}
 		link = bh->b_data;
 	}
-	else
-		link = (char *) inode->u.ext2_i.i_data;
 
 	i = 0;
 	while (i < buflen && link[i])
@@ -79,7 +105,6 @@
 		inode->i_atime = CURRENT_TIME;
 		inode->i_dirt = 1;
 	}
-	iput (inode);
 	if (bh)
 		brelse (bh);
 	return i;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov