1 /*
2 * linux/fs/sysv/dir.c
3 *
4 * minix/dir.c
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
7 * coh/dir.c
8 * Copyright (C) 1993 Pascal Haible, Bruno Haible
9 *
10 * sysv/dir.c
11 * Copyright (C) 1993 Bruno Haible
12 *
13 * SystemV/Coherent directory handling functions
14 */
15
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>
21
22 #include <asm/segment.h>
23
24 static int sysv_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
25 {
26 return -EISDIR;
27 }
28
29 static int sysv_readdir(struct inode *, struct file *, void *, filldir_t);
30
31 static struct file_operations sysv_dir_operations = {
32 NULL, /* lseek - default */
33 sysv_dir_read, /* read */
34 NULL, /* write - bad */
35 sysv_readdir, /* readdir */
36 NULL, /* select - default */
37 NULL, /* ioctl - default */
38 NULL, /* mmap */
39 NULL, /* no special open code */
40 NULL, /* no special release code */
41 file_fsync /* default fsync */
42 };
43
44 /*
45 * directories can handle most operations...
46 */
47 struct inode_operations sysv_dir_inode_operations = {
48 &sysv_dir_operations, /* default directory file-ops */
49 sysv_create, /* create */
50 sysv_lookup, /* lookup */
51 sysv_link, /* link */
52 sysv_unlink, /* unlink */
53 sysv_symlink, /* symlink */
54 sysv_mkdir, /* mkdir */
55 sysv_rmdir, /* rmdir */
56 sysv_mknod, /* mknod */
57 sysv_rename, /* rename */
58 NULL, /* readlink */
59 NULL, /* follow_link */
60 NULL, /* readpage */
61 NULL, /* writepage */
62 NULL, /* bmap */
63 sysv_truncate, /* truncate */
64 NULL /* permission */
65 };
66
67 static int sysv_readdir(struct inode * inode, struct file * filp,
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
68 void * dirent, filldir_t filldir)
69 {
70 struct super_block * sb;
71 unsigned int offset,i;
72 struct buffer_head * bh;
73 char* bh_data;
74 struct sysv_dir_entry * de, sde;
75
76 if (!inode || !(sb = inode->i_sb) || !S_ISDIR(inode->i_mode))
77 return -EBADF;
78 if ((unsigned long)(filp->f_pos) % SYSV_DIRSIZE)
79 return -EBADF;
80 while (filp->f_pos < inode->i_size) {
81 offset = filp->f_pos & sb->sv_block_size_1;
82 bh = sysv_file_bread(inode, filp->f_pos >> sb->sv_block_size_bits, 0);
83 if (!bh) {
84 filp->f_pos += sb->sv_block_size - offset;
85 continue;
86 }
87 bh_data = bh->b_data;
88 while (offset < sb->sv_block_size && filp->f_pos < inode->i_size) {
89 de = (struct sysv_dir_entry *) (offset + bh_data);
90 if (de->inode) {
91 /* Copy the directory entry first, because the directory
92 * might be modified while we sleep in filldir()...
93 */
94 memcpy(&sde, de, sizeof(struct sysv_dir_entry));
95
96 if (sde.inode > inode->i_sb->sv_ninodes)
97 printk("sysv_readdir: Bad inode number on dev "
98 "%s, ino %ld, offset 0x%04lx: %d is out of range\n",
99 kdevname(inode->i_dev),
100 inode->i_ino, (off_t) filp->f_pos, sde.inode);
101
102 i = strnlen(sde.name, SYSV_NAMELEN);
103 if (filldir(dirent, sde.name, i, filp->f_pos, sde.inode) < 0) {
104 brelse(bh);
105 return 0;
106 }
107 }
108 offset += SYSV_DIRSIZE;
109 filp->f_pos += SYSV_DIRSIZE;
110 }
111 brelse(bh);
112 }
113 return 0;
114 }