Esempio n. 1
0
/* write 'n' bytes from 'buf' in the file referenced by 'fd' */
ssize_t fs_write(struct file_s *flip, char *buf, size_t n)
{
    return fs_readwrite(flip, buf, n, FS_WRITE);
}
Esempio n. 2
0
PRIVATE int uds_perform_write(int minor, endpoint_t m_source,
						size_t size, int pretend)
{
	int rc, peer, i;
	message fs_m_in;
	message fs_m_out;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] uds_perform_write() call_count=%d\n", minor,
							++call_count);
#endif

	/* skip reads and writes of 0 (or less!) bytes */
	if (size <= 0) {
		return 0;
	}

	/* check if we are allowed to write */
	if (!(uds_fd_table[minor].mode & S_IWUSR)) {

		/* socket is shutdown for writing */
		errno = EPIPE;
		return -1;
	}

	if (size > PIPE_BUF) {

		/* message is too big to ever write to the PIPE */
		errno = EMSGSIZE;
		return -1;
	}

	if (uds_fd_table[minor].type == SOCK_STREAM ||
			uds_fd_table[minor].type == SOCK_SEQPACKET) {

		/* if we're writing with a connection oriented socket, 
		 * then it needs a peer to write to
		 */
		if (uds_fd_table[minor].peer == -1) {
			if (uds_fd_table[minor].err == ECONNRESET) {

				uds_fd_table[minor].err = 0;
				errno = ECONNRESET;
			} else {
				errno = ENOTCONN;
			}

			return -1;
		} else {

			peer = uds_fd_table[minor].peer;
		}

	} else /* uds_fd_table[minor].type == SOCK_DGRAM */ {

		peer = -1;

		/* locate the "peer" we want to write to */
		for (i = 0; i < NR_FDS; i++) {

			/* look for a SOCK_DGRAM socket that is bound on 
			 * the target address
			 */
			if (uds_fd_table[i].type == SOCK_DGRAM &&
				uds_fd_table[i].addr.sun_family == AF_UNIX &&
				!strncmp(uds_fd_table[minor].target.sun_path,
				uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {

				peer = i;
				break;
			}
		}

		if (peer == -1) {
			errno = ENOENT;
			return -1;
		}
	}

	/* check if write would overrun buffer. check if message 
	 * boundry preserving types (SEQPACKET and DGRAM) wouldn't write 
	 * to an empty buffer. check if connectionless sockets have a 
	 * target to write to.
	 */
	if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) ||
		((uds_fd_table[minor].type == SOCK_SEQPACKET ||
		uds_fd_table[minor].type == SOCK_DGRAM) && 
		uds_fd_table[peer].size > 0) || (peer == -1)) {

		if (pretend) {
			return SUSPEND;
		}

		/* if needed revive the reader */
		if (uds_fd_table[peer].suspended) {

			uds_fd_table[peer].ready_to_revive = 1;
			notify(m_source);
		}

#if DEBUG == 1
	printf("(uds) [%d] suspending write request\n", minor);
#endif

		/* Process is reading from an empty pipe, 
		 * suspend it so some bytes can be written
		 */
		uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE;
		return SUSPEND;
	}

	if (pretend) {
		return size;
	}

	/* Prepare Request to the FS side of PFS */
	fs_m_in.m_type = REQ_WRITE;
	fs_m_in.REQ_INODE_NR = uds_fd_table[peer].inode_nr;
	fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr;
	fs_m_in.REQ_SEEK_POS_HI = 0;
	fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[peer].pos +
					uds_fd_table[peer].size;
	fs_m_in.REQ_NBYTES = size;

	/* Request the write */
	rc = fs_readwrite(&fs_m_in, &fs_m_out);
	if (rc != OK) {
		perror("fs_readwrite");
		return rc;
	}

	/* Process the response */
#if DEBUG == 1
	printf("(uds) [%d] write complete\n", minor);
