root/fs/minix/file_dev.c

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

DEFINITIONS

This source file includes following definitions.
  1. minix_readdir
  2. minix_file_read
  3. minix_file_write

   1 /*
   2  *  linux/fs/file_dev.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 #include <errno.h>
   8 #include <fcntl.h>
   9 #include <sys/dirent.h>
  10 #include <sys/stat.h>
  11 
  12 #include <linux/sched.h>
  13 #include <linux/minix_fs.h>
  14 #include <linux/kernel.h>
  15 #include <asm/segment.h>
  16 
  17 #define MIN(a,b) (((a)<(b))?(a):(b))
  18 #define MAX(a,b) (((a)>(b))?(a):(b))
  19 
  20 int minix_readdir(struct inode * inode, struct file * filp, struct dirent * dirent, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  21 {
  22         unsigned int block,offset,i;
  23         char c;
  24         struct buffer_head * bh;
  25         struct minix_dir_entry * de;
  26 
  27         if (!inode || !S_ISDIR(inode->i_mode))
  28                 return -EBADF;
  29         if (filp->f_pos & (sizeof (struct minix_dir_entry) - 1))
  30                 return -EBADF;
  31         while (filp->f_pos < inode->i_size) {
  32                 offset = filp->f_pos & 1023;
  33                 block = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS);
  34                 if (!block || !(bh = bread(inode->i_dev,block))) {
  35                         filp->f_pos += 1024-offset;
  36                         continue;
  37                 }
  38                 de = (struct minix_dir_entry *) (offset + bh->b_data);
  39                 while (offset < 1024 && filp->f_pos < inode->i_size) {
  40                         offset += sizeof (struct minix_dir_entry);
  41                         filp->f_pos += sizeof (struct minix_dir_entry);
  42                         if (de->inode) {
  43                                 for (i = 0; i < MINIX_NAME_LEN; i++)
  44                                         if (c = de->name[i])
  45                                                 put_fs_byte(c,i+dirent->d_name);
  46                                         else
  47                                                 break;
  48                                 if (i) {
  49                                         put_fs_long(de->inode,&dirent->d_ino);
  50                                         put_fs_byte(0,i+dirent->d_name);
  51                                         put_fs_word(i,&dirent->d_reclen);
  52                                         brelse(bh);
  53                                         return i;
  54                                 }
  55                         }
  56                         de++;
  57                 }
  58                 brelse(bh);
  59         }
  60         return 0;
  61 }
  62 
  63 int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
  64 {
  65         int read,left,chars,nr;
  66         struct buffer_head * bh;
  67 
  68         if (!inode) {
  69                 printk("minix_file_read: inode = NULL\n");
  70                 return -EINVAL;
  71         }
  72         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
  73                 printk("minix_file_read: mode = %07o\n",inode->i_mode);
  74                 return -EINVAL;
  75         }
  76         if (filp->f_pos > inode->i_size)
  77                 left = 0;
  78         else
  79                 left = inode->i_size - filp->f_pos;
  80         if (left > count)
  81                 left = count;
  82         read = 0;
  83         while (left > 0) {
  84                 if (nr = minix_bmap(inode,(filp->f_pos)>>BLOCK_SIZE_BITS)) {
  85                         if (!(bh=bread(inode->i_dev,nr)))
  86                                 return read?read:-EIO;
  87                 } else
  88                         bh = NULL;
  89                 nr = filp->f_pos & (BLOCK_SIZE-1);
  90                 chars = MIN( BLOCK_SIZE-nr , left );
  91                 filp->f_pos += chars;
  92                 left -= chars;
  93                 read += chars;
  94                 if (bh) {
  95                         memcpy_tofs(buf,nr+bh->b_data,chars);
  96                         buf += chars;
  97                         brelse(bh);
  98                 } else {
  99                         while (chars-->0)
 100                                 put_fs_byte(0,buf++);
 101                 }
 102         }
 103         inode->i_atime = CURRENT_TIME;
 104         return read;
 105 }
 106 
 107 int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 108 {
 109         off_t pos;
 110         int written,block,c;
 111         struct buffer_head * bh;
 112         char * p;
 113 
 114         if (!inode) {
 115                 printk("minix_file_write: inode = NULL\n");
 116                 return -EINVAL;
 117         }
 118         if (!S_ISREG(inode->i_mode)) {
 119                 printk("minix_file_write: mode = %07o\n",inode->i_mode);
 120                 return -EINVAL;
 121         }
 122 /*
 123  * ok, append may not work when many processes are writing at the same time
 124  * but so what. That way leads to madness anyway.
 125  */
 126         if (filp->f_flags & O_APPEND)
 127                 pos = inode->i_size;
 128         else
 129                 pos = filp->f_pos;
 130         written = 0;
 131         while (written<count) {
 132                 if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) {
 133                         if (!written)
 134                                 written = -ENOSPC;
 135                         break;
 136                 }
 137                 c = BLOCK_SIZE - (pos % BLOCK_SIZE);
 138                 if (c > count-written)
 139                         c = count-written;
 140                 if (c == BLOCK_SIZE)
 141                         bh = getblk(inode->i_dev, block);
 142                 else
 143                         bh = bread(inode->i_dev,block);
 144                 if (!bh) {
 145                         if (!written)
 146                                 written = -EIO;
 147                         break;
 148                 }
 149                 p = (pos % BLOCK_SIZE) + bh->b_data;
 150                 pos += c;
 151                 if (pos > inode->i_size) {
 152                         inode->i_size = pos;
 153                         inode->i_dirt = 1;
 154                 }
 155                 written += c;
 156                 memcpy_fromfs(p,buf,c);
 157                 buf += c;
 158                 bh->b_uptodate = 1;
 159                 bh->b_dirt = 1;
 160                 brelse(bh);
 161         }
 162         inode->i_mtime = CURRENT_TIME;
 163         if (!(filp->f_flags & O_APPEND)) {
 164                 filp->f_pos = pos;
 165                 inode->i_ctime = CURRENT_TIME;
 166         }
 167         inode->i_dirt = 1;
 168         return written;
 169 }

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