This source file includes following definitions.
- 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
22
23
24
25
26 #undef PLAN9_SEMANTICS
27
28
29
30
31 static struct file_operations proc_fd_link_operations = {
32 NULL,
33 NULL,
34 NULL,
35 NULL,
36 NULL,
37 NULL,
38 NULL,
39 NULL,
40 NULL,
41 NULL
42 };
43
44 struct inode_operations proc_link_inode_operations = {
45 &proc_fd_link_operations,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 NULL,
53 NULL,
54 NULL,
55 proc_readlink,
56 proc_follow_link,
57 NULL,
58 NULL,
59 NULL
60 };
61
62
63 static int proc_follow_link(struct inode * dir, struct inode * inode,
64 int flag, int mode, struct inode ** res_inode)
65 {
66 unsigned int pid, ino;
67 struct task_struct * p;
68 struct inode * new_inode;
69 int i, error;
70
71 *res_inode = NULL;
72 if (dir)
73 iput(dir);
74 if (!inode)
75 return -ENOENT;
76 if ((error = permission(inode, MAY_EXEC)) != 0){
77 iput(inode);
78 return error;
79 }
80 ino = inode->i_ino;
81 pid = ino >> 16;
82 ino &= 0x0000ffff;
83 for (i = 0 ; i < NR_TASKS ; i++)
84 if ((p = task[i]) && p->pid == pid)
85 break;
86 if (i >= NR_TASKS) {
87 iput(inode);
88 return -ENOENT;
89 }
90 new_inode = NULL;
91 switch (ino) {
92 case PROC_PID_CWD:
93 if (!p->fs)
94 break;
95 new_inode = p->fs->pwd;
96 break;
97 case PROC_PID_ROOT:
98 if (!p->fs)
99 break;
100 new_inode = p->fs->root;
101 break;
102 case PROC_PID_EXE: {
103 struct vm_area_struct * vma;
104 if (!p->mm)
105 break;
106 vma = p->mm->mmap;
107 while (vma) {
108 if (vma->vm_flags & VM_EXECUTABLE) {
109 new_inode = vma->vm_inode;
110 break;
111 }
112 vma = vma->vm_next;
113 }
114 break;
115 }
116 default:
117 switch (ino >> 8) {
118 case PROC_PID_FD_DIR:
119 if (!p->files)
120 break;
121 ino &= 0xff;
122 if (ino < NR_OPEN && p->files->fd[ino]) {
123 new_inode = p->files->fd[ino]->f_inode;
124 }
125 break;
126 }
127 }
128 iput(inode);
129 if (!new_inode)
130 return -ENOENT;
131 *res_inode = new_inode;
132 new_inode->i_count++;
133 return 0;
134 }
135
136 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
137 {
138 int i;
139 unsigned int dev,ino;
140 char buf[64];
141
142 if (!S_ISLNK(inode->i_mode)) {
143 iput(inode);
144 return -EINVAL;
145 }
146 i = proc_follow_link(NULL, inode, 0, 0, &inode);
147 if (i)
148 return i;
149 if (!inode)
150 return -EIO;
151 dev = kdev_t_to_nr(inode->i_dev);
152 ino = inode->i_ino;
153 iput(inode);
154 i = sprintf(buf,"[%04x]:%u", dev, ino);
155 if (buflen > i)
156 buflen = i;
157 i = 0;
158 while (i < buflen)
159 put_user(buf[i++],buffer++);
160 return i;
161 }