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