diff options
Diffstat (limited to 'fs/qnx4/dir.c')
-rw-r--r-- | fs/qnx4/dir.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c new file mode 100644 index 000000000000..cd66147cca04 --- /dev/null +++ b/fs/qnx4/dir.c | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * QNX4 file system, Linux implementation. | ||
3 | * | ||
4 | * Version : 0.2.1 | ||
5 | * | ||
6 | * Using parts of the xiafs filesystem. | ||
7 | * | ||
8 | * History : | ||
9 | * | ||
10 | * 28-05-1998 by Richard Frowijn : first release. | ||
11 | * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/fs.h> | ||
18 | #include <linux/qnx4_fs.h> | ||
19 | #include <linux/stat.h> | ||
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/buffer_head.h> | ||
22 | |||
23 | |||
24 | static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
25 | { | ||
26 | struct inode *inode = filp->f_dentry->d_inode; | ||
27 | unsigned int offset; | ||
28 | struct buffer_head *bh; | ||
29 | struct qnx4_inode_entry *de; | ||
30 | struct qnx4_link_info *le; | ||
31 | unsigned long blknum; | ||
32 | int ix, ino; | ||
33 | int size; | ||
34 | |||
35 | QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size)); | ||
36 | QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos)); | ||
37 | |||
38 | lock_kernel(); | ||
39 | |||
40 | while (filp->f_pos < inode->i_size) { | ||
41 | blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS ); | ||
42 | bh = sb_bread(inode->i_sb, blknum); | ||
43 | if(bh==NULL) { | ||
44 | printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum); | ||
45 | break; | ||
46 | } | ||
47 | ix = (int)(filp->f_pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK; | ||
48 | while (ix < QNX4_INODES_PER_BLOCK) { | ||
49 | offset = ix * QNX4_DIR_ENTRY_SIZE; | ||
50 | de = (struct qnx4_inode_entry *) (bh->b_data + offset); | ||
51 | size = strlen(de->di_fname); | ||
52 | if (size) { | ||
53 | if ( !( de->di_status & QNX4_FILE_LINK ) && size > QNX4_SHORT_NAME_MAX ) | ||
54 | size = QNX4_SHORT_NAME_MAX; | ||
55 | else if ( size > QNX4_NAME_MAX ) | ||
56 | size = QNX4_NAME_MAX; | ||
57 | |||
58 | if ( ( de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK) ) != 0 ) { | ||
59 | QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname)); | ||
60 | if ( ( de->di_status & QNX4_FILE_LINK ) == 0 ) | ||
61 | ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1; | ||
62 | else { | ||
63 | le = (struct qnx4_link_info*)de; | ||
64 | ino = ( le->dl_inode_blk - 1 ) * | ||
65 | QNX4_INODES_PER_BLOCK + | ||
66 | le->dl_inode_ndx; | ||
67 | } | ||
68 | if (filldir(dirent, de->di_fname, size, filp->f_pos, ino, DT_UNKNOWN) < 0) { | ||
69 | brelse(bh); | ||
70 | goto out; | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | ix++; | ||
75 | filp->f_pos += QNX4_DIR_ENTRY_SIZE; | ||
76 | } | ||
77 | brelse(bh); | ||
78 | } | ||
79 | out: | ||
80 | unlock_kernel(); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | struct file_operations qnx4_dir_operations = | ||
85 | { | ||
86 | .read = generic_read_dir, | ||
87 | .readdir = qnx4_readdir, | ||
88 | .fsync = file_fsync, | ||
89 | }; | ||
90 | |||
91 | struct inode_operations qnx4_dir_inode_operations = | ||
92 | { | ||
93 | .lookup = qnx4_lookup, | ||
94 | #ifdef CONFIG_QNX4FS_RW | ||
95 | .create = qnx4_create, | ||
96 | .unlink = qnx4_unlink, | ||
97 | .rmdir = qnx4_rmdir, | ||
98 | #endif | ||
99 | }; | ||