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, 1993, 1994  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         if(ra_blocks > blocks) blocks = ra_blocks;
 150 
 151         max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
 152         nextblock = -1;
 153 
 154         /* We do this in a two stage process.  We first try and request
 155            as many blocks as we can, then we wait for the first one to
 156            complete, and then we try and wrap up as many as are actually
 157            done.  This routine is rather generic, in that it can be used
 158            in a filesystem by substituting the appropriate function in
 159            for getblk.
 160 
 161            This routine is optimized to make maximum use of the various
 162            buffers and caches. */
 163 
 164         do {
 165                 bhrequest = 0;
 166                 while (blocks) {
 167                         int uptodate;
 168                         --blocks;
 169                         *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
 170                         uptodate = 1;
 171                         if (*bhb && !(*bhb)->b_uptodate) {
 172                                 uptodate = 0;
 173                                 bhreq[bhrequest++] = *bhb;
 174                               };
 175 
 176                         if (++bhb == &buflist[NBUF])
 177                                 bhb = buflist;
 178 
 179                         /* If the block we have on hand is uptodate, go ahead
 180                            and complete processing. */
 181                         if(uptodate) break;
 182 
 183                         if (bhb == bhe)
 184                                 break;
 185                       }
 186 
 187                 /* Now request them all */
 188                 if (bhrequest)
 189                   ll_rw_block(READ, bhrequest, bhreq);
 190 
 191                 do{ /* Finish off all I/O that has actually completed */
 192                   if (*bhe) {/* test for valid buffer */
 193                     wait_on_buffer(*bhe);
 194                     if (!(*bhe)->b_uptodate) {
 195                       brelse(*bhe);
 196                       if (++bhe == &buflist[NBUF])
 197                         bhe = buflist;
 198                       left = 0;
 199                       break;
 200                     }
 201                   }
 202                   
 203                   if (left < ISOFS_BUFFER_SIZE(inode) - offset)
 204                     chars = left;
 205                   else
 206                     chars = ISOFS_BUFFER_SIZE(inode) - offset;
 207                   filp->f_pos += chars;
 208                   left -= chars;
 209                   read += chars;
 210                   if (*bhe) {
 211                     if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
 212                         inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
 213                       unixify_text_buffer(offset+(*bhe)->b_data,
 214                                           chars, inode->u.isofs_i.i_file_format);
 215                     memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 216                     brelse(*bhe);
 217                     buf += chars;
 218                   } else {
 219                     while (chars-->0)
 220                       put_fs_byte(0,buf++);
 221                   }
 222                   offset = 0;
 223                   if (++bhe == &buflist[NBUF])
 224                     bhe = buflist;
 225                 } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && 
 226                         (left > 0));
 227         } while (left > 0);
 228 
 229 /* Release the read-ahead blocks */
 230         while (bhe != bhb) {
 231           if (*bhe) brelse(*bhe);
 232           if (++bhe == &buflist[NBUF])
 233             bhe = buflist;
 234         };
 235 
 236         filp->f_reada = 1;
 237 
 238         if (!read)
 239                 return -EIO;
 240         return read;
 241 }

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