This source file includes following definitions.
- sys_readdir
- sys_lseek
- sys_llseek
- sys_read
- sys_write
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
13 #include <asm/segment.h>
14
15
16
17
18
19
20
21
22
23
24
25 asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
26 {
27 int error;
28 struct file * file;
29 struct inode * inode;
30
31 if (fd >= NR_OPEN || !(file = current->files->fd[fd]) ||
32 !(inode = file->f_inode))
33 return -EBADF;
34 error = -ENOTDIR;
35 if (file->f_op && file->f_op->readdir) {
36 int size = count;
37 if (count == 1)
38 size = sizeof(*dirent);
39 error = verify_area(VERIFY_WRITE, dirent, size);
40 if (!error)
41 error = file->f_op->readdir(inode,file,dirent,count);
42 }
43 return error;
44 }
45
46 asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
47 {
48 struct file * file;
49 int tmp = -1;
50
51 if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
52 return -EBADF;
53 if (origin > 2)
54 return -EINVAL;
55 if (file->f_op && file->f_op->lseek)
56 return file->f_op->lseek(file->f_inode,file,offset,origin);
57
58
59 switch (origin) {
60 case 0:
61 tmp = offset;
62 break;
63 case 1:
64 tmp = file->f_pos + offset;
65 break;
66 case 2:
67 if (!file->f_inode)
68 return -EINVAL;
69 tmp = file->f_inode->i_size + offset;
70 break;
71 }
72 if (tmp < 0)
73 return -EINVAL;
74 if (tmp != file->f_pos) {
75 file->f_pos = tmp;
76 file->f_reada = 0;
77 file->f_version = ++event;
78 }
79 return file->f_pos;
80 }
81
82 asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
83 unsigned long offset_low, loff_t * result,
84 unsigned int origin)
85 {
86 struct file * file;
87 loff_t tmp = -1;
88 loff_t offset;
89 int err;
90
91 if (fd >= NR_OPEN || !(file=current->files->fd[fd]) || !(file->f_inode))
92 return -EBADF;
93 if (origin > 2)
94 return -EINVAL;
95 if ((err = verify_area(VERIFY_WRITE, result, sizeof(loff_t))))
96 return err;
97 offset = (loff_t) (((unsigned long long) offset_high << 32) | offset_low);
98
99 switch (origin) {
100 case 0:
101 tmp = offset;
102 break;
103 case 1:
104 tmp = file->f_pos + offset;
105 break;
106 case 2:
107 if (!file->f_inode)
108 return -EINVAL;
109 tmp = file->f_inode->i_size + offset;
110 break;
111 }
112 if (tmp < 0)
113 return -EINVAL;
114 file->f_pos = tmp;
115 file->f_reada = 0;
116 file->f_version = ++event;
117 memcpy_tofs(result, &file->f_pos, sizeof(loff_t));
118 return 0;
119 }
120
121 asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
122 {
123 int error;
124 struct file * file;
125 struct inode * inode;
126
127 if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
128 return -EBADF;
129 if (!(file->f_mode & 1))
130 return -EBADF;
131 if (!file->f_op || !file->f_op->read)
132 return -EINVAL;
133 if (!count)
134 return 0;
135 error = verify_area(VERIFY_WRITE,buf,count);
136 if (error)
137 return error;
138 return file->f_op->read(inode,file,buf,count);
139 }
140
141 asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
142 {
143 int error;
144 struct file * file;
145 struct inode * inode;
146 int written;
147
148 if (fd>=NR_OPEN || !(file=current->files->fd[fd]) || !(inode=file->f_inode))
149 return -EBADF;
150 if (!(file->f_mode & 2))
151 return -EBADF;
152 if (!file->f_op || !file->f_op->write)
153 return -EINVAL;
154 if (!count)
155 return 0;
156 error = verify_area(VERIFY_READ,buf,count);
157 if (error)
158 return error;
159 written = file->f_op->write(inode,file,buf,count);
160
161
162
163
164 if (written > 0 && !suser() && (inode->i_mode & (S_ISUID | S_ISGID))) {
165 struct iattr newattrs;
166 newattrs.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
167 newattrs.ia_valid = ATTR_MODE;
168 notify_change(inode, &newattrs);
169 }
170 return written;
171 }