root/fs/ufs/ufs_dir.c

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

DEFINITIONS

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

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