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

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