root/fs/proc/link.c

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

DEFINITIONS

This source file includes following definitions.
  1. proc_follow_link
  2. 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 
  22 /*
  23  * PLAN9_SEMANTICS won't work any more: it used an ugly hack that broke 
  24  * when the files[] array was updated only after the open code
  25  */
  26 #undef PLAN9_SEMANTICS
  27 
  28 /*
  29  * links can't do much...
  30  */
  31 static struct file_operations proc_fd_link_operations = {
  32         NULL,                   /* lseek - default */
  33         NULL,                   /* read - bad */
  34         NULL,                   /* write - bad */
  35         NULL,                   /* readdir - bad */
  36         NULL,                   /* select - default */
  37         NULL,                   /* ioctl - default */
  38         NULL,                   /* mmap */
  39         NULL,                   /* very special open code */
  40         NULL,                   /* no special release code */
  41         NULL                    /* can't fsync */
  42 };
  43 
  44 struct inode_operations proc_link_inode_operations = {
  45         &proc_fd_link_operations,/* file-operations */
  46         NULL,                   /* create */
  47         NULL,                   /* lookup */
  48         NULL,                   /* link */
  49         NULL,                   /* unlink */
  50         NULL,                   /* symlink */
  51         NULL,                   /* mkdir */
  52         NULL,                   /* rmdir */
  53         NULL,                   /* mknod */
  54         NULL,                   /* rename */
  55         proc_readlink,          /* readlink */
  56         proc_follow_link,       /* follow_link */
  57         NULL,                   /* readpage */
  58         NULL,                   /* writepage */
  59         NULL,                   /* bmap */
  60         NULL,                   /* truncate */
  61         NULL                    /* permission */
  62 };
  63 
  64 
  65 static int proc_follow_link(struct inode * dir, struct inode * inode,
     /* [previous][next][first][last][top][bottom][index][help] */
  66         int flag, int mode, struct inode ** res_inode)
  67 {
  68         unsigned int pid, ino;
  69         struct task_struct * p;
  70         struct inode * new_inode;
  71         int i, error;
  72 
  73         *res_inode = NULL;
  74         if (dir)
  75                 iput(dir);
  76         if (!inode)
  77                 return -ENOENT;
  78         if ((error = permission(inode, MAY_EXEC)) != 0){
  79                 iput(inode);
  80                 return error;
  81         }
  82         ino = inode->i_ino;
  83         pid = ino >> 16;
  84         ino &= 0x0000ffff;
  85         for (i = 0 ; i < NR_TASKS ; i++)
  86                 if ((p = task[i]) && p->pid == pid)
  87                         break;
  88         if (i >= NR_TASKS) {
  89                 iput(inode);
  90                 return -ENOENT;
  91         }
  92         new_inode = NULL;
  93         switch (ino) {
  94                 case PROC_PID_CWD:
  95                         if (!p->fs)
  96                                 break;
  97                         new_inode = p->fs->pwd;
  98                         break;
  99                 case PROC_PID_ROOT:
 100                         if (!p->fs)
 101                                 break;
 102                         new_inode = p->fs->root;
 103                         break;
 104                 case PROC_PID_EXE: {
 105                         struct vm_area_struct * vma;
 106                         if (!p->mm)
 107                                 break;
 108                         vma = p->mm->mmap;
 109                         while (vma) {
 110                                 if (vma->vm_flags & VM_EXECUTABLE) {
 111                                         new_inode = vma->vm_inode;
 112                                         break;
 113                                 }
 114                                 vma = vma->vm_next;
 115                         }
 116                         break;
 117                 }
 118                 default:
 119                         switch (ino >> 8) {
 120                         case PROC_PID_FD_DIR:
 121                                 if (!p->files)
 122                                         break;
 123                                 ino &= 0xff;
 124                                 if (ino < NR_OPEN && p->files->fd[ino]) {
 125                                         new_inode = p->files->fd[ino]->f_inode;
 126                                 }
 127                                 break;
 128                         }
 129         }
 130         iput(inode);
 131         if (!new_inode)
 132                 return -ENOENT;
 133         *res_inode = new_inode;
 134         new_inode->i_count++;
 135         return 0;
 136 }
 137 
 138 static int proc_readlink(struct inode * inode, char * buffer, int buflen)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140         int i;
 141         unsigned int dev,ino;
 142         char buf[64];
 143 
 144         if (!S_ISLNK(inode->i_mode)) {
 145                 iput(inode);
 146                 return -EINVAL;
 147         }
 148         i = proc_follow_link(NULL, inode, 0, 0, &inode);
 149         if (i)
 150                 return i;
 151         if (!inode)
 152                 return -EIO;
 153         dev = kdev_t_to_nr(inode->i_dev);
 154         ino = inode->i_ino;
 155         iput(inode);
 156         i = sprintf(buf,"[%04x]:%u", dev, ino);
 157         if (buflen > i)
 158                 buflen = i;
 159         i = 0;
 160         while (i < buflen)
 161                 put_user(buf[i++],buffer++);
 162         return i;
 163 }

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