File: /usr/src/linux/fs/efs/dir.c

1     /*
2      * dir.c
3      *
4      * Copyright (c) 1999 Al Smith
5      */
6     
7     #include <linux/efs_fs.h>
8     
9     static int efs_readdir(struct file *, void *, filldir_t);
10     
11     struct file_operations efs_dir_operations = {
12     	read:		generic_read_dir,
13     	readdir:	efs_readdir,
14     };
15     
16     struct inode_operations efs_dir_inode_operations = {
17     	lookup:		efs_lookup,
18     };
19     
20     static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
21     	struct inode *inode = filp->f_dentry->d_inode;
22     	struct buffer_head *bh;
23     
24     	struct efs_dir		*dirblock;
25     	struct efs_dentry	*dirslot;
26     	efs_ino_t		inodenum;
27     	efs_block_t		block;
28     	int			slot, namelen;
29     	char			*nameptr;
30     
31     	if (inode->i_size & (EFS_DIRBSIZE-1))
32     		printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n");
33     
34     	/* work out where this entry can be found */
35     	block = filp->f_pos >> EFS_DIRBSIZE_BITS;
36     
37     	/* each block contains at most 256 slots */
38     	slot  = filp->f_pos & 0xff;
39     
40     	/* look at all blocks */
41     	while (block < inode->i_blocks) {
42     		/* read the dir block */
43     		bh = bread(inode->i_dev, efs_bmap(inode, block), EFS_DIRBSIZE);
44     
45     		if (!bh) {
46     			printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block);
47     			break;
48     		}
49     
50     		dirblock = (struct efs_dir *) bh->b_data; 
51     
52     		if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
53     			printk(KERN_ERR "EFS: readdir(): invalid directory block\n");
54     			brelse(bh);
55     			break;
56     		}
57     
58     		while (slot < dirblock->slots) {
59     			if (dirblock->space[slot] == 0) {
60     				slot++;
61     				continue;
62     			}
63     
64     			dirslot  = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
65     
66     			inodenum = be32_to_cpu(dirslot->inode);
67     			namelen  = dirslot->namelen;
68     			nameptr  = dirslot->name;
69     
70     #ifdef DEBUG
71     			printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen);
72     #endif
73     			if (namelen > 0) {
74     				/* found the next entry */
75     				filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
76     
77     				/* copy filename and data in dirslot */
78     				filldir(dirent, nameptr, namelen, filp->f_pos, inodenum, DT_UNKNOWN);
79     
80     				/* sanity check */
81     				if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
82     					printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
83     					slot++;
84     					continue;
85     				}
86     
87     				/* store position of next slot */
88     				if (++slot == dirblock->slots) {
89     					slot = 0;
90     					block++;
91     				}
92     				brelse(bh);
93     				filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
94     				return 0;
95     			}
96     			slot++;
97     		}
98     		brelse(bh);
99     
100     		slot = 0;
101     		block++;
102     	}
103     
104     	filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
105     	return 0;
106     }
107     
108