Example #1
0
static int
unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct unix_proto_data *upd, *peerupd;

	upd = UN_DATA(sock);
	peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;

	switch (cmd) {
	case TIOCINQ:
		verify_area((void *)arg, sizeof(unsigned long));
		if (UN_BUF_AVAIL(upd) || peerupd)
			put_fs_long(UN_BUF_AVAIL(upd), (unsigned long *)arg);
		else
			put_fs_long(1, (unsigned long *)arg); /* read EOF */
		break;

	case TIOCOUTQ:
		verify_area((void *)arg, sizeof(unsigned long));
		if (peerupd)
			put_fs_long(UN_BUF_SPACE(peerupd),
				    (unsigned long *)arg);
		else
			put_fs_long(0, (unsigned long *)arg);
		break;

	default:
		return -EINVAL;
	}
	return 0;
}
Example #2
0
static int
unix_proto_select(struct socket *sock, int which)
{
	struct unix_proto_data *upd, *peerupd;

	if (which == SEL_IN) {
		upd = UN_DATA(sock);
		PRINTK("unix_proto_select: there is%s data available\n",
		       UN_BUF_AVAIL(upd) ? "" : " no");
		if (UN_BUF_AVAIL(upd))	/* even if disconnected */
			return 1;
		else if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_select: socket not connected (read EOF)\n");
			return 1;
		}
		else
			return 0;
	}
	if (which == SEL_OUT) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_select: socket not connected (write EOF)\n");
			return 1;
		}
		peerupd = UN_DATA(sock->conn);
		PRINTK("unix_proto_select: there is%s space available\n",
		       UN_BUF_SPACE(peerupd) ? "" : " no");
		return (UN_BUF_SPACE(peerupd) > 0);
	}
	/* SEL_EX */
	PRINTK("unix_proto_select: there are no exceptions here?!\n");
	return 0;
}
Example #3
0
/*
 * we read from our own buf.
 */
