patch-2.1.78 linux/fs/proc/link.c

Next file: linux/fs/proc/proc_devtree.c
Previous file: linux/fs/proc/generic.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.77/linux/fs/proc/link.c linux/fs/proc/link.c
@@ -15,8 +15,8 @@
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 
-static int proc_readlink(struct inode *, char *, int);
-static struct dentry * proc_follow_link(struct inode *, struct dentry *);
+static int proc_readlink(struct dentry *, char *, int);
+static struct dentry * proc_follow_link(struct dentry *, struct dentry *);
 
 /*
  * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke 
@@ -60,8 +60,10 @@
 	NULL			/* permission */
 };
 
-static struct dentry * proc_follow_link(struct inode *inode, struct dentry *base)
+static struct dentry * proc_follow_link(struct dentry *dentry,
+					struct dentry *base)
 {
+	struct inode *inode = dentry->d_inode;
 	struct task_struct *p;
 	struct dentry * result;
 	int ino, pid;
@@ -73,7 +75,7 @@
 	error = permission(inode, MAY_EXEC);
 	result = ERR_PTR(error);
 	if (error)
-		return result;
+		goto out;
 
 	ino = inode->i_ino;
 	pid = ino >> 16;
@@ -82,7 +84,7 @@
 	p = find_task_by_pid(pid);
 	result = ERR_PTR(-ENOENT);
 	if (!p)
-		return result;
+		goto out;
 
 	switch (ino) {
 		case PROC_PID_CWD:
@@ -126,30 +128,56 @@
 				break;
 			}
 	}
+out:
 	return result;
 }
 
-static int proc_readlink(struct inode * inode, char * buffer, int buflen)
+/*
+ * This pretty-prints the pathname of a dentry,
+ * clarifying sockets etc.
+ */
+static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
+{
+	struct inode * inode;
+	char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
+	int len;
+
+	/* Check for special dentries.. */
+	pattern = NULL;
+	inode = dentry->d_inode;
+	if (inode && dentry->d_parent == dentry) {
+		if (inode->i_sock)
+			pattern = "socket:[%lu]";
+		if (inode->i_pipe)
+			pattern = "pipe:[%lu]";
+	}
+	
+	if (pattern) {
+		len = sprintf(tmp, pattern, inode->i_ino);
+		path = tmp;
+	} else {
+		path = d_path(dentry, tmp, PAGE_SIZE);
+		len = tmp + PAGE_SIZE - path;
+	}
+
+	if (len < buflen)
+		buflen = len;
+	dput(dentry);
+	copy_to_user(buffer, path, buflen);
+	free_page((unsigned long)tmp);
+	return buflen;
+}
+
+static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
 {
 	int error;
-	struct dentry * dentry = proc_follow_link(inode, NULL);
 
+	dentry = proc_follow_link(dentry, NULL);
 	error = PTR_ERR(dentry);
 	if (!IS_ERR(dentry)) {
 		error = -ENOENT;
 		if (dentry) {
-			char * tmp = (char*)__get_free_page(GFP_KERNEL), *path;
-			int len;
-
-			path = d_path(dentry, tmp, PAGE_SIZE);
-			len = tmp + PAGE_SIZE - path;
-
-			if (len < buflen)
-				buflen = len;
-			dput(dentry);
-			copy_to_user(buffer, path, buflen);
-			free_page((unsigned long)tmp);
-			error = buflen;
+			error = do_proc_readlink(dentry, buffer, buflen);
 		}
 	}
 	return error;

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