minix/servers/pfs/read.c

97 lines
2.6 KiB
C
Raw Normal View History

2009-12-20 21:41:50 +01:00
#include "fs.h"
#include "buf.h"
#include "inode.h"
#include <minix/com.h>
#include <string.h>
2009-12-20 21:41:50 +01:00
/*===========================================================================*
* fs_readwrite *
*===========================================================================*/
2012-03-25 20:25:53 +02:00
int fs_readwrite(message *fs_m_in, message *fs_m_out)
2009-12-20 21:41:50 +01:00
{
int r, rw_flag;
struct buf *bp;
cp_grant_id_t gid;
off_t position, f_size;
unsigned int nrbytes, cum_io;
pmode_t mode_word;
2009-12-20 21:41:50 +01:00
struct inode *rip;
pino_t inumb;
2009-12-20 21:41:50 +01:00
r = OK;
cum_io = 0;
inumb = (pino_t) fs_m_in->REQ_INODE_NR;
2009-12-20 21:41:50 +01:00
/* Find the inode referred */
if ((rip = find_inode(inumb)) == NULL) return(EINVAL);
2009-12-20 21:41:50 +01:00
mode_word = rip->i_mode & I_TYPE;
if (mode_word != I_NAMED_PIPE) return(EIO);
f_size = rip->i_size;
2012-02-13 16:28:04 +01:00
/* Get the values from the request message */
rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING);
gid = (cp_grant_id_t) fs_m_in->REQ_GRANT;
nrbytes = (unsigned) fs_m_in->REQ_NBYTES;
2010-05-28 11:39:18 +02:00
/* We can't read beyond the max file position */
2013-01-25 12:57:32 +01:00
if (nrbytes > PIPE_BUF) return(EFBIG);
2012-02-13 16:28:04 +01:00
2009-12-20 21:41:50 +01:00
/* Mark inode in use */
if ((get_inode(rip->i_dev, rip->i_num)) == NULL) return(err_code);
if ((bp = get_block(rip->i_dev, rip->i_num)) == NULL) return(err_code);
2009-12-20 21:41:50 +01:00
if (rw_flag == WRITING) {
/* Check in advance to see if file will grow too big. */
/* Casting nrbytes to signed is safe, because it's guaranteed not to
* be beyond max signed value (i.e., MAX_FILE_POS).
*/
position = rip->i_size;
2013-01-25 12:57:32 +01:00
if ((unsigned) position + nrbytes > PIPE_BUF) {
put_inode(rip);
put_block(rip->i_dev, rip->i_num);
return(EFBIG);
}
} else {
position = 0;
if (nrbytes > rip->i_size) {
/* There aren't that many bytes to read */
nrbytes = rip->i_size;
}
}
2009-12-20 21:41:50 +01:00
if (rw_flag == READING) {
/* Copy a chunk from the block buffer to user space. */
r = sys_safecopyto(fs_m_in->m_source, gid, (vir_bytes) 0,
(vir_bytes) (bp->b_data+position), (size_t) nrbytes);
2009-12-20 21:41:50 +01:00
} else {
/* Copy a chunk from user space to the block buffer. */
r = sys_safecopyfrom(fs_m_in->m_source, gid, (vir_bytes) 0,
(vir_bytes) (bp->b_data+position), (size_t) nrbytes);
2009-12-20 21:41:50 +01:00
}
if (r == OK) {
2010-05-28 11:39:18 +02:00
position += (signed) nrbytes; /* Update position */
2009-12-20 21:41:50 +01:00
cum_io += nrbytes;
}
/* On write, update file size and access time. */
if (rw_flag == WRITING) {
rip->i_size = position;
2009-12-20 21:41:50 +01:00
} else {
memmove(bp->b_data, bp->b_data+nrbytes, rip->i_size - nrbytes);
rip->i_size -= nrbytes;
2009-12-20 21:41:50 +01:00
}
if (rw_flag == READING) rip->i_update |= ATIME;
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
fs_m_out->RES_NBYTES = (size_t) cum_io;
fs_m_out->RES_SEEK_POS_LO = rip->i_size;
2009-12-20 21:41:50 +01:00
put_inode(rip);
put_block(rip->i_dev, rip->i_num);
return(r);
}