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 a 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                         if (!p->fs)
 132                                 break;
 133                         new_inode = p->fs->pwd;
 134                         break;
 135                 case PROC_PID_ROOT:
 136                         if (!p->fs)
 137                                 break;
 138                         new_inode = p->fs->root;
 139                         break;
 140                 case PROC_PID_EXE: {
 141                         struct vm_area_struct * vma;
 142                         if (!p->mm)
 143                                 break;
 144                         vma = p->mm->mmap;
 145                         while (vma) {
 146                                 if (vma->vm_flags & VM_EXECUTABLE) {
 147                                         new_inode = vma->vm_inode;
 148                                         break;
 149                                 }
 150                                 vma = vma->vm_next;
 151                         }
 152                         break;
 153                 }
 154                 default:
 155                         switch (ino >> 8) {
 156                         case PROC_PID_FD_DIR:
 157                                 if (!p->files)
 158                                         break;
 159                                 ino &= 0xff;
 160                                 if (ino < NR_OPEN && p->files->fd[ino]) {
 161 #ifdef PLAN9_SEMANTICS
 162                                         if (dir) {
 163                                                 *res_inode = inode;
 164                                                 return 0;
 165                                         }
 166 #endif
 167                                         new_inode = p->files->fd[ino]->f_inode;
 168                                 }
 169                                 break;
 170                         }
 171         }
 172         iput(inode);
 173         if (!new_inode)
 174                 return -ENOENT;
 175         *res_inode = new_inode;
 176         new_inode->i_count++;
 177         return 0;
 178 }
 179 
 180 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182         int i;
 183         unsigned int dev,ino;
 184         char buf[64];
 185 
 186         if (!S_ISLNK(inode->i_mode)) {
 187                 iput(inode);
 188                 return -EINVAL;
 189         }
 190         i = proc_follow_link(NULL, inode, 0, 0, &inode);
 191         if (i)
 192                 return i;
 193         if (!inode)
 194                 return -EIO;
 195         dev = kdev_t_to_nr(inode->i_dev);
 196         ino = inode->i_ino;
 197         iput(inode);
 198         i = sprintf(buf,"[%04x]:%u", dev, ino);
 199         if (buflen > i)
 200                 buflen = i;
 201         i = 0;
 202         while (i < buflen)
 203                 put_user(buf[i++],buffer++);
 204         return i;
 205 }

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