#endif
	/* increase the count of unread bytes */
	uds_fd_table[peer].size += fs_m_out.RES_NBYTES;


	/* fill in the source address to be returned by recvfrom & recvmsg */
	if (uds_fd_table[minor].type == SOCK_DGRAM) {
		memcpy(&uds_fd_table[peer].source, &uds_fd_table[minor].addr,
						sizeof(struct sockaddr_un));
	}

	/* revive peer that was waiting for us to write */
	if (uds_fd_table[peer].suspended) {

		uds_fd_table[peer].ready_to_revive = 1;
		notify(m_source);
	}

	/* see if peer is blocked on select()*/
	if (uds_fd_table[peer].selecting == 1 && fs_m_out.RES_NBYTES > 0) {

		/* if the peer wants to know about data ready to read
		 * and it doesn't know about it already, then let the peer
		 * know we have data for it.
		 */
		if ((uds_fd_table[peer].sel_ops_in & SEL_RD) &&
				!(uds_fd_table[peer].sel_ops_out & SEL_RD)) {

			/* a read on peer is possible now */
			uds_fd_table[peer].sel_ops_out |= SEL_RD;
			uds_fd_table[peer].status_updated = 1;
			notify(uds_fd_table[peer].select_proc);
		}
	}

	return fs_m_out.RES_NBYTES; /* return number of bytes written */
}
Esempio n. 3
0
/* read 'n' bytes from a file a put them on buf */
size_t fs_read(struct file_s *flip, char *buf, size_t n)
{
    return fs_readwrite(flip, buf, n, FS_READ);
}
Esempio n. 4
0
PRIVATE int uds_perform_read(int minor, endpoint_t m_source,
	size_t size, int pretend)
{
	int rc;
	message fs_m_in;
	message fs_m_out;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] uds_perform_read() call_count=%d\n", minor,
							++call_count);
#endif

	/* skip reads and writes of 0 (or less!) bytes */
	if (size <= 0) {
		return 0;
	}

	/* check if we are allowed to read */
	if (!(uds_fd_table[minor].mode & S_IRUSR)) {

		/* socket is shutdown for reading */
		errno = EPIPE;
		return -1;
	}

	if (uds_fd_table[minor].size == 0) {

		if (pretend) {
			return SUSPEND;
		}

		/* maybe a process is blocked waiting to write? if 
		 * needed revive the writer
		 */
		if (uds_fd_table[minor].peer != -1 &&
			uds_fd_table[uds_fd_table[minor].peer].suspended) {

			int peer = uds_fd_table[minor].peer;

			uds_fd_table[peer].ready_to_revive = 1;
			notify(m_source);
		}

#if DEBUG == 1
		printf("(uds) [%d] suspending read request\n", minor);
#endif

		/* Process is reading from an empty pipe, 
		 * suspend it so some bytes can be written
		 */
		uds_fd_table[minor].suspended = UDS_SUSPENDED_READ;
		return SUSPEND;
	}

	if (pretend) {

		return (size > uds_fd_table[minor].size) ?
				uds_fd_table[minor].size : size;
	}


	/* Prepare Request to the FS side of PFS */
	fs_m_in.m_type = REQ_READ;
	fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr;
	fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr;
	fs_m_in.REQ_SEEK_POS_HI = 0;
	fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[minor].pos;
	fs_m_in.REQ_NBYTES = (size > uds_fd_table[minor].size) ?
				uds_fd_table[minor].size : size;

	/* perform the read */
	rc = fs_readwrite(&fs_m_in, &fs_m_out);
	if (rc != OK) {
		perror("fs_readwrite");
		return rc;
	}

	/* Process the response */
#if DEBUG == 1
	printf("(uds) [%d] read complete\n", minor);
#endif

	/* move the position of the data pointer up to data we haven't 
	 * read yet
	 */
	uds_fd_table[minor].pos += fs_m_out.RES_NBYTES;

	/* decrease the number of unread bytes */
	uds_fd_table[minor].size -= fs_m_out.RES_NBYTES;

	/* if we have 0 unread bytes, move the data pointer back to the 
	 * start of the buffer
	 */
	if (uds_fd_table[minor].size == 0) {
		uds_fd_table[minor].pos = 0;
	}

	/* maybe a big write was waiting for us to read some data, if 
	 * needed revive the writer
	 */
	if (uds_fd_table[minor].peer != -1 && 
			uds_fd_table[uds_fd_table[minor].peer].suspended) {

		uds_fd_table[uds_fd_table[minor].peer].ready_to_revive = 1;
		notify(m_source);
	}

	/* see if peer is blocked on select() and a write is possible 
	 * (from peer to minor)
	 */
	if (uds_fd_table[minor].peer != -1 && 
		uds_fd_table[uds_fd_table[minor].peer].selecting == 1 &&
		(uds_fd_table[minor].size + uds_fd_table[minor].pos + 1 
		< PIPE_BUF)) {

		int peer = uds_fd_table[minor].peer;

		/* if the peer wants to know about write being possible
		 * and it doesn't know about it already, then let the peer know.
		 */
		if ((uds_fd_table[peer].sel_ops_in & SEL_WR) &&
				!(uds_fd_table[peer].sel_ops_out & SEL_WR)) {

			/* a write on peer is possible now */
			uds_fd_table[peer].sel_ops_out |= SEL_WR;
			uds_fd_table[peer].status_updated = 1;
			notify(uds_fd_table[peer].select_proc);
		}
	}

	return fs_m_out.RES_NBYTES; /* return number of bytes read */
}