1 /*
2 * linux/fs/proc/link.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 *
6 * /proc link-file handling code
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 * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke
24 * when the files[] array was updated only after the open code
25 */
26 #undef PLAN9_SEMANTICS
27
28 /*
29 * links can't do much...
30 */
31 static struct file_operations proc_fd_link_operations = {
32 NULL, /* lseek - default */
33 NULL, /* read - bad */
34 NULL, /* write - bad */
35 NULL, /* readdir - bad */
36 NULL, /* select - default */
37 NULL, /* ioctl - default */
38 NULL, /* mmap */
39 NULL, /* very special open code */
40 NULL, /* no special release code */
41 NULL /* can't fsync */
42 };
43
44 struct inode_operations proc_link_inode_operations = {
45 &proc_fd_link_operations,/* file-operations */
46 NULL, /* create */
47 NULL, /* lookup */
48 NULL, /* link */
49 NULL, /* unlink */
50 NULL, /* symlink */
51 NULL, /* mkdir */
52 NULL, /* rmdir */
53 NULL, /* mknod */
54 NULL, /* rename */
55 proc_readlink, /* readlink */
56 proc_follow_link, /* follow_link */
57 NULL, /* readpage */
58 NULL, /* writepage */
59 NULL, /* bmap */
60 NULL, /* truncate */
61 NULL /* permission */
62 };
63
64
65 static int proc_follow_link(struct inode * dir, struct inode * inode,
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
66 int flag, int mode, struct inode ** res_inode)
67 {
68 unsigned int pid, ino;
69 struct task_struct * p;
70 struct inode * new_inode;
71 int i, error;
72
73 *res_inode = NULL;
74 if (dir)
75 iput(dir);
76 if (!inode)
77 return -ENOENT;
78 if ((error = permission(inode, MAY_EXEC)) != 0){
79 iput(inode);
80 return error;
81 }
82 ino = inode->i_ino;
83 pid = ino >> 16;
84 ino &= 0x0000ffff;
85 for (i = 0 ; i < NR_TASKS ; i++)
86 if ((p = task[i]) && p->pid == pid)
87 break;
88 if (i >= NR_TASKS) {
89 iput(inode);
90 return -ENOENT;
91 }
92 new_inode = NULL;
93 switch (ino) {
94 case PROC_PID_CWD:
95 if (!p->fs)
96 break;
97 new_inode = p->fs->pwd;
98 break;
99 case PROC_PID_ROOT:
100 if (!p->fs)
101 break;
102 new_inode = p->fs->root;
103 break;
104 case PROC_PID_EXE: {
105 struct vm_area_struct * vma;
106 if (!p->mm)
107 break;
108 vma = p->mm->mmap;
109 while (vma) {
110 if (vma->vm_flags & VM_EXECUTABLE) {
111 new_inode = vma->vm_inode;
112 break;
113 }
114 vma = vma->vm_next;
115 }
116 break;
117 }
118 default:
119 switch (ino >> 8) {
120 case PROC_PID_FD_DIR:
121 if (!p->files)
122 break;
123 ino &= 0xff;
124 if (ino < NR_OPEN && p->files->fd[ino]) {
125 new_inode = p->files->fd[ino]->f_inode;
126 }
127 break;
128 }
129 }
130 iput(inode);
131 if (!new_inode)
132 return -ENOENT;
133 *res_inode = new_inode;
134 new_inode->i_count++;
135 return 0;
136 }
137
138 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
139 {
140 int i;
141 unsigned int dev,ino;
142 char buf[64];
143
144 if (!S_ISLNK(inode->i_mode)) {
145 iput(inode);
146 return -EINVAL;
147 }
148 i = proc_follow_link(NULL, inode, 0, 0, &inode);
149 if (i)
150 return i;
151 if (!inode)
152 return -EIO;
153 dev = kdev_t_to_nr(inode->i_dev);
154 ino = inode->i_ino;
155 iput(inode);
156 i = sprintf(buf,"[%04x]:%u", dev, ino);
157 if (buflen > i)
158 buflen = i;
159 i = 0;
160 while (i < buflen)
161 put_user(buf[i++],buffer++);
162 return i;
163 }