Exemplo n.º 1
0
void
conn_write_dispatch(int fd, short event, void *arg)
{
	struct connection *c = arg;
	ssize_t n;
	int error;
	socklen_t len;

	if (!(event & EV_WRITE)) {
		log_debug("spurious write call");
		return;
	}

	switch (c->state) {
	case CONN_XPT_WAIT:
		len = sizeof(error);
		if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR,
		    &error, &len) == -1 || (errno = error)) {
			log_warn("connect to %s failed",
			    log_sockaddr(&c->config.TargetAddr));
			conn_fsm(c, CONN_EV_FAIL);
			return;
		}
		conn_fsm(c, CONN_EV_CONNECTED);
		break;
	default:
		if ((n = pdu_write(c)) == -1) {
			log_warn("pdu_write");
			conn_fsm(c, CONN_EV_FAIL);
			return;
		}
		if (n == 0) {    /* connection closed */
			conn_fsm(c, CONN_EV_CLOSED);
			return;
		}

		/* check if there is more to send */
		if (pdu_pending(c))
			event_add(&c->wev, NULL);
	}
}
Exemplo n.º 2
0
int
p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
              va_list ap)
{
    const char *ptr;
    int errcode = 0;

    for (ptr = fmt; *ptr; ptr++) {
        switch (*ptr) {
        case 'b': {
            int8_t val = va_arg(ap, int);
            if (pdu_write(pdu, &val, sizeof(val)))
                errcode = -EFAULT;
        }
        break;
        case 'w': {
            __le16 val = cpu_to_le16(va_arg(ap, int));
            if (pdu_write(pdu, &val, sizeof(val)))
                errcode = -EFAULT;
        }
        break;
        case 'd': {
            __le32 val = cpu_to_le32(va_arg(ap, int32_t));
            if (pdu_write(pdu, &val, sizeof(val)))
                errcode = -EFAULT;
        }
        break;
        case 'q': {
            __le64 val = cpu_to_le64(va_arg(ap, int64_t));
            if (pdu_write(pdu, &val, sizeof(val)))
                errcode = -EFAULT;
        }
        break;
        case 's': {
            const char *sptr = va_arg(ap, const char *);
            int16_t len = 0;
            if (sptr)
                len = MIN(strlen(sptr), USHRT_MAX);

            errcode = p9pdu_writef(pdu, proto_version,
                                   "w", len);
            if (!errcode && pdu_write(pdu, sptr, len))
                errcode = -EFAULT;
        }
        break;
        case 'Q': {
            const struct p9_qid *qid =
                va_arg(ap, const struct p9_qid *);
            errcode =
                p9pdu_writef(pdu, proto_version, "bdq",
                             qid->type, qid->version,
                             qid->path);
        }
        break;
        case 'S': {
            const struct p9_wstat *stbuf =
                va_arg(ap, const struct p9_wstat *);
            errcode =
                p9pdu_writef(pdu, proto_version,
                             "wwdQdddqssss?sddd",
                             stbuf->size, stbuf->type,
                             stbuf->dev, &stbuf->qid,
                             stbuf->mode, stbuf->atime,
                             stbuf->mtime, stbuf->length,
                             stbuf->name, stbuf->uid,
                             stbuf->gid, stbuf->muid,
                             stbuf->extension, stbuf->n_uid,
                             stbuf->n_gid, stbuf->n_muid);
        }
        break;
        case 'D': {
            int32_t count = va_arg(ap, int32_t);
            const void *data = va_arg(ap, const void *);

            errcode = p9pdu_writef(pdu, proto_version, "d",
                                   count);
            if (!errcode && pdu_write(pdu, data, count))
                errcode = -EFAULT;
        }
        break;
        case 'U': {
            int32_t count = va_arg(ap, int32_t);
            const char __user *udata =
                va_arg(ap, const void __user *);
            errcode = p9pdu_writef(pdu, proto_version, "d",
                                   count);
            if (!errcode && pdu_write_u(pdu, udata, count))
                errcode = -EFAULT;
        }
        break;
        case 'T': {
            int16_t nwname = va_arg(ap, int);
            const char **wnames = va_arg(ap, const char **);

            errcode = p9pdu_writef(pdu, proto_version, "w",
                                   nwname);
            if (!errcode) {
                int i;

                for (i = 0; i < nwname; i++) {
                    errcode =
                        p9pdu_writef(pdu,
                                     proto_version,
                                     "s",
                                     wnames[i]);
                    if (errcode)
                        break;
                }
            }
        }
        break;
        case 'R': {
            int16_t nwqid = va_arg(ap, int);
            struct p9_qid *wqids =
                va_arg(ap, struct p9_qid *);

            errcode = p9pdu_writef(pdu, proto_version, "w",
                                   nwqid);
            if (!errcode) {
                int i;

                for (i = 0; i < nwqid; i++) {
                    errcode =
                        p9pdu_writef(pdu,
                                     proto_version,
                                     "Q",
                                     &wqids[i]);
                    if (errcode)
                        break;
                }
            }
        }
        break;
        case '?':
            if ((proto_version != p9_proto_2000u) &&
                    (proto_version != p9_proto_2000L))
                return 0;
            break;
        default:
            BUG();
            break;
        }

        if (errcode)
            break;
    }

    return errcode;
}