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