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

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