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 / link.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-23  |  4.1 KB  |  197 lines

  1. /*
  2.  *  linux/fs/proc/link.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *
  6.  *  /proc link-file handling code
  7.  */
  8.  
  9. #include <asm/segment.h>
  10.  
  11. #include <linux/errno.h>
  12. #include <linux/sched.h>
  13. #include <linux/fs.h>
  14. #include <linux/mm.h>
  15. #include <linux/proc_fs.h>
  16. #include <linux/stat.h>
  17.  
  18. static int proc_readlink(struct inode *, char *, int);
  19. static int proc_follow_link(struct inode *, struct inode *, int, int,
  20.                 struct inode **);
  21. static int proc_fd_dupf(struct inode * inode, struct file * f);
  22.  
  23. #define PLAN9_SEMANTICS
  24.  
  25. /*
  26.  * links can't do much...
  27.  */
  28. static struct file_operations proc_fd_link_operations = {
  29.     NULL,            /* lseek - default */
  30.     NULL,            /* read - bad */
  31.     NULL,            /* write - bad */
  32.     NULL,            /* readdir - bad */
  33.     NULL,            /* select - default */
  34.     NULL,            /* ioctl - default */
  35.     NULL,            /* mmap */
  36.     proc_fd_dupf,        /* very special open code */
  37.     NULL,            /* no special release code */
  38.     NULL            /* can't fsync */
  39. };
  40.  
  41. struct inode_operations proc_link_inode_operations = {
  42.     &proc_fd_link_operations,/* file-operations */
  43.     NULL,            /* create */
  44.     NULL,            /* lookup */
  45.     NULL,            /* link */
  46.     NULL,            /* unlink */
  47.     NULL,            /* symlink */
  48.     NULL,            /* mkdir */
  49.     NULL,            /* rmdir */
  50.     NULL,            /* mknod */
  51.     NULL,            /* rename */
  52.     proc_readlink,        /* readlink */
  53.     proc_follow_link,    /* follow_link */
  54.     NULL,            /* bmap */
  55.     NULL,            /* truncate */
  56.     NULL            /* permission */
  57. };
  58.  
  59. /*
  60.  * This open routine is somewhat of a hack.... what we are doing is
  61.  * looking up the file structure of the newly opened proc fd file, and
  62.  * replacing it with the actual file structure of the process's file
  63.  * descriptor.  This allows plan 9 semantics, so that the returned
  64.  * file descriptor is an dup of the target file descriptor.
  65.  */
  66. static int proc_fd_dupf(struct inode * inode, struct file * f)
  67. {
  68.     unsigned int pid, ino;
  69.     int    i, fd;
  70.     struct task_struct * p;
  71.     struct file *new_f;
  72.     
  73.     for(fd=0 ; fd<NR_OPEN ; fd++)
  74.         if (current->files->fd[fd] == f)
  75.             break;
  76.     if (fd>=NR_OPEN)
  77.         return -ENOENT;    /* should never happen */
  78.  
  79.     ino = inode->i_ino;
  80.     pid = ino >> 16;
  81.     ino &= 0x0000ffff;
  82.  
  83.     for (i = 0 ; i < NR_TASKS ; i++)
  84.         if ((p = task[i]) && p->pid == pid)
  85.             break;
  86.  
  87.     if ((i >= NR_TASKS) ||
  88.         ((ino >> 8) != 1) || !(new_f = p->files->fd[ino & 0x0ff]))
  89.         return -ENOENT;
  90.  
  91.     if (new_f->f_mode && !f->f_mode && 3)
  92.         return -EPERM;
  93.  
  94.     new_f->f_count++;
  95.     current->files->fd[fd] = new_f;
  96.     if (!--f->f_count)
  97.         iput(f->f_inode);
  98.     return 0;
  99. }
  100.  
  101. static int proc_follow_link(struct inode * dir, struct inode * inode,
  102.     int flag, int mode, struct inode ** res_inode)
  103. {
  104.     unsigned int pid, ino;
  105.     struct task_struct * p;
  106.     struct inode * new_inode;
  107.     int i, error;
  108.  
  109.     *res_inode = NULL;
  110.     if (dir)
  111.         iput(dir);
  112.     if (!inode)
  113.         return -ENOENT;
  114.     if ((error = permission(inode, MAY_EXEC)) != 0){
  115.         iput(inode);
  116.         return error;
  117.     }
  118.     ino = inode->i_ino;
  119.     pid = ino >> 16;
  120.     ino &= 0x0000ffff;
  121.     for (i = 0 ; i < NR_TASKS ; i++)
  122.         if ((p = task[i]) && p->pid == pid)
  123.             break;
  124.     if (i >= NR_TASKS) {
  125.         iput(inode);
  126.         return -ENOENT;
  127.     }
  128.     new_inode = NULL;
  129.     switch (ino) {
  130.         case PROC_PID_CWD:
  131.             new_inode = p->fs->pwd;
  132.             break;
  133.         case PROC_PID_ROOT:
  134.             new_inode = p->fs->root;
  135.             break;
  136.         case PROC_PID_EXE: {
  137.             struct vm_area_struct * vma = p->mm->mmap;
  138.             while (vma) {
  139.                 if (vma->vm_flags & VM_EXECUTABLE) {
  140.                     new_inode = vma->vm_inode;
  141.                     break;
  142.                 }
  143.                 vma = vma->vm_next;
  144.             }
  145.             break;
  146.         }
  147.         default:
  148.             switch (ino >> 8) {
  149.             case PROC_PID_FD_DIR:
  150.                 ino &= 0xff;
  151.                 if (ino < NR_OPEN && p->files->fd[ino]) {
  152. #ifdef PLAN9_SEMANTICS
  153.                     if (dir) {
  154.                         *res_inode = inode;
  155.                         return 0;
  156.                     }
  157. #endif
  158.                     new_inode = p->files->fd[ino]->f_inode;
  159.                 }
  160.                 break;
  161.             }
  162.     }
  163.     iput(inode);
  164.     if (!new_inode)
  165.         return -ENOENT;
  166.     *res_inode = new_inode;
  167.     new_inode->i_count++;
  168.     return 0;
  169. }
  170.  
  171. static int proc_readlink(struct inode * inode, char * buffer, int buflen)
  172. {
  173.     int i;
  174.     unsigned int dev,ino;
  175.     char buf[64];
  176.  
  177.     if (!S_ISLNK(inode->i_mode)) {
  178.         iput(inode);
  179.         return -EINVAL;
  180.     }
  181.     i = proc_follow_link(NULL, inode, 0, 0, &inode);
  182.     if (i)
  183.         return i;
  184.     if (!inode)
  185.         return -EIO;
  186.     dev = inode->i_dev;
  187.     ino = inode->i_ino;
  188.     iput(inode);
  189.     i = sprintf(buf,"[%04x]:%u", dev, ino);
  190.     if (buflen > i)
  191.         buflen = i;
  192.     i = 0;
  193.     while (i < buflen)
  194.         put_fs_byte(buf[i++],buffer++);
  195.     return i;
  196. }
  197.