root/fs/proc/mem.c

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

DEFINITIONS

This source file includes following definitions.
  1. mem_read
  2. mem_write
  3. mem_lseek

   1 /*
   2  *  linux/fs/proc/mem.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <linux/types.h>
   8 #include <linux/errno.h>
   9 #include <linux/sched.h>
  10 #include <linux/kernel.h>
  11 
  12 #include <asm/segment.h>
  13 #include <asm/io.h>
  14 
  15 /*
  16  * mem_write isn't really a good idea right now. It needs
  17  * to check a lot more: if the process we try to write to 
  18  * dies in the middle right now, mem_write will overwrite
  19  * kernel memory.. This disables it altogether.
  20  */
  21 #define mem_write NULL
  22 
  23 static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  24 {
  25         unsigned long addr, pid, cr3;
  26         char *tmp;
  27         unsigned long pte, page;
  28         int i;
  29 
  30         if (count < 0)
  31                 return -EINVAL;
  32         pid = inode->i_ino;
  33         pid >>= 16;
  34         cr3 = 0;
  35         for (i = 1 ; i < NR_TASKS ; i++)
  36                 if (task[i] && task[i]->pid == pid) {
  37                         cr3 = task[i]->tss.cr3;
  38                         break;
  39                 }
  40         if (!cr3)
  41                 return -EACCES;
  42         addr = file->f_pos;
  43         tmp = buf;
  44         while (count > 0) {
  45                 if (current->signal & ~current->blocked)
  46                         break;
  47                 pte = *PAGE_DIR_OFFSET(cr3,addr);
  48                 if (!(pte & PAGE_PRESENT))
  49                         break;
  50                 pte &= PAGE_MASK;
  51                 pte += PAGE_PTR(addr);
  52                 page = *(unsigned long *) pte;
  53                 if (!(page & 1))
  54                         break;
  55                 page &= PAGE_MASK;
  56                 page += addr & ~PAGE_MASK;
  57                 i = PAGE_SIZE-(addr & ~PAGE_MASK);
  58                 if (i > count)
  59                         i = count;
  60                 memcpy_tofs(tmp,(void *) page,i);
  61                 addr += i;
  62                 tmp += i;
  63                 count -= i;
  64         }
  65         file->f_pos = addr;
  66         return tmp-buf;
  67 }
  68 
  69 #ifndef mem_write
  70 
  71 static int mem_write(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         unsigned long addr, pid, cr3;
  74         char *tmp;
  75         unsigned long pte, page;
  76         int i;
  77 
  78         if (count < 0)
  79                 return -EINVAL;
  80         addr = file->f_pos;
  81         pid = inode->i_ino;
  82         pid >>= 16;
  83         cr3 = 0;
  84         for (i = 1 ; i < NR_TASKS ; i++)
  85                 if (task[i] && task[i]->pid == pid) {
  86                         cr3 = task[i]->tss.cr3;
  87                         break;
  88                 }
  89         if (!cr3)
  90                 return -EACCES;
  91         tmp = buf;
  92         while (count > 0) {
  93                 if (current->signal & ~current->blocked)
  94                         break;
  95                 pte = *PAGE_DIR_OFFSET(cr3,addr);
  96                 if (!(pte & PAGE_PRESENT))
  97                         break;
  98                 pte &= PAGE_MASK;
  99                 pte += PAGE_PTR(addr);
 100                 page = *(unsigned long *) pte;
 101                 if (!(page & PAGE_PRESENT))
 102                         break;
 103                 if (!(page & 2)) {
 104                         do_wp_page(0,addr,current,0);
 105                         continue;
 106                 }
 107                 page &= PAGE_MASK;
 108                 page += addr & ~PAGE_MASK;
 109                 i = PAGE_SIZE-(addr & ~PAGE_MASK);
 110                 if (i > count)
 111                         i = count;
 112                 memcpy_fromfs((void *) page,tmp,i);
 113                 addr += i;
 114                 tmp += i;
 115                 count -= i;
 116         }
 117         file->f_pos = addr;
 118         if (tmp != buf)
 119                 return tmp-buf;
 120         if (current->signal & ~current->blocked)
 121                 return -ERESTARTSYS;
 122         return 0;
 123 }
 124 
 125 #endif
 126 
 127 static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129         switch (orig) {
 130                 case 0:
 131                         file->f_pos = offset;
 132                         return file->f_pos;
 133                 case 1:
 134                         file->f_pos += offset;
 135                         return file->f_pos;
 136                 default:
 137                         return -EINVAL;
 138         }
 139 }
 140 
 141 static struct file_operations proc_mem_operations = {
 142         mem_lseek,
 143         mem_read,
 144         mem_write,
 145         NULL,           /* mem_readdir */
 146         NULL,           /* mem_select */
 147         NULL,           /* mem_ioctl */
 148         NULL,           /* mmap */
 149         NULL,           /* no special open code */
 150         NULL,           /* no special release code */
 151         NULL            /* can't fsync */
 152 };
 153 
 154 struct inode_operations proc_mem_inode_operations = {
 155         &proc_mem_operations,   /* default base directory file-ops */
 156         NULL,                   /* create */
 157         NULL,                   /* lookup */
 158         NULL,                   /* link */
 159         NULL,                   /* unlink */
 160         NULL,                   /* symlink */
 161         NULL,                   /* mkdir */
 162         NULL,                   /* rmdir */
 163         NULL,                   /* mknod */
 164         NULL,                   /* rename */
 165         NULL,                   /* readlink */
 166         NULL,                   /* follow_link */
 167         NULL,                   /* bmap */
 168         NULL,                   /* truncate */
 169         NULL                    /* permission */
 170 };

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