root/fs/isofs/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. unixify_text_buffer
  2. isofs_determine_filetype
  3. isofs_file_read

   1 /*
   2  *  linux/fs/isofs/file.c
   3  *
   4  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
   5  *
   6  *  (C) 1991  Linus Torvalds - minix filesystem
   7  *
   8  *  isofs regular file handling primitives
   9  */
  10 
  11 #include <asm/segment.h>
  12 #include <asm/system.h>
  13 
  14 #include <linux/sched.h>
  15 #include <linux/iso_fs.h>
  16 #include <linux/fcntl.h>
  17 #include <linux/kernel.h>
  18 #include <linux/errno.h>
  19 #include <linux/stat.h>
  20 #include <linux/locks.h>
  21 
  22 #include <linux/dirent.h>
  23 
  24 #define NBUF    32
  25 
  26 #define MIN(a,b) (((a)<(b))?(a):(b))
  27 #define MAX(a,b) (((a)>(b))?(a):(b))
  28 
  29 #include <linux/fs.h>
  30 #include <linux/iso_fs.h>
  31 
  32 static int isofs_file_read(struct inode *, struct file *, char *, int);
  33 
  34 /*
  35  * We have mostly NULL's here: the current defaults are ok for
  36  * the isofs filesystem.
  37  */
  38 static struct file_operations isofs_file_operations = {
  39         NULL,                   /* lseek - default */
  40         isofs_file_read,        /* read */
  41         NULL,                   /* write */
  42         NULL,                   /* readdir - bad */
  43         NULL,                   /* select - default */
  44         NULL,                   /* ioctl - default */
  45         generic_mmap,           /* mmap */
  46         NULL,                   /* no special open is needed */
  47         NULL,                   /* release */
  48         NULL                    /* fsync */
  49 };
  50 
  51 struct inode_operations isofs_file_inode_operations = {
  52         &isofs_file_operations, /* default file operations */
  53         NULL,                   /* create */
  54         NULL,                   /* lookup */
  55         NULL,                   /* link */
  56         NULL,                   /* unlink */
  57         NULL,                   /* symlink */
  58         NULL,                   /* mkdir */
  59         NULL,                   /* rmdir */
  60         NULL,                   /* mknod */
  61         NULL,                   /* rename */
  62         NULL,                   /* readlink */
  63         NULL,                   /* follow_link */
  64         isofs_bmap,             /* bmap */
  65         NULL,                   /* truncate */
  66         NULL                    /* permission */
  67 };
  68 
  69 /* This is a heuristic to determine if a file is text of binary.  If it
  70  * is text, then we translate all 0x0d characters to spaces.  If the 0x0d
  71  * character is not preceeded or followed by a 0x0a, then we turn it into
  72  * a 0x0a.  A control-Z is also turned into a linefeed.
  73  */
  74 
  75 static inline void unixify_text_buffer(char * buffer, int chars, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77         while(chars--){
  78                 if(*buffer == 0x1a) *buffer = 0x0a;
  79                 if(*buffer == 0x0d){
  80                         if(mode == ISOFS_FILE_TEXT_M) *buffer = 0x0a;
  81                         if(mode == ISOFS_FILE_TEXT) *buffer = ' ';
  82                 }
  83                 buffer++;
  84         }
  85 }
  86 
  87 /*This function determines if a given file has a DOS-like text format or not*/
  88 
  89 static void isofs_determine_filetype(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  90 {
  91         int block;
  92         int result, i;
  93         struct buffer_head * bh;
  94         unsigned char * pnt;
  95         
  96         block = isofs_bmap(inode,0);
  97         if (block && (bh = bread(inode->i_dev,block, ISOFS_BUFFER_SIZE(inode)))) {
  98                 pnt = (unsigned char *) bh->b_data;
  99                 result = ISOFS_FILE_TEXT_M;
 100                 for(i=0;i<(inode->i_size < ISOFS_BUFFER_SIZE(inode) ? inode->i_size : ISOFS_BUFFER_SIZE(inode));
 101                     i++,pnt++){
 102                         if(*pnt & 0x80) {result = ISOFS_FILE_BINARY; break;};
 103                         if(*pnt >= 0x20 || *pnt == 0x1a) continue;
 104                         if(*pnt == 0x0a) {result = ISOFS_FILE_TEXT; continue;};
 105                         if(*pnt >= 0x9 && *pnt <= 0x0d) continue;
 106                         result = ISOFS_FILE_BINARY;
 107                         break;
 108                 }
 109                 brelse(bh);
 110                 inode->u.isofs_i.i_file_format = result;
 111         }
 112 }
 113 
 114 static int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         int read,left,chars;
 117         int block, blocks, offset;
 118         int bhrequest;
 119         int ra_blocks, max_block, nextblock;
 120         struct buffer_head ** bhb, ** bhe;
 121         struct buffer_head * bhreq[NBUF];
 122         struct buffer_head * buflist[NBUF];
 123         
 124         if (!inode) {
 125                 printk("isofs_file_read: inode = NULL\n");
 126                 return -EINVAL;
 127         }
 128         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
 129                 printk("isofs_file_read: mode = %07o\n",inode->i_mode);
 130                 return -EINVAL;
 131         }
 132         if (inode->u.isofs_i.i_file_format == ISOFS_FILE_UNKNOWN)
 133                 isofs_determine_filetype(inode);
 134         if (filp->f_pos > inode->i_size)
 135                 left = 0;
 136         else
 137                 left = inode->i_size - filp->f_pos;
 138         if (left > count)
 139                 left = count;
 140         if (left <= 0)
 141                 return 0;
 142         read = 0;
 143         block = filp->f_pos >> ISOFS_BUFFER_BITS(inode);
 144         offset = filp->f_pos & (ISOFS_BUFFER_SIZE(inode)-1);
 145         blocks = (left + offset + ISOFS_BUFFER_SIZE(inode) - 1) / ISOFS_BUFFER_SIZE(inode);
 146         bhb = bhe = buflist;
 147 
 148         ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
 149         max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
 150         nextblock = -1;
 151 
 152         /* We do this in a two stage process.  We first try and request
 153            as many blocks as we can, then we wait for the first one to
 154            complete, and then we try and wrap up as many as are actually
 155            done.  This routine is rather generic, in that it can be used
 156            in a filesystem by substituting the appropriate function in
 157            for getblk.
 158 
 159            This routine is optimized to make maximum use of the various
 160            buffers and caches. */
 161 
 162         do {
 163                 bhrequest = 0;
 164                 while (blocks) {
 165                         int uptodate;
 166                         --blocks;
 167                         *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
 168                         uptodate = 1;
 169                         if (*bhb && !(*bhb)->b_uptodate) {
 170                                 uptodate = 0;
 171                                 bhreq[bhrequest++] = *bhb;
 172                                 nextblock = (*bhb)->b_blocknr + 1;
 173                               };
 174 
 175                         if (++bhb == &buflist[NBUF])
 176                                 bhb = buflist;
 177 
 178                         /* If the block we have on hand is uptodate, go ahead
 179                            and complete processing. */
 180                         if(bhrequest == 0 && uptodate) break;
 181 
 182                         if (bhb == bhe)
 183                                 break;
 184                       }
 185 
 186                 if(blocks == 0 && bhrequest && filp->f_reada && bhb != bhe) { 
 187                   /* If we are going to read something anyways, add in the
 188                      read-ahead blocks */
 189                   while(ra_blocks){
 190                     if (block >= max_block) break;
 191                     if(bhrequest == NBUF) break;  /* Block full */
 192                     --ra_blocks;
 193                     *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
 194 
 195                     if (*bhb && !(*bhb)->b_uptodate) {
 196                       if((*bhb)->b_blocknr != nextblock) {
 197                         brelse(*bhb);
 198                         break;
 199                       };
 200                       nextblock = (*bhb)->b_blocknr + 1;
 201                       bhreq[bhrequest++] = *bhb;
 202                     };
 203                     
 204                     if (++bhb == &buflist[NBUF])
 205                       bhb = buflist;
 206                     
 207                     if (bhb == bhe)
 208                       break;
 209                   };
 210                 };
 211                 /* Now request them all */
 212                 if (bhrequest)
 213                   ll_rw_block(READ, bhrequest, bhreq);
 214 
 215                 do{ /* Finish off all I/O that has actually completed */
 216                   if (*bhe) {/* test for valid buffer */
 217                     wait_on_buffer(*bhe);
 218                     if (!(*bhe)->b_uptodate) {
 219                       brelse(*bhe);
 220                       if (++bhe == &buflist[NBUF])
 221                         bhe = buflist;
 222                       left = 0;
 223                       break;
 224                     }
 225                   }
 226                   
 227                   if (left < ISOFS_BUFFER_SIZE(inode) - offset)
 228                     chars = left;
 229                   else
 230                     chars = ISOFS_BUFFER_SIZE(inode) - offset;
 231                   filp->f_pos += chars;
 232                   left -= chars;
 233                   read += chars;
 234                   if (*bhe) {
 235                     if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
 236                         inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
 237                       unixify_text_buffer(offset+(*bhe)->b_data,
 238                                           chars, inode->u.isofs_i.i_file_format);
 239                     memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 240                     brelse(*bhe);
 241                     buf += chars;
 242                   } else {
 243                     while (chars-->0)
 244                       put_fs_byte(0,buf++);
 245                   }
 246                   offset = 0;
 247                   if (++bhe == &buflist[NBUF])
 248                     bhe = buflist;
 249                 } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && 
 250                         (left > 0));
 251         } while (left > 0);
 252 
 253 /* Release the read-ahead blocks */
 254         while (bhe != bhb) {
 255           if (*bhe) brelse(*bhe);
 256           if (++bhe == &buflist[NBUF])
 257             bhe = buflist;
 258         };
 259 
 260         filp->f_reada = 1;
 261 
 262         if (!read)
 263                 return -EIO;
 264         return read;
 265 }

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