Import 2.3.26pre2
[davej-history.git] / fs / proc / link.c
blob69d435600505983a3fb91f5083796476803f98a3
1 /*
2 * linux/fs/proc/link.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * /proc link-file handling code
7 */
9 #include <asm/uaccess.h>
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/mm.h>
14 #include <linux/fs.h>
15 #include <linux/file.h>
16 #include <linux/proc_fs.h>
17 #include <linux/stat.h>
19 static int proc_readlink(struct dentry *, char *, int);
20 static struct dentry * proc_follow_link(struct dentry *, struct dentry *, unsigned int);
23 * links can't do much...
25 static struct file_operations proc_fd_link_operations = {
26 NULL, /* lseek - default */
27 NULL, /* read - bad */
28 NULL, /* write - bad */
29 NULL, /* readdir - bad */
30 NULL, /* poll - default */
31 NULL, /* ioctl - default */
32 NULL, /* mmap */
33 NULL, /* very special open code */
34 NULL, /* flush */
35 NULL, /* no special release code */
36 NULL /* can't fsync */
39 struct inode_operations proc_link_inode_operations = {
40 &proc_fd_link_operations,/* file-operations */
41 NULL, /* create */
42 NULL, /* lookup */
43 NULL, /* link */
44 NULL, /* unlink */
45 NULL, /* symlink */
46 NULL, /* mkdir */
47 NULL, /* rmdir */
48 NULL, /* mknod */
49 NULL, /* rename */
50 proc_readlink, /* readlink */
51 proc_follow_link, /* follow_link */
52 NULL, /* get_block */
53 NULL, /* readpage */
54 NULL, /* writepage */
55 NULL, /* flushpage */
56 NULL, /* truncate */
57 proc_permission, /* permission */
58 NULL, /* smap */
59 NULL /* revalidate */
62 static struct dentry * proc_follow_link(struct dentry *dentry,
63 struct dentry *base,
64 unsigned int follow)
66 struct inode *inode = dentry->d_inode;
67 struct task_struct *p;
68 struct dentry * result;
69 int ino, pid;
70 int error;
72 /* We don't need a base pointer in the /proc filesystem */
73 dput(base);
75 error = permission(inode, MAY_EXEC);
76 result = ERR_PTR(error);
77 if (error)
78 goto out;
80 ino = inode->i_ino;
81 pid = ino >> 16;
82 ino &= 0x0000ffff;
84 result = ERR_PTR(-ENOENT);
86 switch (ino) {
87 case PROC_PID_CWD:
88 read_lock(&tasklist_lock);
89 p = find_task_by_pid(pid);
90 if (p && p->fs && p->fs->pwd)
91 result = dget(p->fs->pwd);
92 read_unlock(&tasklist_lock);
93 break;
95 case PROC_PID_ROOT:
96 read_lock(&tasklist_lock);
97 p = find_task_by_pid(pid);
98 if (p && p->fs && p->fs->root)
99 result = dget(p->fs->root);
100 read_unlock(&tasklist_lock);
101 break;
103 case PROC_PID_EXE: {
104 struct mm_struct *mm = NULL;
105 struct vm_area_struct * vma;
106 read_lock(&tasklist_lock);
107 p = find_task_by_pid(pid);
108 if (p)
109 mm = p->mm;
110 if (mm)
111 atomic_inc(&mm->mm_users);
112 read_unlock(&tasklist_lock);
113 if (!mm)
114 break;
115 down(&mm->mmap_sem);
116 vma = mm->mmap;
117 while (vma) {
118 if ((vma->vm_flags & VM_EXECUTABLE) &&
119 vma->vm_file) {
120 result = dget(vma->vm_file->f_dentry);
121 break;
123 vma = vma->vm_next;
125 up(&mm->mmap_sem);
126 mmput(mm);
127 break;
129 default:
130 if (ino & PROC_PID_FD_DIR) {
131 struct file * file;
132 struct files_struct *files = NULL;
133 read_lock(&tasklist_lock);
134 p = find_task_by_pid(pid);
135 if (p)
136 files = p->files;
137 read_unlock(&tasklist_lock);
138 if (!files)
139 break;
140 ino &= 0x7fff;
141 read_lock(&files->file_lock);
142 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
143 if (ino < files->max_fds &&
144 (file = files->fd[ino]) && file->f_dentry)
145 result = dget(file->f_dentry);
146 read_unlock(&p->files->file_lock);
149 out:
150 return result;
154 * This pretty-prints the pathname of a dentry,
155 * clarifying sockets etc.
157 static int do_proc_readlink(struct dentry *dentry, char * buffer, int buflen)
159 struct inode * inode;
160 char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
161 int len;
163 if(tmp==NULL)
164 return -ENOMEM;
166 /* Check for special dentries.. */
167 pattern = NULL;
168 inode = dentry->d_inode;
169 if (inode && IS_ROOT(dentry)) {
170 if (S_ISSOCK(inode->i_mode))
171 pattern = "socket:[%lu]";
172 if (S_ISFIFO(inode->i_mode))
173 pattern = "pipe:[%lu]";
176 if (pattern) {
177 len = sprintf(tmp, pattern, inode->i_ino);
178 path = tmp;
179 } else {
180 path = d_path(dentry, tmp, PAGE_SIZE);
181 len = tmp + PAGE_SIZE - 1 - path;
184 if (len < buflen)
185 buflen = len;
186 dput(dentry);
187 copy_to_user(buffer, path, buflen);
188 free_page((unsigned long)tmp);
189 return buflen;
192 static int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
194 int error;
196 dentry = proc_follow_link(dentry, NULL, 1);
197 error = PTR_ERR(dentry);
198 if (!IS_ERR(dentry)) {
199 error = -ENOENT;
200 if (dentry) {
201 error = do_proc_readlink(dentry, buffer, buflen);
204 return error;