root/fs/affs/file.c

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

DEFINITIONS

This source file includes following definitions.
  1. affs_smap
  2. affs_file_read

   1 /*
   2  *  linux/fs/affs/file.c
   3  *
   4  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
   5  *
   6  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
   7  *
   8  *  (C) 1991  Linus Torvalds - minix filesystem
   9  *
  10  *  affs regular file handling primitives
  11  */
  12 
  13 #include <asm/segment.h>
  14 #include <asm/system.h>
  15 
  16 #include <linux/sched.h>
  17 #include <linux/affs_fs.h>
  18 #include <linux/fcntl.h>
  19 #include <linux/kernel.h>
  20 #include <linux/errno.h>
  21 #include <linux/stat.h>
  22 #include <linux/locks.h>
  23 
  24 #include <linux/dirent.h>
  25 
  26 #define NBUF    16
  27 
  28 #define MIN(a,b) (((a)<(b))?(a):(b))
  29 #define MAX(a,b) (((a)>(b))?(a):(b))
  30 
  31 #include <linux/fs.h>
  32 #include <linux/affs_fs.h>
  33 
  34 #include "amigaffs.h"
  35 
  36 int affs_file_read(struct inode *, struct file *, char *, int);
  37 
  38 /*
  39  * We have mostly NULL's here: the current defaults are ok for
  40  * the affs filesystem.
  41  */
  42 struct file_operations affs_file_operations = {
  43         NULL,                   /* lseek - default */
  44         affs_file_read,         /* read */
  45         NULL,                   /* write */
  46         NULL,                   /* readdir - bad */
  47         NULL,                   /* select - default */
  48         NULL,                   /* ioctl - default */
  49         generic_file_mmap,      /* mmap */
  50         NULL,                   /* no special open is needed */
  51         NULL,                   /* release */
  52         NULL                    /* can't fsync */
  53 };
  54 
  55 struct inode_operations affs_file_inode_operations = {
  56         &affs_file_operations,  /* default file operations */
  57         NULL,                   /* create */
  58         NULL,                   /* lookup */
  59         NULL,                   /* link */
  60         NULL,                   /* unlink */
  61         NULL,                   /* symlink */
  62         NULL,                   /* mkdir */
  63         NULL,                   /* rmdir */
  64         NULL,                   /* mknod */
  65         NULL,                   /* rename */
  66         NULL,                   /* readlink */
  67         NULL,                   /* follow_link */
  68         NULL /* affs_bmap */,           /* bmap */
  69         NULL,                   /* truncate */
  70         NULL                    /* permission */
  71 };
  72 
  73 static int affs_smap(struct inode *inode, int block)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75         struct buffer_head *bh;
  76         int key;
  77         void *fh_data;
  78 
  79 /* FIXME */
  80 #define KEY_SLOTS_PER_BLOCK 72
  81 
  82 #ifdef DEBUG
  83         printk ("affs_smap: ino=%d block=%d\n", inode->i_ino, block);
  84 #endif
  85 
  86         if (block < 0) {
  87                 printk("affs_smap: block < 0");
  88                 return 0;
  89         }
  90 
  91         key = inode->i_ino;
  92         for (;;) {
  93                 bh = affs_pread (inode, key, &fh_data);
  94                 if (!bh)
  95                         return 0;
  96                 if (block < KEY_SLOTS_PER_BLOCK)
  97                         break;
  98                 block -= KEY_SLOTS_PER_BLOCK;
  99                 key = affs_get_extension (AFFS_I2BSIZE (inode), fh_data);
 100 #ifdef DEBUG
 101                 printk ("affs_smap: reading extension block %d\n", key);
 102 #endif
 103                 brelse (bh);
 104         }
 105         key = affs_get_key_entry (AFFS_I2BSIZE (inode), fh_data,
 106                                   (KEY_SLOTS_PER_BLOCK - 1) - block);
 107         brelse (bh);
 108 
 109 #ifdef DEBUG
 110         printk ("affs_smap: key=%d\n", key);
 111 #endif
 112         return key;
 113 }
 114 
 115 /*
 116  * affs_file_read() is also needed by the directory read-routine,
 117  * so it's not static. NOTE! reading directories directly is a bad idea,
 118  * but has to be supported for now for compatibility reasons with older
 119  * versions.
 120  */
 121 int affs_file_read(struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
 122                    char * buf, int count)
 123 {
 124         char *start;
 125         int left, offset, size, sector;
 126         struct buffer_head *bh;
 127         void *data;
 128 
 129         if (!inode) {
 130                 printk("affs_file_read: inode = NULL\n");
 131                 return -EINVAL;
 132         }
 133         if (!(S_ISREG(inode->i_mode))) {
 134 #ifdef DEBUG
 135                 printk("affs_file_read: mode = %07o\n",inode->i_mode);
 136 #endif
 137                 return -EINVAL;
 138         }
 139         if (filp->f_pos >= inode->i_size || count <= 0)
 140                 return 0;
 141 
 142         start = buf;
 143         for (;;) {
 144                 left = MIN (inode->i_size - filp->f_pos,
 145                             count - (buf - start));
 146                 if (!left)
 147                         break;
 148                 sector = affs_smap (inode, filp->f_pos >> AFFS_BLOCK_BITS);
 149                 if (!sector)
 150                         break;
 151                 offset = filp->f_pos & (AFFS_BLOCK_SIZE - 1);
 152                 bh = affs_pread (inode, sector, &data);
 153                 if (!bh)
 154                         break;
 155                 size = MIN (AFFS_BLOCK_SIZE - offset, left);
 156                 filp->f_pos += size;
 157                 memcpy_tofs (buf, data + offset, size);
 158                 buf += size;
 159                 brelse (bh);
 160         }
 161         if (start == buf)
 162                 return -EIO;
 163         return buf - start;
 164 
 165 #if 0
 166         if (filp->f_pos == 0 && count > 0) {
 167                 put_fs_byte ('X', buf++);
 168                 filp->f_pos++;
 169                 return 1;
 170         }
 171         else
 172                 return 0;
 173 #endif
 174 }

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