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 new_inode = p->fs->pwd;
132 break;
133 case PROC_PID_ROOT:
134 new_inode = p->fs->root;
135 break;
136 case PROC_PID_EXE: {
137 struct vm_area_struct * vma = p->mm->mmap;
138 while (vma) {
139 if (vma->vm_flags & VM_EXECUTABLE) {
140 new_inode = vma->vm_inode;
141 break;
142 }
143 vma = vma->vm_next;
144 }
145 break;
146 }
147 default:
148 switch (ino >> 8) {
149 case PROC_PID_FD_DIR:
150 ino &= 0xff;
151 if (ino < NR_OPEN && p->files->fd[ino]) {
152 #ifdef PLAN9_SEMANTICS
153 if (dir) {
154 *res_inode = inode;
155 return 0;
156 }
157 #endif
158 new_inode = p->files->fd[ino]->f_inode;
159 }
160 break;
161 }
162 }
163 iput(inode);
164 if (!new_inode)
165 return -ENOENT;
166 *res_inode = new_inode;
167 new_inode->i_count++;
168 return 0;
169 }
170
171 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
172 {
173 int i;
174 unsigned int dev,ino;
175 char buf[64];
176
177 if (!S_ISLNK(inode->i_mode)) {
178 iput(inode);
179 return -EINVAL;
180 }
181 i = proc_follow_link(NULL, inode, 0, 0, &inode);
182 if (i)
183 return i;
184 if (!inode)
185 return -EIO;
186 dev = inode->i_dev;
187 ino = inode->i_ino;
188 iput(inode);
189 i = sprintf(buf,"[%04x]:%u", dev, ino);
190 if (buflen > i)
191 buflen = i;
192 i = 0;
193 while (i < buflen)
194 put_user(buf[i++],buffer++);
195 return i;
196 }