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 static int mem_read(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  16 {
  17         unsigned long addr, pid, cr3;
  18         char *tmp;
  19         unsigned long pde, pte, page;
  20         int i;
  21 
  22         if (count < 0)
  23                 return -EINVAL;
  24         pid = inode->i_ino;
  25         pid >>= 16;
  26         cr3 = 0;
  27         for (i = 1 ; i < NR_TASKS ; i++)
  28                 if (task[i] && task[i]->pid == pid) {
  29                         cr3 = task[i]->tss.cr3;
  30                         break;
  31                 }
  32         if (!cr3)
  33                 return -EACCES;
  34         addr = file->f_pos;
  35         tmp = buf;
  36         while (count > 0) {
  37                 if (current->signal & ~current->blocked)
  38                         break;
  39                 pde = cr3 + (addr >> 20 & 0xffc);
  40                 pte = *(unsigned long *) pde;
  41                 if (!(pte & PAGE_PRESENT))
  42                         break;
  43                 pte &= 0xfffff000;
  44                 pte += (addr >> 10) & 0xffc;
  45                 page = *(unsigned long *) pte;
  46                 if (!(page & 1))
  47                         break;
  48                 page &= 0xfffff000;
  49                 page += addr & 0xfff;
  50                 i = 4096-(addr & 0xfff);
  51                 if (i > count)
  52                         i = count;
  53                 memcpy_tofs(tmp,(void *) page,i);
  54                 addr += i;
  55                 tmp += i;
  56                 count -= i;
  57         }
  58         file->f_pos = addr;
  59         return tmp-buf;
  60 }
  61 
  62 static int mem_write(struct inode * inode, struct file * file,char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  63 {
  64         unsigned long addr, pid, cr3;
  65         char *tmp;
  66         unsigned long pde, pte, page;
  67         int i;
  68 
  69         if (count < 0)
  70                 return -EINVAL;
  71         addr = file->f_pos;
  72         pid = inode->i_ino;
  73         pid >>= 16;
  74         cr3 = 0;
  75         for (i = 1 ; i < NR_TASKS ; i++)
  76                 if (task[i] && task[i]->pid == pid) {
  77                         cr3 = task[i]->tss.cr3;
  78                         break;
  79                 }
  80         if (!cr3)
  81                 return -EACCES;
  82         tmp = buf;
  83         while (count > 0) {
  84                 if (current->signal & ~current->blocked)
  85                         break;
  86                 pde = cr3 + (addr >> 20 & 0xffc);
  87                 pte = *(unsigned long *) pde;
  88                 if (!(pte & PAGE_PRESENT))
  89                         break;
  90                 pte &= 0xfffff000;
  91                 pte += (addr >> 10) & 0xffc;
  92                 page = *(unsigned long *) pte;
  93                 if (!(page & PAGE_PRESENT))
  94                         break;
  95                 if (!(page & 2)) {
  96                         do_wp_page(0,addr,current,0);
  97                         continue;
  98                 }
  99                 page &= 0xfffff000;
 100                 page += addr & 0xfff;
 101                 i = 4096-(addr & 0xfff);
 102                 if (i > count)
 103                         i = count;
 104                 memcpy_fromfs((void *) page,tmp,i);
 105                 addr += i;
 106                 tmp += i;
 107                 count -= i;
 108         }
 109         file->f_pos = addr;
 110         if (tmp != buf)
 111                 return tmp-buf;
 112         if (current->signal & ~current->blocked)
 113                 return -ERESTARTSYS;
 114         return 0;
 115 }
 116 
 117 static int mem_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         switch (orig) {
 120                 case 0:
 121                         file->f_pos = offset;
 122                         return file->f_pos;
 123                 case 1:
 124                         file->f_pos += offset;
 125                         return file->f_pos;
 126                 default:
 127                         return -EINVAL;
 128         }
 129         if (file->f_pos < 0)
 130                 return 0;
 131         return file->f_pos;
 132 }
 133 
 134 static struct file_operations proc_mem_operations = {
 135         mem_lseek,
 136         mem_read,
 137         mem_write,
 138         NULL,           /* mem_readdir */
 139         NULL,           /* mem_select */
 140         NULL,           /* mem_ioctl */
 141         NULL,           /* no special open code */
 142         NULL            /* no special release code */
 143 };
 144 
 145 struct inode_operations proc_mem_inode_operations = {
 146         &proc_mem_operations,   /* default base directory file-ops */
 147         NULL,                   /* create */
 148         NULL,                   /* lookup */
 149         NULL,                   /* link */
 150         NULL,                   /* unlink */
 151         NULL,                   /* symlink */
 152         NULL,                   /* mkdir */
 153         NULL,                   /* rmdir */
 154         NULL,                   /* mknod */
 155         NULL,                   /* rename */
 156         NULL,                   /* readlink */
 157         NULL,                   /* follow_link */
 158         NULL,                   /* bmap */
 159         NULL                    /* truncate */
 160 };

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