|
|
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.