static int
unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
{
	struct unix_proto_data *upd;
	int todo, avail;

	if ((todo = size) <= 0)
		return 0;
	upd = UN_DATA(sock);
	while (!(avail = UN_BUF_AVAIL(upd))) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_read: socket not connected\n");
			return (sock->state == SS_DISCONNECTING) ? 0 : -EINVAL;
		}
		PRINTK("unix_proto_read: no data available...\n");
		if (nonblock)
			return -EAGAIN;
		interruptible_sleep_on(sock->wait);
		if (current->signal & ~current->blocked) {
			PRINTK("unix_proto_read: interrupted\n");
			return -ERESTARTSYS;
		}
		if (sock->state == SS_DISCONNECTING) {
			PRINTK("unix_proto_read: disconnected\n");
			return 0;
		}
	}

	/*
	 * copy from the read buffer into the user's buffer, watching for
	 * wraparound. then we wake up the writer
	 */
	do {
		int part, cando;

		if (avail <= 0) {
			PRINTK("unix_proto_read: AVAIL IS NEGATIVE!!!\n");
			send_sig(SIGKILL,current,1);
			return -EINTR;
		}

		if ((cando = todo) > avail)
			cando = avail;
		if (cando > (part = BUF_SIZE - upd->bp_tail))
			cando = part;
		PRINTK("unix_proto_read: avail=%d, todo=%d, cando=%d\n",
		       avail, todo, cando);
		verify_area(ubuf, cando);
		memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
		upd->bp_tail = (upd->bp_tail + cando) & (BUF_SIZE-1);
		ubuf += cando;
		todo -= cando;
		if (sock->state == SS_CONNECTED)
			wake_up(sock->conn->wait);
		avail = UN_BUF_AVAIL(upd);
	} while (todo && avail);
	return size - todo;
}
Example #4
0
static int
unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
{
	struct unix_proto_data *upd, *peerupd;

	/*
	 * handle server sockets specially
	 */
	if (sock->flags & SO_ACCEPTCON) {
		if (sel_type == SEL_IN) {
			PRINTK("sock_select: %sconnections pending\n",
			       sock->iconn ? "" : "no ");
			if (sock->iconn)
				return 1;
			select_wait(sock->wait, wait);
			return sock->iconn ? 1 : 0;
		}
		PRINTK("sock_select: nothing else for server socket\n");
		select_wait(sock->wait, wait);
		return 0;
	}

	if (sel_type == SEL_IN) {
		upd = UN_DATA(sock);
		PRINTK("unix_proto_select: there is%s data available\n",
		       UN_BUF_AVAIL(upd) ? "" : " no");
		if (UN_BUF_AVAIL(upd))	/* even if disconnected */
			return 1;
		else if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_select: socket not connected (read EOF)\n");
			return 1;
		}
		select_wait(sock->wait,wait);
		return 0;
	}
	if (sel_type == SEL_OUT) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_select: socket not connected (write EOF)\n");
			return 1;
		}
		peerupd = UN_DATA(sock->conn);
		PRINTK("unix_proto_select: there is%s space available\n",
		       UN_BUF_SPACE(peerupd) ? "" : " no");
		if (UN_BUF_SPACE(peerupd) > 0)
			return 1;
		select_wait(sock->wait,wait);
		return 0;
	}
	/* SEL_EX */
	PRINTK("unix_proto_select: there are no exceptions here?!\n");
	return 0;
}
Example #5
0
static int unix_select(struct socket *sock, int sel_type, select_table * wait)
{
    struct unix_proto_data *upd, *peerupd;

    /* 
     *      Handle server sockets specially.
     */

    if (sock->flags & SO_ACCEPTCON) {
	if (sel_type == SEL_IN) {

	    if (sock->iconn)
		return 1;

	    select_wait(sock->wait, wait);

	    return (sock->iconn ? 1 : 0);
	}
	select_wait(sock->wait, wait);

	return 0;
    }

    if (sel_type == SEL_IN) {
	upd = UN_DATA(sock);

	if (UN_BUF_AVAIL(upd))	/* even if disconnected */
	    return 1;

	else if (sock->state != SS_CONNECTED)
	    return 1;

	select_wait(sock->wait, wait);

	return 0;
    }

    if (sel_type == SEL_OUT) {

	if (sock->state != SS_CONNECTED)
	    return 1;

	peerupd = UN_DATA(sock->conn);

	if (UN_BUF_SPACE(peerupd) > 0)
	    return 1;

	select_wait(sock->wait, wait);

	return 0;
    }

    /*
     * Exceptions - SEL_EX 
     */

    return 0;
}
Example #6
0
static int unix_read(struct socket *sock, char *ubuf, int size, int nonblock)
{
    struct unix_proto_data *upd;
    int todo, avail;

    if ((todo = size) <= 0)
	return 0;

    upd = UN_DATA(sock);

    while (!(avail = UN_BUF_AVAIL(upd))) {
	if (sock->state != SS_CONNECTED)
	    return ((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);

	if (nonblock)
	    return -EAGAIN;

	sock->flags |= SO_WAITDATA;
	interruptible_sleep_on(sock->wait);
	sock->flags &= ~SO_WAITDATA;

	if (current->signal /* & ~current->blocked */ )
	    return -ERESTARTSYS;
    }

/*
 *	Copy from the read buffer into the user's buffer,
 *	watching for wraparound. Then we wake up the writer.
 */

    down(&upd->sem);
    do {
	int part, cando;

	if (avail <= 0) {
	    printk("UNIX: read: AVAIL IS NEGATIVE (%d)!!!\n", avail);
	    send_sig(SIGKILL, current, 1);
	    return -EPIPE;
	}

	if ((cando = todo) > avail)
	    cando = avail;

	if (cando > (part = UN_BUF_SIZE - upd->bp_tail))
	    cando = part;

	memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
	upd->bp_tail = (upd->bp_tail + cando) & (UN_BUF_SIZE - 1);
	ubuf += cando;
	todo -= cando;

	if (sock->state == SS_CONNECTED) {
	    wake_up_interruptible(sock->conn->wait);
#if 0
	    sock_wake_async(sock->conn, 2);
#endif
	}
	avail = UN_BUF_AVAIL(upd);
    } while (todo && avail);

    up(&upd->sem);

    return (size - todo);
}