root/fs/proc/link.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proc_fd_dupf
  2. proc_follow_link
  3. proc_readlink

   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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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,
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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_user(buf[i++],buffer++);
 195         return i;
 196 }

/* [previous][next][first][last][top][bottom][index][help] */