goto out;
if (pos < 0)
goto out;
+ ret = -ESPIPE;
+ if (!(file->f_mode & FMODE_PREAD))
+ goto out;
ret = read(file, buf, count, &pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_ACCESS);
if (pos < 0)
goto out;
+ ret = -ESPIPE;
+ if (!(file->f_mode & FMODE_PWRITE))
+ goto out;
+
ret = write(file, buf, count, &pos);
if (ret > 0)
dnotify_parent(file->f_dentry, DN_MODIFY);
goto err_nocleanup;
}
filp->f_version = 0;
- filp->f_mode &= ~FMODE_LSEEK;
+
+ /* We can only do regular read/write on fifos */
+ filp->f_mode &= (FMODE_READ | FMODE_WRITE);
switch (filp->f_mode) {
case 1:
memset(filp, 0, sizeof(*filp));
eventpoll_init_file(filp);
filp->f_flags = flags;
- filp->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK;
+ filp->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
atomic_set(&filp->f_count, 1);
filp->f_dentry = dentry;
filp->f_mapping = dentry->d_inode->i_mapping;
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
status = get_write_access(filp->f_dentry->d_inode);
- if (!status)
- filp->f_mode = FMODE_WRITE | FMODE_LSEEK;
- else
+ if (status)
return nfserrno(status);
+ filp->f_mode = (filp->f_mode | FMODE_WRITE) & ~FMODE_READ;
}
return nfs_ok;
}
{
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
put_write_access(filp->f_dentry->d_inode);
- filp->f_mode = FMODE_READ | FMODE_LSEEK;
+ filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
}
}
if (!f)
goto cleanup_dentry;
f->f_flags = flags;
- f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK;
+ f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
inode = dentry->d_inode;
if (f->f_mode & FMODE_WRITE) {
error = get_write_access(inode);
struct iovec *iov = (struct iovec *)_iov;
size_t total_len;
- /* pread is not allowed on pipes. */
- if (unlikely(ppos != &filp->f_pos))
- return -ESPIPE;
-
total_len = iov_length(iov, nr_segs);
/* Null read succeeds. */
if (unlikely(total_len == 0))
struct iovec *iov = (struct iovec *)_iov;
size_t total_len;
- /* pwrite is not allowed on pipes. */
- if (unlikely(ppos != &filp->f_pos))
- return -ESPIPE;
-
total_len = iov_length(iov, nr_segs);
/* Null write succeeds. */
if (unlikely(total_len == 0))
file = fget_light(fd, &fput_needed);
if (file) {
ret = -ESPIPE;
- if (file->f_mode & FMODE_LSEEK)
+ if (file->f_mode & FMODE_PREAD)
ret = vfs_read(file, buf, count, &pos);
fput_light(file, fput_needed);
}
file = fget_light(fd, &fput_needed);
if (file) {
ret = -ESPIPE;
- if (file->f_mode & FMODE_LSEEK)
+ if (file->f_mode & FMODE_PWRITE)
ret = vfs_write(file, buf, count, &pos);
fput_light(file, fput_needed);
}
sema_init(&p->sem, 1);
p->op = op;
file->private_data = p;
+
+ /* SEQ files support lseek, but not pread/pwrite */
+ file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
return 0;
}
EXPORT_SYMBOL(seq_open);
void *p;
int err = 0;
- if (ppos != &file->f_pos)
- return -EPIPE;
-
down(&m->sem);
/* grab buffer if we didn't have one */
if (!m->buf) {
#define FMODE_READ 1
#define FMODE_WRITE 2
-#define FMODE_LSEEK 4 /* Internal kernel extension */
+
+/* Internal kernel extensions */
+#define FMODE_LSEEK 4
+#define FMODE_PREAD 8
+#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */
#define RW_MASK 1
#define RWA_MASK 2