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, /* bmap */
58 NULL, /* truncate */
59 NULL /* permission */
60 };
61
62
63 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)
*/
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)
/* ![[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)
*/
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 }