This source file includes following definitions.
- fillonedir
- old_readdir
- filldir
- sys_getdents
1
2
3
4
5
6
7 #include <linux/types.h>
8 #include <linux/errno.h>
9 #include <linux/stat.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/mm.h>
13
14 #include <asm/segment.h>
15
16
17
18
19
20
21
22
23
24 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
25 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
26
27 struct old_linux_dirent {
28 unsigned long d_ino;
29 unsigned long d_offset;
30 unsigned short d_namlen;
31 char d_name[1];
32 };
33
34 struct readdir_callback {
35 struct old_linux_dirent * dirent;
36 int count;
37 };
38
39 static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
40 {
41 struct readdir_callback * buf = (struct readdir_callback *) __buf;
42 struct old_linux_dirent * dirent;
43
44 if (buf->count)
45 return -EINVAL;
46 buf->count++;
47 dirent = buf->dirent;
48 put_user(ino, &dirent->d_ino);
49 put_user(offset, &dirent->d_offset);
50 put_user(namlen, &dirent->d_namlen);
51 memcpy_tofs(dirent->d_name, name, namlen);
52 put_user(0, dirent->d_name + namlen);
53 return 0;
54 }
55
56 asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count)
57 {
58 int error;
59 struct file * file;
60 struct readdir_callback buf;
61
62 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
63 return -EBADF;
64 if (!file->f_op || !file->f_op->readdir)
65 return -ENOTDIR;
66 error = verify_area(VERIFY_WRITE, dirent, sizeof(struct old_linux_dirent));
67 if (error)
68 return error;
69 buf.count = 0;
70 buf.dirent = dirent;
71 error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
72 if (error < 0)
73 return error;
74 return buf.count;
75 }
76
77
78
79
80
81 struct linux_dirent {
82 unsigned long d_ino;
83 unsigned long d_off;
84 unsigned short d_reclen;
85 char d_name[1];
86 };
87
88 struct getdents_callback {
89 struct linux_dirent * current;
90 struct linux_dirent * previous;
91 int count;
92 int error;
93 };
94
95 static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
96 {
97 struct linux_dirent * dirent;
98 struct getdents_callback * buf = (struct getdents_callback *) __buf;
99 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
100
101 buf->error = -EINVAL;
102 if (reclen > buf->count)
103 return -EINVAL;
104 dirent = buf->previous;
105 if (dirent)
106 put_user(offset, &dirent->d_off);
107 dirent = buf->current;
108 buf->previous = dirent;
109 put_user(ino, &dirent->d_ino);
110 put_user(reclen, &dirent->d_reclen);
111 memcpy_tofs(dirent->d_name, name, namlen);
112 put_user(0, dirent->d_name + namlen);
113 ((char *) dirent) += reclen;
114 buf->current = dirent;
115 buf->count -= reclen;
116 return 0;
117 }
118
119 asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count)
120 {
121 struct file * file;
122 struct linux_dirent * lastdirent;
123 struct getdents_callback buf;
124 int error;
125
126 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
127 return -EBADF;
128 if (!file->f_op || !file->f_op->readdir)
129 return -ENOTDIR;
130 error = verify_area(VERIFY_WRITE, dirent, count);
131 if (error)
132 return error;
133 buf.current = (struct linux_dirent *) dirent;
134 buf.previous = NULL;
135 buf.count = count;
136 buf.error = 0;
137 error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
138 if (error < 0)
139 return error;
140 lastdirent = buf.previous;
141 if (!lastdirent)
142 return buf.error;
143 put_user(file->f_pos, &lastdirent->d_off);
144 return count - buf.count;
145 }