Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
static int unix_write(struct socket *sock, char *ubuf, int size, int nonblock)
{
    struct unix_proto_data *pupd;
    int todo, space;

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

    if (sock->state != SS_CONNECTED) {
	if (sock->state == SS_DISCONNECTING) {
	    send_sig(SIGPIPE, current, 1);
	    return -EPIPE;
	}
	return -EINVAL;
    }

    pupd = UN_DATA(sock)->peerupd;	/* safer than sock->conn */

    while (!(space = UN_BUF_SPACE(pupd))) {
	sock->flags |= SO_NOSPACE;

	if (nonblock)
	    return -EAGAIN;

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

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

	if (sock->state == SS_DISCONNECTING) {
	    send_sig(SIGPIPE, current, 1);
	    return -EPIPE;
	}
    }

/*
 *	Copy from the user's buffer to the write buffer,
 *	watching for wraparound. Then we wake up the reader.
 */

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

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

	/*
	 *      We may become disconnected inside this loop, so watch
	 *      for it (peerupd is safe until we close).
	 */

	if (sock->state == SS_DISCONNECTING) {
	    send_sig(SIGPIPE, current, 1);
	    up(&pupd->sem);
	    return -EPIPE;
	}

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

	if (cando > (part = UN_BUF_SIZE - pupd->bp_head))
	    cando = part;

	memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
	pupd->bp_head = (pupd->bp_head + 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, 1);
#endif
	}
	space = UN_BUF_SPACE(pupd);
    } while (todo && space);

    up(&pupd->sem);

    return (size - todo);
}
Ejemplo n.º 6
0
/*
 * we write to our peer's buf. when we connected we ref'd this peer so we
 * are safe that the buffer remains, even after the peer has disconnected,
 * which we check other ways.
 */
static int
unix_proto_write(struct socket *sock, char *ubuf, int size, int nonblock)
{
	struct unix_proto_data *pupd;
	int todo, space;

	if ((todo = size) <= 0)
		return 0;
	if (sock->state != SS_CONNECTED) {
		PRINTK("unix_proto_write: socket not connected\n");
		if (sock->state == SS_DISCONNECTING) {
			send_sig(SIGPIPE,current,1);
			return -EINTR;
		}
		return -EINVAL;
	}
	pupd = UN_DATA(sock)->peerupd;	/* safer than sock->conn */

	while (!(space = UN_BUF_SPACE(pupd))) {
		PRINTK("unix_proto_write: no space left...\n");
		if (nonblock)
			return -EAGAIN;
		interruptible_sleep_on(sock->wait);
		if (current->signal & ~current->blocked) {
			PRINTK("unix_proto_write: interrupted\n");
			return -ERESTARTSYS;
		}
		if (sock->state == SS_DISCONNECTING) {
			PRINTK("unix_proto_write: disconnected (SIGPIPE)\n");
			send_sig(SIGPIPE,current,1);
			return -EINTR;
		}
	}

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

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

		/*
		 * we may become disconnected inside this loop, so watch
		 * for it (peerupd is safe until we close)
		 */
		if (sock->state == SS_DISCONNECTING) {
			send_sig(SIGPIPE,current,1);
			return -EINTR;
		}
		if ((cando = todo) > space)
			cando = space;
		if (cando > (part = BUF_SIZE - pupd->bp_head))
			cando = part;
		PRINTK("unix_proto_write: space=%d, todo=%d, cando=%d\n",
		       space, todo, cando);
		verify_area(ubuf, cando);
		memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
		pupd->bp_head = (pupd->bp_head + cando) & (BUF_SIZE-1);
		ubuf += cando;
		todo -= cando;
		if (sock->state == SS_CONNECTED)
			wake_up(sock->conn->wait);
		space = UN_BUF_SPACE(pupd);
	} while (todo && space);
	return size - todo;
}