2 * linux/fs/read_write.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
7 #include <linux/malloc.h>
8 #include <linux/stat.h>
9 #include <linux/fcntl.h>
10 #include <linux/file.h>
11 #include <linux/uio.h>
12 #include <linux/smp_lock.h>
14 #include <asm/uaccess.h>
16 struct file_operations generic_ro_fops
= {
17 read
: generic_file_read
,
18 mmap
: generic_file_mmap
,
21 ssize_t
generic_read_dir(struct file
*filp
, char *buf
, size_t siz
, loff_t
*ppos
)
26 loff_t
default_llseek(struct file
*file
, loff_t offset
, int origin
)
32 offset
+= file
->f_dentry
->d_inode
->i_size
;
35 offset
+= file
->f_pos
;
39 if (offset
!= file
->f_pos
) {
42 file
->f_version
= ++event
;
49 static inline loff_t
llseek(struct file
*file
, loff_t offset
, int origin
)
51 loff_t (*fn
)(struct file
*, loff_t
, int);
55 if (file
->f_op
&& file
->f_op
->llseek
)
56 fn
= file
->f_op
->llseek
;
58 retval
= fn(file
, offset
, origin
);
63 asmlinkage off_t
sys_lseek(unsigned int fd
, off_t offset
, unsigned int origin
)
74 loff_t res
= llseek(file
, offset
, origin
);
76 if (res
!= (loff_t
)retval
)
77 retval
= -EOVERFLOW
; /* LFS: should only happen on 32 bit platforms */
84 #if !defined(__alpha__)
85 asmlinkage
long sys_llseek(unsigned int fd
, unsigned long offset_high
,
86 unsigned long offset_low
, loff_t
* result
,
101 offset
= llseek(file
, ((loff_t
) offset_high
<< 32) | offset_low
,
104 retval
= (int)offset
;
107 if (!copy_to_user(result
, &offset
, sizeof(offset
)))
117 asmlinkage ssize_t
sys_read(unsigned int fd
, char * buf
, size_t count
)
125 if (file
->f_mode
& FMODE_READ
) {
126 ret
= locks_verify_area(FLOCK_VERIFY_READ
, file
->f_dentry
->d_inode
,
127 file
, file
->f_pos
, count
);
129 ssize_t (*read
)(struct file
*, char *, size_t, loff_t
*);
131 if (file
->f_op
&& (read
= file
->f_op
->read
) != NULL
)
132 ret
= read(file
, buf
, count
, &file
->f_pos
);
140 asmlinkage ssize_t
sys_write(unsigned int fd
, const char * buf
, size_t count
)
148 if (file
->f_mode
& FMODE_WRITE
) {
149 struct inode
*inode
= file
->f_dentry
->d_inode
;
150 ret
= locks_verify_area(FLOCK_VERIFY_WRITE
, inode
, file
,
153 ssize_t (*write
)(struct file
*, const char *, size_t, loff_t
*);
155 if (file
->f_op
&& (write
= file
->f_op
->write
) != NULL
)
156 ret
= write(file
, buf
, count
, &file
->f_pos
);
165 static ssize_t
do_readv_writev(int type
, struct file
*file
,
166 const struct iovec
* vector
,
169 typedef ssize_t (*io_fn_t
)(struct file
*, char *, size_t, loff_t
*);
170 typedef ssize_t (*iov_fn_t
)(struct file
*, const struct iovec
*, unsigned long, loff_t
*);
173 struct iovec iovstack
[UIO_FASTIOV
];
174 struct iovec
*iov
=iovstack
;
181 * First get the "struct iovec" from user memory and
182 * verify all the pointers
188 if (count
> UIO_MAXIOV
)
192 if (count
> UIO_FASTIOV
) {
194 iov
= kmalloc(count
*sizeof(struct iovec
), GFP_KERNEL
);
199 if (copy_from_user(iov
, vector
, count
*sizeof(*vector
)))
202 /* BSD readv/writev returns EINVAL if one of the iov_len
203 values < 0 or tot_len overflowed a 32-bit integer. -ink */
206 for (i
= 0 ; i
< count
; i
++) {
207 size_t tmp
= tot_len
;
208 int len
= iov
[i
].iov_len
;
212 if (tot_len
< tmp
|| tot_len
< (u32
)len
)
216 inode
= file
->f_dentry
->d_inode
;
217 /* VERIFY_WRITE actually means a read, as we write to user space */
218 ret
= locks_verify_area((type
== VERIFY_WRITE
219 ? FLOCK_VERIFY_READ
: FLOCK_VERIFY_WRITE
),
220 inode
, file
, file
->f_pos
, tot_len
);
223 fnv
= (type
== VERIFY_WRITE
? file
->f_op
->readv
: file
->f_op
->writev
);
225 ret
= fnv(file
, iov
, count
, &file
->f_pos
);
229 /* VERIFY_WRITE actually means a read, as we write to user space */
230 fn
= (type
== VERIFY_WRITE
? file
->f_op
->read
:
231 (io_fn_t
) file
->f_op
->write
);
240 base
= vector
->iov_base
;
241 len
= vector
->iov_len
;
245 nr
= fn(file
, base
, len
, &file
->f_pos
);
263 asmlinkage ssize_t
sys_readv(unsigned long fd
, const struct iovec
* vector
,
274 if (file
->f_op
&& (file
->f_mode
& FMODE_READ
) &&
275 (file
->f_op
->readv
|| file
->f_op
->read
))
276 ret
= do_readv_writev(VERIFY_WRITE
, file
, vector
, count
);
283 asmlinkage ssize_t
sys_writev(unsigned long fd
, const struct iovec
* vector
,
294 if (file
->f_op
&& (file
->f_mode
& FMODE_WRITE
) &&
295 (file
->f_op
->writev
|| file
->f_op
->write
))
296 ret
= do_readv_writev(VERIFY_READ
, file
, vector
, count
);
303 /* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
304 lseek back to original location. They fail just like lseek does on
305 non-seekable files. */
307 asmlinkage ssize_t
sys_pread(unsigned int fd
, char * buf
,
308 size_t count
, loff_t pos
)
312 ssize_t (*read
)(struct file
*, char *, size_t, loff_t
*);
318 if (!(file
->f_mode
& FMODE_READ
))
320 ret
= locks_verify_area(FLOCK_VERIFY_READ
, file
->f_dentry
->d_inode
,
325 if (!file
->f_op
|| !(read
= file
->f_op
->read
))
329 ret
= read(file
, buf
, count
, &pos
);
336 asmlinkage ssize_t
sys_pwrite(unsigned int fd
, const char * buf
,
337 size_t count
, loff_t pos
)
341 ssize_t (*write
)(struct file
*, const char *, size_t, loff_t
*);
347 if (!(file
->f_mode
& FMODE_WRITE
))
349 ret
= locks_verify_area(FLOCK_VERIFY_WRITE
, file
->f_dentry
->d_inode
,
354 if (!file
->f_op
|| !(write
= file
->f_op
->write
))
359 ret
= write(file
, buf
, count
, &pos
);