Import 2.3.26pre2
[davej-history.git] / fs / proc / fd.c
blob1862f6f5fd1f6c512d5536d30a2f0bf13907f35b
1 /*
2 * linux/fs/proc/fd.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * proc fd directory handling functions
8 * 01-May-98 Edgar Toernig <froese@gmx.de>
9 * Added support for more than 256 fds.
10 * Limit raised to 32768.
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/file.h>
16 #include <linux/proc_fs.h>
17 #include <linux/stat.h>
19 #include <asm/uaccess.h>
21 static int proc_readfd(struct file *, void *, filldir_t);
22 static struct dentry *proc_lookupfd(struct inode *, struct dentry *);
24 static struct file_operations proc_fd_operations = {
25 NULL, /* lseek - default */
26 NULL, /* read - bad */
27 NULL, /* write - bad */
28 proc_readfd, /* readdir */
29 NULL, /* poll - default */
30 NULL, /* ioctl - default */
31 NULL, /* mmap */
32 NULL, /* no special open code */
33 NULL, /* flush */
34 NULL, /* no special release code */
35 NULL /* can't fsync */
39 * proc directories can do almost nothing..
41 struct inode_operations proc_fd_inode_operations = {
42 &proc_fd_operations, /* default base directory file-ops */
43 NULL, /* create */
44 proc_lookupfd, /* lookup */
45 NULL, /* link */
46 NULL, /* unlink */
47 NULL, /* symlink */
48 NULL, /* mkdir */
49 NULL, /* rmdir */
50 NULL, /* mknod */
51 NULL, /* rename */
52 NULL, /* readlink */
53 NULL, /* follow_link */
54 NULL, /* get_block */
55 NULL, /* readpage */
56 NULL, /* writepage */
57 NULL, /* flushpage */
58 NULL, /* truncate */
59 proc_permission, /* permission */
60 NULL, /* smap */
61 NULL /* revalidate */
65 * NOTE! Normally we'd indicate that a file does not
66 * exist by creating a negative dentry and returning
67 * a successful return code. However, for this case
68 * we do not want to create negative dentries, because
69 * the state of the world can change behind our backs.
71 * Thus just return -ENOENT instead.
73 static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
75 unsigned int ino, pid, fd, c;
76 struct task_struct * p;
77 struct file * file;
78 struct inode *inode;
79 const char *name;
80 int len, err;
82 err = -ENOENT;
83 ino = dir->i_ino;
84 pid = ino >> 16;
85 ino &= 0x0000ffff;
87 if (!pid || ino != PROC_PID_FD)
88 goto out;
90 fd = 0;
91 len = dentry->d_name.len;
92 name = dentry->d_name.name;
93 if (len > 1 && *name == '0') goto out;
94 while (len-- > 0) {
95 c = *name - '0';
96 name++;
97 if (c > 9)
98 goto out;
99 fd *= 10;
100 fd += c;
101 if (fd & 0xffff8000)
102 goto out;
105 read_lock(&tasklist_lock);
106 file = NULL;
107 p = find_task_by_pid(pid);
108 if (p && p->files)
109 file = fcheck_task(p, fd);
110 read_unlock(&tasklist_lock);
113 * File handle is invalid if it is out of range, if the process
114 * has no files (Zombie) if the file is closed, or if its inode
115 * is NULL
118 if (!file)
119 goto out;
121 ino = (pid << 16) + PROC_PID_FD_DIR + fd;
122 inode = proc_get_inode(dir->i_sb, ino, NULL);
123 if (inode) {
124 dentry->d_op = &proc_dentry_operations;
125 d_add(dentry, inode);
126 return NULL;
128 out:
129 return ERR_PTR(err);
132 #define NUMBUF 10
134 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
136 struct inode *inode = filp->f_dentry->d_inode;
137 struct task_struct *p, *tmp;
138 unsigned int fd, pid, ino;
139 int retval;
140 char buf[NUMBUF];
142 retval = 0;
143 ino = inode->i_ino;
144 pid = ino >> 16;
145 ino &= 0x0000ffff;
146 if (ino != PROC_PID_FD)
147 goto out;
149 for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) {
150 ino = inode->i_ino;
151 if (fd)
152 ino = (ino & 0xffff0000) | PROC_PID_INO;
153 if (filldir(dirent, "..", fd+1, fd, ino) < 0)
154 goto out;
157 read_lock(&tasklist_lock);
158 p = find_task_by_pid(pid);
159 if (!p)
160 goto out_unlock;
162 for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++)
164 unsigned int i,j;
166 if (!fcheck_task(p, fd))
167 continue;
169 j = NUMBUF;
170 i = fd;
171 do {
172 j--;
173 buf[j] = '0' + (i % 10);
174 i /= 10;
175 } while (i);
177 /* Drop the task lock, as the filldir function may block */
178 read_unlock(&tasklist_lock);
180 ino = (pid << 16) + PROC_PID_FD_DIR + fd;
181 if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
182 goto out;
184 read_lock(&tasklist_lock);
186 * filldir() might have slept, so we must
187 * re-validate "p". This is fast enough due
188 * to the pidhash
190 tmp = find_task_by_pid(pid);
191 if (p != tmp)
192 break;
194 out_unlock:
195 read_unlock(&tasklist_lock);
197 out:
198 return retval;