diff options
Diffstat (limited to 'fs/proc/self.c')
| -rw-r--r-- | fs/proc/self.c | 59 | 
1 files changed, 59 insertions, 0 deletions
diff --git a/fs/proc/self.c b/fs/proc/self.c new file mode 100644 index 00000000000..aa5cc3bff14 --- /dev/null +++ b/fs/proc/self.c @@ -0,0 +1,59 @@ +#include <linux/proc_fs.h> +#include <linux/sched.h> +#include <linux/namei.h> + +/* + * /proc/self: + */ +static int proc_self_readlink(struct dentry *dentry, char __user *buffer, +			      int buflen) +{ +	struct pid_namespace *ns = dentry->d_sb->s_fs_info; +	pid_t tgid = task_tgid_nr_ns(current, ns); +	char tmp[PROC_NUMBUF]; +	if (!tgid) +		return -ENOENT; +	sprintf(tmp, "%d", tgid); +	return vfs_readlink(dentry,buffer,buflen,tmp); +} + +static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) +{ +	struct pid_namespace *ns = dentry->d_sb->s_fs_info; +	pid_t tgid = task_tgid_nr_ns(current, ns); +	char *name = ERR_PTR(-ENOENT); +	if (tgid) { +		/* 11 for max length of signed int in decimal + NULL term */ +		name = kmalloc(12, GFP_KERNEL); +		if (!name) +			name = ERR_PTR(-ENOMEM); +		else +			sprintf(name, "%d", tgid); +	} +	nd_set_link(nd, name); +	return NULL; +} + +static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd, +				void *cookie) +{ +	char *s = nd_get_link(nd); +	if (!IS_ERR(s)) +		kfree(s); +} + +static const struct inode_operations proc_self_inode_operations = { +	.readlink	= proc_self_readlink, +	.follow_link	= proc_self_follow_link, +	.put_link	= proc_self_put_link, +}; + +void __init proc_self_init(void) +{ +	struct proc_dir_entry *proc_self_symlink; +	mode_t mode; + +	mode = S_IFLNK | S_IRWXUGO; +	proc_self_symlink = proc_create("self", mode, NULL, NULL ); +	proc_self_symlink->proc_iops = &proc_self_inode_operations; +}  | 
