home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / proc / fd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  4.0 KB  |  199 lines

  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,            /* mmap */
  27.     NULL,            /* no special open code */
  28.     NULL,            /* no special release code */
  29.     NULL            /* can't fsync */
  30. };
  31.  
  32. /*
  33.  * proc directories can do almost nothing..
  34.  */
  35. struct inode_operations proc_fd_inode_operations = {
  36.     &proc_fd_operations,    /* default base directory file-ops */
  37.     NULL,            /* create */
  38.     proc_lookupfd,        /* lookup */
  39.     NULL,            /* link */
  40.     NULL,            /* unlink */
  41.     NULL,            /* symlink */
  42.     NULL,            /* mkdir */
  43.     NULL,            /* rmdir */
  44.     NULL,            /* mknod */
  45.     NULL,            /* rename */
  46.     NULL,            /* readlink */
  47.     NULL,            /* follow_link */
  48.     NULL,            /* bmap */
  49.     NULL,            /* truncate */
  50.     NULL            /* permission */
  51. };
  52.  
  53. static int proc_lookupfd(struct inode * dir,const char * name, int len,
  54.     struct inode ** result)
  55. {
  56.     unsigned int ino, pid, fd, c;
  57.     struct task_struct * p;
  58.     struct super_block * sb;
  59.     int i;
  60.  
  61.     *result = NULL;
  62.     ino = dir->i_ino;
  63.     pid = ino >> 16;
  64.     ino &= 0x0000ffff;
  65.     ino -= 7;
  66.     if (!dir)
  67.         return -ENOENT;
  68.     sb = dir->i_sb;
  69.     if (!pid || ino > 1 || !S_ISDIR(dir->i_mode)) {
  70.         iput(dir);
  71.         return -ENOENT;
  72.     }
  73.     if (!len || (name[0] == '.' && (len == 1 ||
  74.         (name[1] == '.' && len == 2)))) {
  75.         if (len < 2) {
  76.             *result = dir;
  77.             return 0;
  78.         }
  79.         if (!(*result = iget(sb,(pid << 16)+2))) {
  80.             iput(dir);
  81.             return -ENOENT;
  82.         }
  83.         iput(dir);
  84.         return 0;
  85.     }
  86.     iput(dir);
  87.     fd = 0;
  88.     while (len-- > 0) {
  89.         c = *name - '0';
  90.         name++;
  91.         if (c > 9) {
  92.             fd = 0xfffff;
  93.             break;
  94.         }
  95.         fd *= 10;
  96.         fd += c;
  97.         if (fd & 0xffff0000) {
  98.             fd = 0xfffff;
  99.             break;
  100.         }
  101.     }
  102.     for (i = 0 ; i < NR_TASKS ; i++)
  103.         if ((p = task[i]) && p->pid == pid)
  104.             break;
  105.     if (!pid || i >= NR_TASKS)
  106.         return -ENOENT;
  107.     if (!ino) {
  108.         if (fd >= NR_OPEN || !p->filp[fd] || !p->filp[fd]->f_inode)
  109.             return -ENOENT;
  110.         ino = (pid << 16) + 0x100 + fd;
  111.     } else {
  112.         int j = 0;
  113.         struct vm_area_struct * mpnt;
  114.         for (mpnt = p->mmap; mpnt; mpnt = mpnt->vm_next)
  115.             if (mpnt->vm_inode)
  116.                 j++;
  117.         if (fd >= j)
  118.             return -ENOENT;
  119.         ino = (pid << 16) + 0x200 + fd;
  120.     }
  121.     if (!(*result = iget(sb,ino)))
  122.         return -ENOENT;
  123.     return 0;
  124. }
  125.  
  126. static int proc_readfd(struct inode * inode, struct file * filp,
  127.     struct dirent * dirent, int count)
  128. {
  129.     struct task_struct * p;
  130.     unsigned int fd, pid, ino;
  131.     int i,j;
  132.  
  133.     if (!inode || !S_ISDIR(inode->i_mode))
  134.         return -EBADF;
  135.     ino = inode->i_ino;
  136.     pid = ino >> 16;
  137.     ino &= 0x0000ffff;
  138.     ino -= 7;
  139.     if (ino > 1)
  140.         return 0;
  141.     while (1) {
  142.         fd = filp->f_pos;
  143.         filp->f_pos++;
  144.         if (fd < 2) {
  145.             i = j = fd+1;
  146.             if (!fd)
  147.                 fd = inode->i_ino;
  148.             else
  149.                 fd = (inode->i_ino & 0xffff0000) | 2;
  150.             put_fs_long(fd, &dirent->d_ino);
  151.             put_fs_word(i, &dirent->d_reclen);
  152.             put_fs_byte(0, i+dirent->d_name);
  153.             while (i--)
  154.                 put_fs_byte('.', i+dirent->d_name);
  155.             return j;
  156.         }
  157.         fd -= 2;
  158.         for (i = 1 ; i < NR_TASKS ; i++)
  159.             if ((p = task[i]) && p->pid == pid)
  160.                 break;
  161.         if (i >= NR_TASKS)
  162.             return 0;
  163.         if (!ino) {
  164.             if (fd >= NR_OPEN)
  165.                 break;
  166.             if (!p->filp[fd] || !p->filp[fd]->f_inode)
  167.                 continue;
  168.         } else {
  169.             int j = 0;
  170.             struct vm_area_struct * mpnt;
  171.             for (mpnt = p->mmap ; mpnt ; mpnt = mpnt->vm_next)
  172.                 if (mpnt->vm_inode)
  173.                     j++;
  174.             if (fd >= j)
  175.                 break;
  176.         }
  177.         j = 10;
  178.         i = 1;
  179.         while (fd >= j) {
  180.             j *= 10;
  181.             i++;
  182.         }
  183.         j = i;
  184.         if (!ino)
  185.             ino = (pid << 16) + 0x100 + fd;
  186.         else
  187.             ino = (pid << 16) + 0x200 + fd;
  188.         put_fs_long(ino, &dirent->d_ino);
  189.         put_fs_word(i, &dirent->d_reclen);
  190.         put_fs_byte(0, i+dirent->d_name);
  191.         while (i--) {
  192.             put_fs_byte('0'+(fd % 10), i+dirent->d_name);
  193.             fd /= 10;
  194.         }
  195.         return j;
  196.     }
  197.     return 0;
  198. }
  199.