Import 2.1.55pre1
[davej-history.git] / fs / ufs / ufs_dir.c
blobe91847df34611397f951eb310b1b99bba385e6cd
1 /*
2 * linux/fs/ufs/ufs_dir.c
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
9 * $Id: ufs_dir.c,v 1.10 1997/06/05 01:29:06 davem Exp $
13 #include <linux/fs.h>
14 #include <linux/ufs_fs.h>
17 * This is blatantly stolen from ext2fs
19 static int
20 ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
22 struct inode *inode = filp->f_dentry->d_inode;
23 int error = 0;
24 unsigned long offset, lblk, blk;
25 int i, stored;
26 struct buffer_head * bh;
27 struct ufs_direct * de;
28 struct super_block * sb;
30 if (!inode || !S_ISDIR(inode->i_mode))
31 return -EBADF;
32 sb = inode->i_sb;
34 if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
35 printk("ufs_readdir: ino %lu f_pos %lu\n",
36 inode->i_ino, (unsigned long) filp->f_pos);
37 ufs_print_inode(inode);
40 stored = 0;
41 bh = NULL;
42 offset = filp->f_pos & (sb->s_blocksize - 1);
44 while (!error && !stored && filp->f_pos < inode->i_size) {
45 lblk = (filp->f_pos) >> sb->s_blocksize_bits;
46 /* XXX - ufs_bmap() call needs error checking */
47 blk = ufs_bmap(inode, lblk);
48 bh = bread (sb->s_dev, blk, sb->s_blocksize);
49 if (!bh) {
50 /* XXX - error - skip to the next block */
51 printk("ufs_readdir: dir inode %lu has a hole at offset %lu\n",
52 inode->i_ino, (unsigned long int)filp->f_pos);
53 filp->f_pos += sb->s_blocksize - offset;
54 continue;
57 revalidate:
58 /* If the dir block has changed since the last call to
59 * readdir(2), then we might be pointing to an invalid
60 * dirent right now. Scan from the start of the block
61 * to make sure. */
62 if (filp->f_version != inode->i_version) {
63 for (i = 0; i < sb->s_blocksize && i < offset; ) {
64 de = (struct ufs_direct *)
65 (bh->b_data + i);
66 /* It's too expensive to do a full
67 * dirent test each time round this
68 * loop, but we do have to test at
69 * least that it is non-zero. A
70 * failure will be detected in the
71 * dirent test below. */
72 if (ufs_swab16(de->d_reclen) < 1)
73 break;
74 i += ufs_swab16(de->d_reclen);
76 offset = i;
77 filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
78 | offset;
79 filp->f_version = inode->i_version;
82 while (!error && filp->f_pos < inode->i_size
83 && offset < sb->s_blocksize) {
84 de = (struct ufs_direct *) (bh->b_data + offset);
85 /* XXX - put in a real ufs_check_dir_entry() */
86 if ((ufs_swab16(de->d_reclen) == 0)
87 || (ufs_swab16(de->d_namlen) == 0)) {
88 filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize;
89 brelse(bh);
90 return stored;
92 #if 0
93 if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
94 bh, offset)) {
95 /* On error, skip the f_pos to the
96 next block. */
97 filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1))
98 + sb->s_blocksize;
99 brelse (bh);
100 return stored;
102 #endif /* XXX */
103 offset += ufs_swab16(de->d_reclen);
104 if (ufs_swab32(de->d_ino)) {
105 /* We might block in the next section
106 * if the data destination is
107 * currently swapped out. So, use a
108 * version stamp to detect whether or
109 * not the directory has been modified
110 * during the copy operation. */
111 unsigned long version = inode->i_version;
113 if (inode->i_sb->u.ufs_sb.s_flags & UFS_DEBUG) {
114 printk("ufs_readdir: filldir(%s,%u)\n",
115 de->d_name, ufs_swab32(de->d_ino));
117 error = filldir(dirent, de->d_name, ufs_swab16(de->d_namlen), filp->f_pos, ufs_swab32(de->d_ino));
118 if (error)
119 break;
120 if (version != inode->i_version)
121 goto revalidate;
122 stored ++;
124 filp->f_pos += ufs_swab16(de->d_reclen);
126 offset = 0;
127 brelse (bh);
129 #if 0 /* XXX */
130 if (!IS_RDONLY(inode)) {
131 inode->i_atime = CURRENT_TIME;
132 inode->i_dirt = 1;
134 #endif /* XXX */
135 return 0;
138 static struct file_operations ufs_dir_operations = {
139 NULL, /* lseek */
140 NULL, /* read */
141 NULL, /* write */
142 ufs_readdir, /* readdir */
143 NULL, /* poll */
144 NULL, /* ioctl */
145 NULL, /* mmap */
146 NULL, /* open */
147 NULL, /* release */
148 file_fsync, /* fsync */
149 NULL, /* fasync */
150 NULL, /* check_media_change */
151 NULL, /* revalidate */
154 struct inode_operations ufs_dir_inode_operations = {
155 &ufs_dir_operations, /* default directory file operations */
156 NULL, /* create */
157 ufs_lookup, /* lookup */
158 NULL, /* link */
159 NULL, /* unlink */
160 NULL, /* symlink */
161 NULL, /* mkdir */
162 NULL, /* rmdir */
163 NULL, /* mknod */
164 NULL, /* rename */
165 NULL, /* readlink */
166 NULL, /* readpage */
167 NULL, /* writepage */
168 NULL, /* bmap */
169 NULL, /* truncate */
170 NULL, /* permission */
171 NULL, /* smap */