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         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                       left = 0;
 220                       break;
 221                     }
 222                   }
 223                   
 224                   if (left < ISOFS_BUFFER_SIZE(inode) - offset)
 225                     chars = left;
 226                   else
 227                     chars = ISOFS_BUFFER_SIZE(inode) - offset;
 228                   filp->f_pos += chars;
 229                   left -= chars;
 230                   read += chars;
 231                   if (*bhe) {
 232                     if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
 233                         inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
 234                       unixify_text_buffer(offset+(*bhe)->b_data,
 235                                           chars, inode->u.isofs_i.i_file_format);
 236                     memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 237                     brelse(*bhe);
 238                     buf += chars;
 239                   } else {
 240                     while (chars-->0)
 241                       put_fs_byte(0,buf++);
 242                   }
 243                   offset = 0;
 244                   if (++bhe == &buflist[NBUF])
 245                     bhe = buflist;
 246                 } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && 
 247                         (left > 0));
 248         } while (left > 0);
 249 
 250 /* Release the read-ahead blocks */
 251         while (bhe != bhb) {
 252           if (*bhe) brelse(*bhe);
 253           if (++bhe == &buflist[NBUF])
 254             bhe = buflist;
 255         };
 256 
 257         filp->f_reada = 1;
 258 
 259         if (!read)
 260                 return -EIO;
 261         return read;
 262 }

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