Import 2.3.9pre7
[davej-history.git] / fs / sysv / dir.c
blobd76f1d6b3729a4848fe65393325d2036899957ca
1 /*
2 * linux/fs/sysv/dir.c
4 * minix/dir.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
7 * coh/dir.c
8 * Copyright (C) 1993 Pascal Haible, Bruno Haible
10 * sysv/dir.c
11 * Copyright (C) 1993 Bruno Haible
13 * SystemV/Coherent directory handling functions
16 #include <linux/errno.h>
17 #include <linux/fs.h>
18 #include <linux/sysv_fs.h>
19 #include <linux/stat.h>
20 #include <linux/string.h>
22 #include <asm/uaccess.h>
24 static ssize_t sysv_dir_read(struct file * filp, char * buf,
25 size_t count, loff_t *ppos)
27 return -EISDIR;
30 static int sysv_readdir(struct file *, void *, filldir_t);
32 static struct file_operations sysv_dir_operations = {
33 NULL, /* lseek - default */
34 sysv_dir_read, /* read */
35 NULL, /* write - bad */
36 sysv_readdir, /* readdir */
37 NULL, /* poll - default */
38 NULL, /* ioctl - default */
39 NULL, /* mmap */
40 NULL, /* no special open code */
41 NULL, /* flush */
42 NULL, /* no special release code */
43 file_fsync /* default fsync */
47 * directories can handle most operations...
49 struct inode_operations sysv_dir_inode_operations = {
50 &sysv_dir_operations, /* default directory file-ops */
51 sysv_create, /* create */
52 sysv_lookup, /* lookup */
53 sysv_link, /* link */
54 sysv_unlink, /* unlink */
55 sysv_symlink, /* symlink */
56 sysv_mkdir, /* mkdir */
57 sysv_rmdir, /* rmdir */
58 sysv_mknod, /* mknod */
59 sysv_rename, /* rename */
60 NULL, /* readlink */
61 NULL, /* follow_link */
62 NULL, /* get_block */
63 NULL, /* readpage */
64 NULL, /* writepage */
65 NULL, /* flushpage */
66 NULL, /* truncate */
67 NULL, /* permission */
68 NULL, /* smap */
69 NULL /* revalidate */
72 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir)
74 struct inode *inode = filp->f_dentry->d_inode;
75 struct super_block * sb = inode->i_sb;
76 unsigned int offset,i;
77 struct buffer_head * bh;
78 char* bh_data;
79 struct sysv_dir_entry * de, sde;
81 if ((unsigned long)(filp->f_pos) % SYSV_DIRSIZE)
82 return -EBADF;
83 while (filp->f_pos < inode->i_size) {
84 offset = filp->f_pos & sb->sv_block_size_1;
85 bh = sysv_file_bread(inode, filp->f_pos >> sb->sv_block_size_bits, 0);
86 if (!bh) {
87 filp->f_pos += sb->sv_block_size - offset;
88 continue;
90 bh_data = bh->b_data;
91 while (offset < sb->sv_block_size && filp->f_pos < inode->i_size) {
92 de = (struct sysv_dir_entry *) (offset + bh_data);
93 if (de->inode) {
94 /* Copy the directory entry first, because the directory
95 * might be modified while we sleep in filldir()...
97 memcpy(&sde, de, sizeof(struct sysv_dir_entry));
99 if (sde.inode > inode->i_sb->sv_ninodes)
100 printk("sysv_readdir: Bad inode number on dev "
101 "%s, ino %ld, offset 0x%04lx: %d is out of range\n",
102 kdevname(inode->i_dev),
103 inode->i_ino, (off_t) filp->f_pos, sde.inode);
105 i = strnlen(sde.name, SYSV_NAMELEN);
106 if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode) < 0) {
107 brelse(bh);
108 return 0;
111 offset += SYSV_DIRSIZE;
112 filp->f_pos += SYSV_DIRSIZE;
114 brelse(bh);
116 return 0;