|
|
1.1 root 1: /*
2: * linux/fs/proc/fd.c
3: *
4: * Copyright (C) 1991, 1992 Linus Torvalds
5: *
6: * proc fd directory handling functions
7: */
8:
9: #include <asm/segment.h>
10:
11: #include <linux/errno.h>
12: #include <linux/sched.h>
13: #include <linux/proc_fs.h>
14: #include <linux/stat.h>
15:
16: static int proc_readfd(struct inode *, struct file *, struct dirent *, int);
17: static int proc_lookupfd(struct inode *,const char *,int,struct inode **);
18:
19: static struct file_operations proc_fd_operations = {
20: NULL, /* lseek - default */
21: NULL, /* read - bad */
22: NULL, /* write - bad */
23: proc_readfd, /* readdir */
24: NULL, /* select - default */
25: NULL, /* ioctl - default */
26: NULL, /* no special open code */
27: NULL /* no special release code */
28: };
29:
30: /*
31: * proc directories can do almost nothing..
32: */
33: struct inode_operations proc_fd_inode_operations = {
34: &proc_fd_operations, /* default base directory file-ops */
35: NULL, /* create */
36: proc_lookupfd, /* lookup */
37: NULL, /* link */
38: NULL, /* unlink */
39: NULL, /* symlink */
40: NULL, /* mkdir */
41: NULL, /* rmdir */
42: NULL, /* mknod */
43: NULL, /* rename */
44: NULL, /* readlink */
45: NULL, /* follow_link */
46: NULL, /* bmap */
47: NULL /* truncate */
48: };
49:
50: static int proc_lookupfd(struct inode * dir,const char * name, int len,
51: struct inode ** result)
52: {
53: unsigned int ino, pid, fd, c;
54: struct task_struct * p;
55: int i, dev;
56:
57: *result = NULL;
58: ino = dir->i_ino;
59: pid = ino >> 16;
60: ino &= 0x0000ffff;
61: ino -= 7;
62: if (!dir)
63: return -ENOENT;
64: if (!pid || ino > 1 || !S_ISDIR(dir->i_mode)) {
65: iput(dir);
66: return -ENOENT;
67: }
68: if (!len || (get_fs_byte(name) == '.' && (len == 1 ||
69: (get_fs_byte(name+1) == '.' && len == 2)))) {
70: if (len < 2) {
71: *result = dir;
72: return 0;
73: }
74: if (!(*result = iget(dir->i_dev,(pid << 16)+2))) {
75: iput(dir);
76: return -ENOENT;
77: }
78: iput(dir);
79: return 0;
80: }
81: dev = dir->i_dev;
82: iput(dir);
83: fd = 0;
84: while (len-- > 0) {
85: c = get_fs_byte(name) - '0';
86: name++;
87: if (c > 9) {
88: fd = 0xfffff;
89: break;
90: }
91: fd *= 10;
92: fd += c;
93: if (fd & 0xffff0000) {
94: fd = 0xfffff;
95: break;
96: }
97: }
98: for (i = 0 ; i < NR_TASKS ; i++)
99: if ((p = task[i]) && p->pid == pid)
100: break;
101: if (!pid || i >= NR_TASKS)
102: return -ENOENT;
103: if (!ino) {
104: if (fd >= NR_OPEN || !p->filp[fd] || !p->filp[fd]->f_inode)
105: return -ENOENT;
106: ino = (pid << 16) + 0x100 + fd;
107: } else {
108: if (fd >= p->numlibraries)
109: return -ENOENT;
110: ino = (pid << 16) + 0x200 + fd;
111: }
112: if (!(*result = iget(dev,ino)))
113: return -ENOENT;
114: return 0;
115: }
116:
117: static int proc_readfd(struct inode * inode, struct file * filp,
118: struct dirent * dirent, int count)
119: {
120: struct task_struct * p;
121: unsigned int fd, pid, ino;
122: int i,j;
123:
124: if (!inode || !S_ISDIR(inode->i_mode))
125: return -EBADF;
126: ino = inode->i_ino;
127: pid = ino >> 16;
128: ino &= 0x0000ffff;
129: ino -= 7;
130: if (ino > 1)
131: return 0;
132: while (1) {
133: fd = filp->f_pos;
134: filp->f_pos++;
135: if (fd < 2) {
136: i = j = fd+1;
137: if (!fd)
138: fd = inode->i_ino;
139: else
140: fd = (inode->i_ino & 0xffff0000) | 2;
141: put_fs_long(fd, &dirent->d_ino);
142: put_fs_word(i, &dirent->d_reclen);
143: put_fs_byte(0, i+dirent->d_name);
144: while (i--)
145: put_fs_byte('.', i+dirent->d_name);
146: return j;
147: }
148: fd -= 2;
149: for (i = 1 ; i < NR_TASKS ; i++)
150: if ((p = task[i]) && p->pid == pid)
151: break;
152: if (i >= NR_TASKS)
153: return 0;
154: if (!ino) {
155: if (fd >= NR_OPEN)
156: break;
157: if (!p->filp[fd] || !p->filp[fd]->f_inode)
158: continue;
159: } else
160: if (fd >= p->numlibraries)
161: break;
162: j = 10;
163: i = 1;
164: while (fd >= j) {
165: j *= 10;
166: i++;
167: }
168: j = i;
169: if (!ino)
170: ino = (pid << 16) + 0x100 + fd;
171: else
172: ino = (pid << 16) + 0x200 + fd;
173: put_fs_long(ino, &dirent->d_ino);
174: put_fs_word(i, &dirent->d_reclen);
175: put_fs_byte(0, i+dirent->d_name);
176: while (i--) {
177: put_fs_byte('0'+(fd % 10), i+dirent->d_name);
178: fd /= 10;
179: }
180: return j;
181: }
182: return 0;
183: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.