home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / proc / fd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-29  |  3.6 KB  |  179 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.     if (!dir)
  66.         return -ENOENT;
  67.     sb = dir->i_sb;
  68.     if (!pid || ino != PROC_PID_FD || !S_ISDIR(dir->i_mode)) {
  69.         iput(dir);
  70.         return -ENOENT;
  71.     }
  72.     if (!len || (name[0] == '.' && (len == 1 ||
  73.         (name[1] == '.' && len == 2)))) {
  74.         if (len < 2) {
  75.             *result = dir;
  76.             return 0;
  77.         }
  78.         if (!(*result = iget(sb,(pid << 16)+PROC_PID_INO))) {
  79.             iput(dir);
  80.             return -ENOENT;
  81.         }
  82.         iput(dir);
  83.         return 0;
  84.     }
  85.     iput(dir);
  86.     fd = 0;
  87.     while (len-- > 0) {
  88.         c = *name - '0';
  89.         name++;
  90.         if (c > 9) {
  91.             fd = 0xfffff;
  92.             break;
  93.         }
  94.         fd *= 10;
  95.         fd += c;
  96.         if (fd & 0xffff0000) {
  97.             fd = 0xfffff;
  98.             break;
  99.         }
  100.     }
  101.     for (i = 0 ; i < NR_TASKS ; i++)
  102.         if ((p = task[i]) && p->pid == pid)
  103.             break;
  104.     if (!pid || i >= NR_TASKS)
  105.         return -ENOENT;
  106.  
  107.     if (fd >= NR_OPEN || !p->files->fd[fd] || !p->files->fd[fd]->f_inode)
  108.       return -ENOENT;
  109.  
  110.     ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd;
  111.  
  112.     if (!(*result = iget(sb,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.     if (ino != PROC_PID_FD)
  130.         return 0;
  131.     while (1) {
  132.         fd = filp->f_pos;
  133.         filp->f_pos++;
  134.         if (fd < 2) {
  135.             i = j = fd+1;
  136.             if (!fd)
  137.                 fd = inode->i_ino;
  138.             else
  139.                 fd = (inode->i_ino & 0xffff0000) | PROC_PID_INO;
  140.             put_fs_long(fd, &dirent->d_ino);
  141.             put_fs_word(i, &dirent->d_reclen);
  142.             put_fs_byte(0, i+dirent->d_name);
  143.             while (i--)
  144.                 put_fs_byte('.', i+dirent->d_name);
  145.             return j;
  146.         }
  147.         fd -= 2;
  148.         for (i = 1 ; i < NR_TASKS ; i++)
  149.             if ((p = task[i]) && p->pid == pid)
  150.                 break;
  151.         if (i >= NR_TASKS)
  152.             return 0;
  153.         if (fd >= NR_OPEN)
  154.           break;
  155.  
  156.         if (!p->files->fd[fd] || !p->files->fd[fd]->f_inode)
  157.           continue;
  158.  
  159.         j = 10;
  160.         i = 1;
  161.         while (fd >= j) {
  162.             j *= 10;
  163.             i++;
  164.         }
  165.         j = i;
  166.         ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd;
  167.  
  168.         put_fs_long(ino, &dirent->d_ino);
  169.         put_fs_word(i, &dirent->d_reclen);
  170.         put_fs_byte(0, i+dirent->d_name);
  171.         while (i--) {
  172.             put_fs_byte('0'+(fd % 10), i+dirent->d_name);
  173.             fd /= 10;
  174.         }
  175.         return j;
  176.     }
  177.     return 0;
  178. }
  179.