Import 2.1.118
[davej-history.git] / fs / proc / fd.c
blob5409e2d671aa1c25bd2ea3cb0e4f560bc14c696b
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 int 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, /* readpage */
55 NULL, /* writepage */
56 NULL, /* bmap */
57 NULL, /* truncate */
58 proc_permission /* permission */
62 * NOTE! Normally we'd indicate that a file does not
63 * exist by creating a negative dentry and returning
64 * a successful return code. However, for this case
65 * we do not want to create negative dentries, because
66 * the state of the world can change behind our backs.
68 * Thus just return -ENOENT instead.
70 static int proc_lookupfd(struct inode * dir, struct dentry * dentry)
72 unsigned int ino, pid, fd, c;
73 struct task_struct * p;
74 struct file * file;
75 struct inode *inode;
76 const char *name;
77 int len, err;
79 err = -ENOENT;
80 if (!dir)
81 goto out;
82 ino = dir->i_ino;
83 pid = ino >> 16;
84 ino &= 0x0000ffff;
86 if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode))
87 goto out;
89 fd = 0;
90 len = dentry->d_name.len;
91 name = dentry->d_name.name;
92 while (len-- > 0) {
93 c = *name - '0';
94 name++;
95 if (c > 9)
96 goto out;
97 fd *= 10;
98 fd += c;
99 if (fd & 0xffff8000)
100 goto out;
103 read_lock(&tasklist_lock);
104 file = NULL;
105 p = find_task_by_pid(pid);
106 if (p)
107 file = fcheck_task(p, fd);
108 read_unlock(&tasklist_lock);
111 * File handle is invalid if it is out of range, if the process
112 * has no files (Zombie) if the file is closed, or if its inode
113 * is NULL
116 if (!file || !file->f_dentry)
117 goto out;
119 ino = (pid << 16) + PROC_PID_FD_DIR + fd;
120 inode = proc_get_inode(dir->i_sb, ino, NULL);
121 if (inode) {
122 d_add(dentry, inode);
123 err = 0;
125 out:
126 return err;
129 #define NUMBUF 10
131 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
133 struct inode *inode = filp->f_dentry->d_inode;
134 struct task_struct * p, **tarrayp;
135 unsigned int fd, pid, ino;
136 int retval;
137 char buf[NUMBUF];
139 retval = -EBADF;
140 if (!inode || !S_ISDIR(inode->i_mode))
141 goto out;
143 retval = 0;
144 ino = inode->i_ino;
145 pid = ino >> 16;
146 ino &= 0x0000ffff;
147 if (ino != PROC_PID_FD)
148 goto out;
150 for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) {
151 ino = inode->i_ino;
152 if (fd)
153 ino = (ino & 0xffff0000) | PROC_PID_INO;
154 if (filldir(dirent, "..", fd+1, fd, ino) < 0)
155 goto out;
158 read_lock(&tasklist_lock);
159 p = find_task_by_pid(pid);
160 if (!p)
161 goto out_unlock;
162 tarrayp = p->tarray_ptr;
164 for (fd -= 2 ; p->files && fd < p->files->max_fds; fd++, filp->f_pos++)
166 struct file * file = fcheck_task(p, fd);
167 unsigned int i,j;
169 if (!file || !file->f_dentry)
170 continue;
172 j = NUMBUF;
173 i = fd;
174 do {
175 j--;
176 buf[j] = '0' + (i % 10);
177 i /= 10;
178 } while (i);
180 /* Drop the task lock, as the filldir function may block */
181 read_unlock(&tasklist_lock);
183 ino = (pid << 16) + PROC_PID_FD_DIR + fd;
184 if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
185 goto out;
187 read_lock(&tasklist_lock);
188 /* filldir() might have slept, so we must re-validate "p" */
189 if (p != *tarrayp || p->pid != pid)
190 break;
192 out_unlock:
193 read_unlock(&tasklist_lock);
195 out:
196 return retval;