root/fs/ufs/ufs_dir.c

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

DEFINITIONS

This source file includes following definitions.
  1. ufs_dir_read
  2. ufs_readdir

   1 /*
   2  *  linux/fs/ufs/ufs_dir.c
   3  *
   4  * Copyright (C) 1996
   5  * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
   6  * Laboratory for Computer Science Research Computing Facility
   7  * Rutgers, The State University of New Jersey
   8  *
   9  * $Id: ufs_dir.c,v 1.1 1996/04/21 14:41:04 davem Exp $
  10  *
  11  */
  12 
  13 #include <linux/fs.h>
  14 
  15 /* XXX */
  16 extern int ufs_lookup();
  17 extern int ufs_bmap();
  18 
  19 static int ufs_dir_read (struct inode * inode, struct file * filp,
     /* [previous][next][first][last][top][bottom][index][help] */
  20                          char * buf, int count)
  21 {
  22         /* XXX - probably allow this for root, EISDIR for normal users */
  23         return -EISDIR;
  24 }
  25 
  26 /*
  27  * This is blatantly stolen from ext2fs
  28  */
  29 static int
  30 ufs_readdir (struct inode * inode, struct file * filp, void * dirent,
     /* [previous][next][first][last][top][bottom][index][help] */
  31              filldir_t filldir)
  32 {
  33         int error = 0;
  34         unsigned long offset, lblk, blk;
  35         int i, stored;
  36         struct buffer_head * bh;
  37         struct direct * de;
  38         struct super_block * sb;
  39 
  40         if (!inode || !S_ISDIR(inode->i_mode))
  41                 return -EBADF;
  42         sb = inode->i_sb;
  43 
  44         if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
  45                 printk("ufs_readdir: ino %lu  f_pos %lu\n",
  46                        inode->i_ino, filp->f_pos);
  47                 ufs_print_inode(inode);
  48         }
  49 
  50         stored = 0;
  51         bh = NULL;
  52         offset = filp->f_pos & (sb->s_blocksize - 1);
  53 
  54         while (!error && !stored && filp->f_pos < inode->i_size) {
  55                 lblk = (filp->f_pos) >> sb->s_blocksize_bits;
  56                 blk = ufs_bmap(inode, lblk);
  57                 /* XXX - ufs_bmap() call needs error checking */
  58                 blk = ufs_bmap(inode, lblk);
  59                 bh = bread (sb->s_dev, blk, sb->s_blocksize);
  60                 if (!bh) {
  61                         /* XXX - error - skip to the next block */
  62                         printk("ufs_readdir: dir inode %lu has a hole at offset %lu\n",
  63                                inode->i_ino, (unsigned long int)filp->f_pos);
  64                         filp->f_pos += sb->s_blocksize - offset;
  65                         continue;
  66                 }
  67 
  68 revalidate:
  69                 /* If the dir block has changed since the last call to
  70                  * readdir(2), then we might be pointing to an invalid
  71                  * dirent right now.  Scan from the start of the block
  72                  * to make sure. */
  73                 if (filp->f_version != inode->i_version) {
  74                         for (i = 0; i < sb->s_blocksize && i < offset; ) {
  75                                 de = (struct direct *) 
  76                                         (bh->b_data + i);
  77                                 /* It's too expensive to do a full
  78                                  * dirent test each time round this
  79                                  * loop, but we do have to test at
  80                                  * least that it is non-zero.  A
  81                                  * failure will be detected in the
  82                                  * dirent test below. */
  83                                 if (de->d_reclen < 1)
  84                                         break;
  85                                 i += de->d_reclen;
  86                         }
  87                         offset = i;
  88                         filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
  89                                 | offset;
  90                         filp->f_version = inode->i_version;
  91                 }
  92                 
  93                 while (!error && filp->f_pos < inode->i_size 
  94                        && offset < sb->s_blocksize) {
  95                         de = (struct direct *) (bh->b_data + offset);
  96                         /* XXX - put in a real ufs_check_dir_entry() */
  97                         if ((de->d_reclen == 0) || (de->d_namlen == 0)) {
  98                                 filp->f_pos = filp->f_pos & (sb->s_blocksize - 1) + sb->s_blocksize;
  99                                 brelse(bh);
 100                                 return stored;
 101                         }
 102 #if 0
 103                         if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
 104                                                    bh, offset)) {
 105                                 /* On error, skip the f_pos to the
 106                                    next block. */
 107                                 filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
 108                                               + sb->s_blocksize;
 109                                 brelse (bh);
 110                                 return stored;
 111                         }
 112 #endif /* XXX */
 113                         offset += de->d_reclen;
 114                         if (de->d_ino) {
 115                                 /* We might block in the next section
 116                                  * if the data destination is
 117                                  * currently swapped out.  So, use a
 118                                  * version stamp to detect whether or
 119                                  * not the directory has been modified
 120                                  * during the copy operation. */
 121                                 unsigned long version;
 122                                 dcache_add(inode, de->d_name, de->d_namlen,
 123                                            de->d_ino);
 124                                 version = inode->i_version;
 125                                 if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
 126                                         printk("ufs_readdir: filldir(%s,%lu)\n",
 127                                                de->d_name, de->d_ino);
 128                                 }
 129                                 error = filldir(dirent, de->d_name, de->d_namlen, filp->f_pos, de->d_ino);
 130                                 if (error)
 131                                         break;
 132                                 if (version != inode->i_version)
 133                                         goto revalidate;
 134                                 stored ++;
 135                         }
 136                         filp->f_pos += de->d_reclen;
 137                 }
 138                 offset = 0;
 139                 brelse (bh);
 140         }
 141 #if 0 /* XXX */
 142         if (!IS_RDONLY(inode)) {
 143                 inode->i_atime = CURRENT_TIME;
 144                 inode->i_dirt = 1;
 145         }
 146 #endif /* XXX */
 147         return 0;
 148 }
 149 
 150 
 151 static struct file_operations ufs_dir_operations = {
 152         NULL,                   /* lseek */
 153         &ufs_dir_read,          /* read */
 154         NULL,                   /* write */
 155         &ufs_readdir,           /* readdir */
 156         NULL,                   /* select */
 157         NULL,                   /* ioctl */
 158         NULL,                   /* mmap */
 159         NULL,                   /* open */
 160         NULL,                   /* release */
 161         &file_fsync,            /* fsync */
 162         NULL,                   /* fasync */
 163         NULL,                   /* check_media_change */
 164         NULL,                   /* revalidate */
 165 };
 166 
 167 struct inode_operations ufs_dir_inode_operations = {
 168         &ufs_dir_operations,    /* default directory file operations */
 169         NULL,                   /* create */
 170         &ufs_lookup,            /* lookup */
 171         NULL,                   /* link */
 172         NULL,                   /* unlink */
 173         NULL,                   /* symlink */
 174         NULL,                   /* mkdir */
 175         NULL,                   /* rmdir */
 176         NULL,                   /* mknod */
 177         NULL,                   /* rename */
 178         NULL,                   /* readlink */
 179         NULL,                   /* follow_link */
 180         NULL,                   /* readpage */
 181         NULL,                   /* writepage */
 182         NULL,                   /* bmap */
 183         NULL,                   /* truncate */
 184         NULL,                   /* permission */
 185         NULL,                   /* smap */
 186 };
 187 
 188 /*
 189  * Local Variables: ***
 190  * c-indent-level: 8 ***
 191  * c-continued-statement-offset: 8 ***
 192  * c-brace-offset: -8 ***
 193  * c-argdecl-indent: 0 ***
 194  * c-label-offset: -8 ***
 195  * End: ***
 196  */

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