root/fs/msdos/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. msdos_file_read
  2. msdos_file_write
  3. msdos_truncate

   1 /*
   2  *  linux/fs/msdos/file.c
   3  *
   4  *  Written 1992,1993 by Werner Almesberger
   5  *
   6  *  MS-DOS regular file handling primitives
   7  */
   8 
   9 #include <asm/segment.h>
  10 #include <asm/system.h>
  11 
  12 #include <linux/sched.h>
  13 #include <linux/fs.h>
  14 #include <linux/msdos_fs.h>
  15 #include <linux/errno.h>
  16 #include <linux/fcntl.h>
  17 #include <linux/stat.h>
  18 
  19 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  20 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
  21 
  22 static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
  23     int count);
  24 static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
  25     int count);
  26 
  27 
  28 static struct file_operations msdos_file_operations = {
  29         NULL,                   /* lseek - default */
  30         msdos_file_read,        /* read */
  31         msdos_file_write,       /* write */
  32         NULL,                   /* readdir - bad */
  33         NULL,                   /* select - default */
  34         NULL,                   /* ioctl - default */
  35         NULL,                   /* mmap */
  36         NULL,                   /* no special open is needed */
  37         NULL,                   /* release */
  38         NULL                    /* fsync */
  39 };
  40 
  41 struct inode_operations msdos_file_inode_operations = {
  42         &msdos_file_operations, /* default 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         NULL,                   /* readlink */
  53         NULL,                   /* follow_link */
  54         msdos_bmap,             /* bmap */
  55         msdos_truncate,         /* truncate */
  56         NULL                    /* permission */
  57 };
  58 
  59 /* No bmap for MS-DOS FS' that don't align data at kByte boundaries. */
  60 
  61 struct inode_operations msdos_file_inode_operations_no_bmap = {
  62         &msdos_file_operations, /* default file operations */
  63         NULL,                   /* create */
  64         NULL,                   /* lookup */
  65         NULL,                   /* link */
  66         NULL,                   /* unlink */
  67         NULL,                   /* symlink */
  68         NULL,                   /* mkdir */
  69         NULL,                   /* rmdir */
  70         NULL,                   /* mknod */
  71         NULL,                   /* rename */
  72         NULL,                   /* readlink */
  73         NULL,                   /* follow_link */
  74         NULL,                   /* bmap */
  75         msdos_truncate,         /* truncate */
  76         NULL                    /* permission */
  77 };
  78 
  79 
  80 static int msdos_file_read(struct inode *inode,struct file *filp,char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
  81     int count)
  82 {
  83         char *start;
  84         int left,offset,size,sector,cnt;
  85         char ch;
  86         struct buffer_head *bh;
  87         void *data;
  88 
  89 /* printk("msdos_file_read\n"); */
  90         if (!inode) {
  91                 printk("msdos_file_read: inode = NULL\n");
  92                 return -EINVAL;
  93         }
  94         if (!S_ISREG(inode->i_mode)) {
  95                 printk("msdos_file_read: mode = %07o\n",inode->i_mode);
  96                 return -EINVAL;
  97         }
  98         if (filp->f_pos >= inode->i_size || count <= 0) return 0;
  99         start = buf;
 100         while ((left = MIN(inode->i_size-filp->f_pos,count-(buf-start))) > 0){
 101                 if (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
 102                         break;
 103                 offset = filp->f_pos & (SECTOR_SIZE-1);
 104                 if (!(bh = msdos_sread(inode->i_dev,sector,&data))) break;
 105                 filp->f_pos += (size = MIN(SECTOR_SIZE-offset,left));
 106                 if (MSDOS_I(inode)->i_binary) {
 107                         memcpy_tofs(buf,data+offset,size);
 108                         buf += size;
 109                 }
 110                 else for (cnt = size; cnt; cnt--) {
 111                                 if ((ch = *((char *) data+offset++)) == '\r')
 112                                         size--;
 113                                 else {
 114                                         if (ch != 26) put_fs_byte(ch,buf++);
 115                                         else {
 116                                                 filp->f_pos = inode->i_size;
 117                                                 brelse(bh);
 118                                                 return buf-start;
 119                                         }
 120                                 }
 121                         }
 122                 brelse(bh);
 123         }
 124         if (start == buf) return -EIO;
 125         return buf-start;
 126 }
 127 
 128 
 129 static int msdos_file_write(struct inode *inode,struct file *filp,char *buf,
     /* [previous][next][first][last][top][bottom][index][help] */
 130     int count)
 131 {
 132         int sector,offset,size,left,written;
 133         int error,carry;
 134         char *start,*to,ch;
 135         struct buffer_head *bh;
 136         void *data;
 137 
 138         if (!inode) {
 139                 printk("msdos_file_write: inode = NULL\n");
 140                 return -EINVAL;
 141         }
 142         if (!S_ISREG(inode->i_mode)) {
 143                 printk("msdos_file_write: mode = %07o\n",inode->i_mode);
 144                 return -EINVAL;
 145         }
 146 /*
 147  * ok, append may not work when many processes are writing at the same time
 148  * but so what. That way leads to madness anyway.
 149  */
 150         if (filp->f_flags & O_APPEND) filp->f_pos = inode->i_size;
 151         if (count <= 0) return 0;
 152         error = carry = 0;
 153         for (start = buf; count || carry; count -= size) {
 154                 while (!(sector = msdos_smap(inode,filp->f_pos >> SECTOR_BITS)))
 155                         if ((error = msdos_add_cluster(inode)) < 0) break;
 156                 if (error) {
 157                         msdos_truncate(inode);
 158                         break;
 159                 }
 160                 offset = filp->f_pos & (SECTOR_SIZE-1);
 161                 size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
 162                 if (!(bh = msdos_sread(inode->i_dev,sector,&data))) {
 163                         error = -EIO;
 164                         break;
 165                 }
 166                 if (MSDOS_I(inode)->i_binary) {
 167                         memcpy_fromfs(data+(filp->f_pos & (SECTOR_SIZE-1)),
 168                             buf,written = size);
 169                         buf += size;
 170                 }
 171                 else {
 172                         written = left = SECTOR_SIZE-offset;
 173                         to = data+(filp->f_pos & (SECTOR_SIZE-1));
 174                         if (carry) {
 175                                 *to++ = '\n';
 176                                 left--;
 177                                 carry = 0;
 178                         }
 179                         for (size = 0; size < count && left; size++) {
 180                                 if ((ch = get_fs_byte(buf++)) == '\n') {
 181                                         *to++ = '\r';
 182                                         left--;
 183                                 }
 184                                 if (!left) carry = 1;
 185                                 else {
 186                                         *to++ = ch;
 187                                         left--;
 188                                 }
 189                         }
 190                         written -= left;
 191                 }
 192                 filp->f_pos += written;
 193                 if (filp->f_pos > inode->i_size) {
 194                         inode->i_size = filp->f_pos;
 195                         inode->i_dirt = 1;
 196                 }
 197                 bh->b_dirt = 1;
 198                 brelse(bh);
 199         }
 200         inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 201         MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 202         inode->i_dirt = 1;
 203         return start == buf ? error : buf-start;
 204 }
 205 
 206 
 207 void msdos_truncate(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         int cluster;
 210 
 211         cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
 212         (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
 213         MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 214         inode->i_dirt = 1;
 215 }

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