This source file includes following definitions.
- proc_fd_dupf
- proc_follow_link
- proc_readlink
1
2
3
4
5
6
7
8
9 #include <asm/segment.h>
10
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/fs.h>
14 #include <linux/mm.h>
15 #include <linux/proc_fs.h>
16 #include <linux/stat.h>
17
18 static int proc_readlink(struct inode *, char *, int);
19 static int proc_follow_link(struct inode *, struct inode *, int, int,
20 struct inode **);
21 static int proc_fd_dupf(struct inode * inode, struct file * f);
22
23 #define PLAN9_SEMANTICS
24
25
26
27
28 static struct file_operations proc_fd_link_operations = {
29 NULL,
30 NULL,
31 NULL,
32 NULL,
33 NULL,
34 NULL,
35 NULL,
36 proc_fd_dupf,
37 NULL,
38 NULL
39 };
40
41 struct inode_operations proc_link_inode_operations = {
42 &proc_fd_link_operations,
43 NULL,
44 NULL,
45 NULL,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 proc_readlink,
53 proc_follow_link,
54 NULL,
55 NULL,
56 NULL
57 };
58
59
60
61
62
63
64
65
66 static int proc_fd_dupf(struct inode * inode, struct file * f)
67 {
68 unsigned int pid, ino;
69 int i, fd;
70 struct task_struct * p;
71 struct file *new_f;
72
73 for(fd=0 ; fd<NR_OPEN ; fd++)
74 if (current->files->fd[fd] == f)
75 break;
76 if (fd>=NR_OPEN)
77 return -ENOENT;
78
79 ino = inode->i_ino;
80 pid = ino >> 16;
81 ino &= 0x0000ffff;
82
83 for (i = 0 ; i < NR_TASKS ; i++)
84 if ((p = task[i]) && p->pid == pid)
85 break;
86
87 if ((i >= NR_TASKS) ||
88 ((ino >> 8) != 1) || !(new_f = p->files->fd[ino & 0x0ff]))
89 return -ENOENT;
90
91 if (new_f->f_mode && !f->f_mode && 3)
92 return -EPERM;
93
94 new_f->f_count++;
95 current->files->fd[fd] = new_f;
96 if (!--f->f_count)
97 iput(f->f_inode);
98 return 0;
99 }
100
101 static int proc_follow_link(struct inode * dir, struct inode * inode,
102 int flag, int mode, struct inode ** res_inode)
103 {
104 unsigned int pid, ino;
105 struct task_struct * p;
106 struct inode * new_inode;
107 int i, error;
108
109 *res_inode = NULL;
110 if (dir)
111 iput(dir);
112 if (!inode)
113 return -ENOENT;
114 if ((error = permission(inode, MAY_EXEC)) != 0){
115 iput(inode);
116 return error;
117 }
118 ino = inode->i_ino;
119 pid = ino >> 16;
120 ino &= 0x0000ffff;
121 for (i = 0 ; i < NR_TASKS ; i++)
122 if ((p = task[i]) && p->pid == pid)
123 break;
124 if (i >= NR_TASKS) {
125 iput(inode);
126 return -ENOENT;
127 }
128 new_inode = NULL;
129 switch (ino) {
130 case PROC_PID_CWD:
131 if (!p->fs)
132 break;
133 new_inode = p->fs->pwd;
134 break;
135 case PROC_PID_ROOT:
136 if (!p->fs)
137 break;
138 new_inode = p->fs->root;
139 break;
140 case PROC_PID_EXE: {
141 struct vm_area_struct * vma;
142 if (!p->mm)
143 break;
144 vma = p->mm->mmap;
145 while (vma) {
146 if (vma->vm_flags & VM_EXECUTABLE) {
147 new_inode = vma->vm_inode;
148 break;
149 }
150 vma = vma->vm_next;
151 }
152 break;
153 }
154 default:
155 switch (ino >> 8) {
156 case PROC_PID_FD_DIR:
157 if (!p->files)
158 break;
159 ino &= 0xff;
160 if (ino < NR_OPEN && p->files->fd[ino]) {
161 #ifdef PLAN9_SEMANTICS
162 if (dir) {
163 *res_inode = inode;
164 return 0;
165 }
166 #endif
167 new_inode = p->files->fd[ino]->f_inode;
168 }
169 break;
170 }
171 }
172 iput(inode);
173 if (!new_inode)
174 return -ENOENT;
175 *res_inode = new_inode;
176 new_inode->i_count++;
177 return 0;
178 }
179
180 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
181 {
182 int i;
183 unsigned int dev,ino;
184 char buf[64];
185
186 if (!S_ISLNK(inode->i_mode)) {
187 iput(inode);
188 return -EINVAL;
189 }
190 i = proc_follow_link(NULL, inode, 0, 0, &inode);
191 if (i)
192 return i;
193 if (!inode)
194 return -EIO;
195 dev = kdev_t_to_nr(inode->i_dev);
196 ino = inode->i_ino;
197 iput(inode);
198 i = sprintf(buf,"[%04x]:%u", dev, ino);
199 if (buflen > i)
200 buflen = i;
201 i = 0;
202 while (i < buflen)
203 put_user(buf[i++],buffer++);
204 return i;
205 }