root/fs/isofs/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. unixify_to_fs
  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 preceded 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_to_fs(char * outbuf, char * buffer, int chars,
     /* [previous][next][first][last][top][bottom][index][help] */
  76                                  int mode)
  77 {
  78         char outchar;
  79 
  80         while(chars--){
  81                 outchar = *buffer;
  82                 if(outchar == 0x1a) outchar = 0x0a;
  83                 if(outchar == 0x0d){
  84                         if(mode == ISOFS_FILE_TEXT_M) outchar = 0x0a;
  85                         if(mode == ISOFS_FILE_TEXT) outchar = ' ';
  86                 }
  87                 put_fs_byte(outchar, outbuf++);
  88                 buffer++;
  89         }
  90 }
  91 
  92 /*This function determines if a given file has a DOS-like text format or not*/
  93 
  94 static void isofs_determine_filetype(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96         int block;
  97         int result, i;
  98         struct buffer_head * bh;
  99         unsigned char * pnt;
 100         
 101         block = isofs_bmap(inode,0);
 102         if (block && (bh = bread(inode->i_dev,block, ISOFS_BUFFER_SIZE(inode)))) {
 103                 pnt = (unsigned char *) bh->b_data;
 104                 result = ISOFS_FILE_TEXT_M;
 105                 for(i=0;i<(inode->i_size < ISOFS_BUFFER_SIZE(inode) ? inode->i_size : ISOFS_BUFFER_SIZE(inode));
 106                     i++,pnt++){
 107                         if(*pnt & 0x80) {result = ISOFS_FILE_BINARY; break;};
 108                         if(*pnt >= 0x20 || *pnt == 0x1a) continue;
 109                         if(*pnt == 0x0a) {result = ISOFS_FILE_TEXT; continue;};
 110                         if(*pnt >= 0x9 && *pnt <= 0x0d) continue;
 111                         result = ISOFS_FILE_BINARY;
 112                         break;
 113                 }
 114                 brelse(bh);
 115                 inode->u.isofs_i.i_file_format = result;
 116         }
 117 }
 118 
 119 static int isofs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 120 {
 121         int read,left,chars;
 122         int block, blocks, offset;
 123         int bhrequest;
 124         int ra_blocks, max_block, nextblock;
 125         struct buffer_head ** bhb, ** bhe;
 126         struct buffer_head * bhreq[NBUF];
 127         struct buffer_head * buflist[NBUF];
 128         
 129         if (!inode) {
 130                 printk("isofs_file_read: inode = NULL\n");
 131                 return -EINVAL;
 132         }
 133         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
 134                 printk("isofs_file_read: mode = %07o\n",inode->i_mode);
 135                 return -EINVAL;
 136         }
 137         if (inode->u.isofs_i.i_file_format == ISOFS_FILE_UNKNOWN)
 138                 isofs_determine_filetype(inode);
 139         if (filp->f_pos > inode->i_size)
 140                 left = 0;
 141         else
 142                 left = inode->i_size - filp->f_pos;
 143         if (left > count)
 144                 left = count;
 145         if (left <= 0)
 146                 return 0;
 147         read = 0;
 148         block = filp->f_pos >> ISOFS_BUFFER_BITS(inode);
 149         offset = (inode->u.isofs_i.i_first_extent + filp->f_pos)
 150           & (ISOFS_BUFFER_SIZE(inode)-1);
 151         blocks = (left + offset + ISOFS_BUFFER_SIZE(inode) - 1) / ISOFS_BUFFER_SIZE(inode);
 152         bhb = bhe = buflist;
 153 
 154         ra_blocks = read_ahead[MAJOR(inode->i_dev)] / (BLOCK_SIZE >> 9);
 155         if(ra_blocks > blocks) blocks = ra_blocks;
 156 
 157         max_block = (inode->i_size + BLOCK_SIZE - 1)/BLOCK_SIZE;
 158         nextblock = -1;
 159 
 160         /* We do this in a two stage process.  We first try and request
 161            as many blocks as we can, then we wait for the first one to
 162            complete, and then we try and wrap up as many as are actually
 163            done.  This routine is rather generic, in that it can be used
 164            in a filesystem by substituting the appropriate function in
 165            for getblk.
 166 
 167            This routine is optimized to make maximum use of the various
 168            buffers and caches. */
 169 
 170         do {
 171                 bhrequest = 0;
 172                 while (blocks) {
 173                         int uptodate;
 174                         --blocks;
 175                         *bhb = getblk(inode->i_dev,isofs_bmap(inode, block++), ISOFS_BUFFER_SIZE(inode));
 176                         uptodate = 1;
 177                         if (*bhb && !(*bhb)->b_uptodate) {
 178                                 uptodate = 0;
 179                                 bhreq[bhrequest++] = *bhb;
 180                               };
 181 
 182                         if (++bhb == &buflist[NBUF])
 183                                 bhb = buflist;
 184 
 185                         /* If the block we have on hand is uptodate, go ahead
 186                            and complete processing. */
 187                         if(uptodate) break;
 188 
 189                         if (bhb == bhe)
 190                                 break;
 191                       }
 192 
 193                 /* Now request them all */
 194                 if (bhrequest)
 195                   ll_rw_block(READ, bhrequest, bhreq);
 196 
 197                 do{ /* Finish off all I/O that has actually completed */
 198                   if (*bhe) {/* test for valid buffer */
 199                     wait_on_buffer(*bhe);
 200                     if (!(*bhe)->b_uptodate) {
 201                       brelse(*bhe);
 202                       if (++bhe == &buflist[NBUF])
 203                         bhe = buflist;
 204                       left = 0;
 205                       break;
 206                     }
 207                   }
 208                   
 209                   if (left < ISOFS_BUFFER_SIZE(inode) - offset)
 210                     chars = left;
 211                   else
 212                     chars = ISOFS_BUFFER_SIZE(inode) - offset;
 213                   filp->f_pos += chars;
 214                   left -= chars;
 215                   read += chars;
 216                   if (*bhe) {
 217                     if (inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT ||
 218                         inode->u.isofs_i.i_file_format == ISOFS_FILE_TEXT_M)
 219                       unixify_to_fs(buf, offset+(*bhe)->b_data, chars, 
 220                                     inode->u.isofs_i.i_file_format);
 221                     else
 222                       memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
 223                     brelse(*bhe);
 224                     buf += chars;
 225                   } else {
 226                     while (chars-->0)
 227                       put_fs_byte(0,buf++);
 228                   }
 229                   offset = 0;
 230                   if (++bhe == &buflist[NBUF])
 231                     bhe = buflist;
 232                 } while( bhe != bhb && (*bhe == 0 || !(*bhe)->b_lock) && 
 233                         (left > 0));
 234         } while (left > 0);
 235 
 236 /* Release the read-ahead blocks */
 237         while (bhe != bhb) {
 238           if (*bhe) brelse(*bhe);
 239           if (++bhe == &buflist[NBUF])
 240             bhe = buflist;
 241         };
 242 
 243         filp->f_reada = 1;
 244 
 245         if (!read)
 246                 return -EIO;
 247         return read;
 248 }

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