summaryrefslogtreecommitdiffstats
path: root/fs/qnx4/dir.c
blob: 0fbae7262f8cc55dc51348cd8c5d0ebc2ab840df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/* 
 * QNX4 file system, Linux implementation.
 * 
 * Version : 0.1
 * 
 * Using parts of the xiafs filesystem.
 * 
 * History :
 * 
 * 28-05-1998 by Richard Frowijn : first release.
 * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support.
 */

#include <linux/config.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/qnx4_fs.h>
#include <linux/stat.h>

#include <asm/segment.h>

static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir);

static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
	struct inode *inode = filp->f_dentry->d_inode;
	unsigned int offset;
	struct buffer_head *bh;
	struct qnx4_inode_entry *de;
	long blknum;
	int i;
	int size;

	blknum = inode->u.qnx4_i.i_first_xtnt.xtnt_blk - 1 +
	    ((filp->f_pos >> 6) >> 3);

	QNX4DEBUG(("qnx4_readdir:i_size = %ld\n", (long) inode->i_size));
	QNX4DEBUG(("filp->f_pos         = %ld\n", (long) filp->f_pos));
	QNX4DEBUG(("BlkNum              = %ld\n", (long) blknum));

	while (filp->f_pos < inode->i_size) {
		bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
		if(bh==NULL)
		{
			printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
			break;
		}
		i = (filp->f_pos - (((filp->f_pos >> 6) >> 3) << 9)) & 0x3f;
		while (i < QNX4_INODES_PER_BLOCK) {
			offset = i * QNX4_DIR_ENTRY_SIZE;
			de = (struct qnx4_inode_entry *) (bh->b_data + offset);
			size = strlen(de->di_fname);
			if (size) {

				QNX4DEBUG(("qnx4_readdir:%s\n", de->di_fname));

				if ((de->di_mode) || (de->di_status == QNX4_FILE_LINK)) {
					if (de->di_status) {
						if (filldir(dirent, de->di_fname, size, filp->f_pos, de->di_first_xtnt.xtnt_blk) < 0) {
							brelse(bh);
							return 0;
						}
					}
				}
			}
			i++;
			filp->f_pos += QNX4_DIR_ENTRY_SIZE;
		}
		brelse(bh);
		blknum++;
	}
	UPDATE_ATIME(inode);

	return 0;
}

static struct file_operations qnx4_dir_operations =
{
	NULL,			/* lseek - default */
	NULL,			/* read */
	NULL,			/* write - bad */
	qnx4_readdir,		/* readdir */
	NULL,			/* poll - default */
	NULL,			/* ioctl - default */
	NULL,			/* mmap */
	NULL,			/* no special open code */
        NULL,                   /* no special flush code */
	NULL,			/* no special release code */
	file_fsync,		/* default fsync */
	NULL,			/* default fasync */
	NULL,			/* default check_media_change */
	NULL,			/* default revalidate */
};

struct inode_operations qnx4_dir_inode_operations =
{
	&qnx4_dir_operations,
#ifdef CONFIG_QNX4FS_RW
	qnx4_create,
#else
	NULL,			/* create */
#endif
	qnx4_lookup,
	NULL,			/* link */
#ifdef CONFIG_QNX4FS_RW
	qnx4_unlink,		/* unlink */
#else
	NULL,
#endif
	NULL,			/* symlink */
	NULL,			/* mkdir */
#ifdef CONFIG_QNX4FS_RW
	qnx4_rmdir,		/* rmdir */
#else
	NULL,
#endif
	NULL,			/* mknod */
	NULL,			/* rename */
	NULL,			/* readlink */
	NULL,			/* follow_link */
	NULL,			/* get_block */
	NULL,			/* readpage */
	NULL,			/* writepage */
	NULL,			/* flushpage */
	NULL,			/* truncate */
	NULL,			/* permission */
	NULL,			/* smap */
	NULL			/* revalidate */
};