Пример #1
0
int wl_connection_data(struct wl_connection *connection, uint32_t mask)
{
	struct wl_buffer *b;
	struct iovec iov[2];
	int len, head, tail, count, size, available;

	if (mask & WL_CONNECTION_READABLE) {
		b = &connection->in;
		head = connection->in.head;
		if (head < b->tail) {
			iov[0].iov_base = b->data + head;
			iov[0].iov_len = b->tail - head;
			count = 1;
		} else {
			size = ARRAY_LENGTH(b->data) - head;
			iov[0].iov_base = b->data + head;
			iov[0].iov_len = size;
			iov[1].iov_base = b->data;
			iov[1].iov_len = b->tail;
			count = 2;
		}
		len = readv(connection->fd, iov, count);
		if (len < 0) {
			fprintf(stderr,
				"read error from connection %p: %m (%d)\n",
				connection, errno);
			return -1;
		} else if (len == 0) {
			/* FIXME: Handle this better? */
			return -1;
		} else if (head + len <= ARRAY_LENGTH(b->data)) {
			b->head += len;
		} else {
			b->head = head + len - ARRAY_LENGTH(b->data);
		}

		/* We know we have data in the buffer at this point,
		 * so if head equals tail, it means the buffer is
		 * full. */

		available = b->head - b->tail;
		if (available == 0)
			available = sizeof b->data;
		else if (available < 0)
			available += ARRAY_LENGTH(b->data);
	} else {
		available = 0;
	}	

	if (mask & WL_CONNECTION_WRITABLE) {
		b = &connection->out;
		tail = b->tail;
		if (tail < b->head) {
			iov[0].iov_base = b->data + tail;
			iov[0].iov_len = b->head - tail;
			count = 1;
		} else {
			size = ARRAY_LENGTH(b->data) - tail;
			iov[0].iov_base = b->data + tail;
			iov[0].iov_len = size;
			iov[1].iov_base = b->data;
			iov[1].iov_len = b->head;
			count = 2;
		}
		len = writev(connection->fd, iov, count);
		if (len < 0) {
			fprintf(stderr, "write error for connection %p: %m\n", connection);
			return -1;
		} else if (tail + len <= ARRAY_LENGTH(b->data)) {
			b->tail += len;
		} else {
			b->tail = tail + len - ARRAY_LENGTH(b->data);
		}

		/* We just took data out of the buffer, so at this
		 * point if head equals tail, the buffer is empty. */

		if (b->tail == b->head)
			connection->update(connection,
					   WL_CONNECTION_READABLE,
					   connection->data);
	}

	return available;
}
Пример #2
0
ngx_chain_t *
ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, c->log, 0, "ngx_linux_sendfile_chain");
    int            rc, tcp_nodelay;
    off_t          size, send, prev_send, aligned, sent, fprev;
    u_char        *prev;
    size_t         file_size;
    ngx_err_t      err;
    ngx_buf_t     *file;
    ngx_uint_t     eintr, complete;
    ngx_array_t    header;
    ngx_event_t   *wev;
    ngx_chain_t   *cl;
    struct iovec  *iov, headers[NGX_HEADERS];
#if (NGX_HAVE_SENDFILE64)
    off_t          offset;
#else
    int32_t        offset;
#endif

    wev = c->write;

    if (!wev->ready) {
        return in;
    }


    /* the maximum limit size is 2G-1 - the page size */

    if (limit == 0 || limit > (off_t) (NGX_SENDFILE_MAXSIZE - ngx_pagesize)) {
        limit = NGX_SENDFILE_MAXSIZE - ngx_pagesize;
    }


    send = 0;

    header.elts = headers;
    header.size = sizeof(struct iovec);
    header.nalloc = NGX_HEADERS;
    header.pool = c->pool;

    for ( ;; ) {
        file = NULL;
        file_size = 0;
        eintr = 0;
        complete = 0;
        prev_send = send;

        header.nelts = 0;

        prev = NULL;
        iov = NULL;

        /* create the iovec and coalesce the neighbouring bufs */

        for (cl = in; cl && send < limit; cl = cl->next) {

            if (ngx_buf_special(cl->buf)) {
                continue;
            }

#if 1
            if (!ngx_buf_in_memory(cl->buf) && !cl->buf->in_file) {
                ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                              "zero size buf in sendfile "
                              "t:%d r:%d f:%d %p %p-%p %p %O-%O",
                              cl->buf->temporary,
                              cl->buf->recycled,
                              cl->buf->in_file,
                              cl->buf->start,
                              cl->buf->pos,
                              cl->buf->last,
                              cl->buf->file,
                              cl->buf->file_pos,
                              cl->buf->file_last);

                ngx_debug_point();

                return NGX_CHAIN_ERROR;
            }
#endif

            if (!ngx_buf_in_memory_only(cl->buf)) {
                break;
            }

            size = cl->buf->last - cl->buf->pos;

            if (send + size > limit) {
                size = limit - send;
            }

            if (prev == cl->buf->pos) {
                iov->iov_len += (size_t) size;

            } else {
                if (header.nelts >= IOV_MAX) {
                    break;
                }

                iov = ngx_array_push(&header);
                if (iov == NULL) {
                    return NGX_CHAIN_ERROR;
                }

                iov->iov_base = (void *) cl->buf->pos;
                iov->iov_len = (size_t) size;
            }

            prev = cl->buf->pos + (size_t) size;
            send += size;
        }

        /* set TCP_CORK if there is a header before a file */

        if (c->tcp_nopush == NGX_TCP_NOPUSH_UNSET
            && header.nelts != 0
            && cl
            && cl->buf->in_file)
        {
            /* the TCP_CORK and TCP_NODELAY are mutually exclusive */

            if (c->tcp_nodelay == NGX_TCP_NODELAY_SET) {

                tcp_nodelay = 0;

                if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
                               (const void *) &tcp_nodelay, sizeof(int)) == -1)
                {
                    err = ngx_socket_errno;

                    /*
                     * there is a tiny chance to be interrupted, however,
                     * we continue a processing with the TCP_NODELAY
                     * and without the TCP_CORK
                     */

                    if (err != NGX_EINTR) {
                        wev->error = 1;
                        ngx_connection_error(c, err,
                                             "setsockopt(TCP_NODELAY) failed");
                        return NGX_CHAIN_ERROR;
                    }

                } else {
                    c->tcp_nodelay = NGX_TCP_NODELAY_UNSET;

                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                                   "no tcp_nodelay");
                }
            }

            if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {

                if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
                    err = ngx_socket_errno;

                    /*
                     * there is a tiny chance to be interrupted, however,
                     * we continue a processing without the TCP_CORK
                     */

                    if (err != NGX_EINTR) {
                        wev->error = 1;
                        ngx_connection_error(c, err,
                                             ngx_tcp_nopush_n " failed");
                        return NGX_CHAIN_ERROR;
                    }

                } else {
                    c->tcp_nopush = NGX_TCP_NOPUSH_SET;

                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                                   "tcp_nopush");
                }
            }
        }

        /* get the file buf */

        if (header.nelts == 0 && cl && cl->buf->in_file && send < limit) {
            file = cl->buf;

            /* coalesce the neighbouring file bufs */

            do {
                size = cl->buf->file_last - cl->buf->file_pos;

                if (send + size > limit) {
                    size = limit - send;

                    aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
                               & ~((off_t) ngx_pagesize - 1);

                    if (aligned <= cl->buf->file_last) {
                        size = aligned - cl->buf->file_pos;
                    }
                }

                file_size += (size_t) size;
                send += size;
                fprev = cl->buf->file_pos + size;
                cl = cl->next;

            } while (cl
                     && cl->buf->in_file
                     && send < limit
                     && file->file->fd == cl->buf->file->fd
                     && fprev == cl->buf->file_pos);
        }

        if (file) {
#if 1
            if (file_size == 0) {
                ngx_debug_point();
                return NGX_CHAIN_ERROR;
            }
#endif
#if (NGX_HAVE_SENDFILE64)
            offset = file->file_pos;
#else
            offset = (int32_t) file->file_pos;
#endif

            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                           "sendfile: @%O %uz", file->file_pos, file_size);

            rc = sendfile(c->fd, file->file->fd, &offset, file_size);

            if (rc == -1) {
                err = ngx_errno;

                switch (err) {
                case NGX_EAGAIN:
                    break;

                case NGX_EINTR:
                    eintr = 1;
                    break;

                default:
                    wev->error = 1;
                    ngx_connection_error(c, err, "sendfile() failed");
                    return NGX_CHAIN_ERROR;
                }

                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                               "sendfile() is not ready");
            }

            sent = rc > 0 ? rc : 0;

            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
                           "sendfile: %d, @%O %O:%uz",
                           rc, file->file_pos, sent, file_size);

        } else {
            rc = writev(c->fd, header.elts, header.nelts);

            if (rc == -1) {
                err = ngx_errno;

                switch (err) {
                case NGX_EAGAIN:
                    break;

                case NGX_EINTR:
                    eintr = 1;
                    break;

                default:
                    wev->error = 1;
                    ngx_connection_error(c, err, "writev() failed");
                    return NGX_CHAIN_ERROR;
                }

                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                               "writev() not ready");
            }

            sent = rc > 0 ? rc : 0;

            ngx_log_debug(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %O, fd:%d", sent, c->fd);
        }

        if (send - prev_send == sent) {
            complete = 1;
        }

        c->sent += sent;

        for ( /* void */ ; in; in = in->next) {

            if (ngx_buf_special(in->buf)) {
                continue;
            }

            if (sent == 0) {
                break;
            }

            size = ngx_buf_size(in->buf);

            if (sent >= size) {
                sent -= size;

                if (ngx_buf_in_memory(in->buf)) {
                    in->buf->pos = in->buf->last;
                }

                if (in->buf->in_file) {
                    in->buf->file_pos = in->buf->file_last;
                }

                continue;
            }

            if (ngx_buf_in_memory(in->buf)) {
                in->buf->pos += (size_t) sent;
            }

            if (in->buf->in_file) {
                in->buf->file_pos += sent;
            }

            break;
        }

        if (eintr) {
            continue;
        }

        if (!complete) {
            wev->ready = 0;
            return in;
        }

        if (send >= limit || in == NULL) {
            return in;
        }
    }
}
Пример #3
0
void write_file(iface_t *ifa)
{
    struct if_file *ifc = (struct if_file *) ifa->info;
    senblk_t *sptr;
    int usereturn=flag_test(ifa,F_NOCR)?0:1;
    int data=0;
    int cnt=1;
    struct iovec iov[2];

    /* ifc->fd will only be < 0 if we're opening a FIFO.
     */
    if (ifc->fd < 0) {
        if ((ifc->fd=open(ifc->filename,O_WRONLY)) < 0) {
            logerr(errno,"Failed to open FIFO %s for writing\n",ifc->filename);
            iface_thread_exit(errno);
        }
        if ((ifa->q =init_q(ifc->qsize)) == NULL) {
            logerr(errno,"Could not create queue for FIFO %s",ifc->filename);
            iface_thread_exit(errno);
        }
    }

    if (ifa->tagflags) {
        if ((iov[0].iov_base=malloc(TAGMAX)) == NULL) {
                logerr(errno,"Disabing tag output on interface id %u (%s)",
                        ifa->id,(ifa->name)?ifa->name:"unlabelled");
                ifa->tagflags=0;
        } else {
            cnt=2;
            data=1;
        }
    }


    for(;;)  {
        if ((sptr = next_senblk(ifa->q)) == NULL) {
            break;
        }

        if (senfilter(sptr,ifa->ofilter)) {
            senblk_free(sptr,ifa->q);
            continue;
        }

        if (!usereturn) {
            sptr->data[sptr->len-2] = '\n';
            sptr->len--;
        }

        if (ifa->tagflags)
            if ((iov[0].iov_len = gettag(ifa,iov[0].iov_base,sptr)) == 0) {
                logerr(errno,"Disabing tag output on interface id %u (%s)",
                        ifa->id,(ifa->name)?ifa->name:"unlabelled");
                ifa->tagflags=0;
                cnt=1;
                data=0;
                free(iov[0].iov_base);
            }

        iov[data].iov_base=sptr->data;
        iov[data].iov_len=sptr->len;
        if (writev(ifc->fd,iov,cnt) <0) {
            if (!(flag_test(ifa,F_PERSIST) && errno == EPIPE) )
                break;
            if ((ifc->fd=open(ifc->filename,O_WRONLY)) < 0)
                break;
        }
        senblk_free(sptr,ifa->q);
    }

    if (cnt == 2)
        free(iov[0].iov_base);

    iface_thread_exit(errno);
}
Пример #4
0
int32_t
sdp_register_service(void *xss, uint16_t uuid, bdaddr_p const bdaddr,
		uint8_t const *data, uint32_t datalen, uint32_t *handle)
{
	sdp_session_p	ss = (sdp_session_p) xss;
	struct iovec	iov[4];
	sdp_pdu_t	pdu;
	int32_t		len;

	if (ss == NULL)
		return (-1);
	if (bdaddr == NULL || data == NULL ||
	    datalen == 0 || !(ss->flags & SDP_SESSION_LOCAL)) {
		ss->error = EINVAL;
		return (-1);
	}
	if (sizeof(pdu)+sizeof(uuid)+sizeof(*bdaddr)+datalen > SDP_LOCAL_MTU) {
		ss->error = EMSGSIZE;
		return (-1);
	}

	pdu.pid = SDP_PDU_SERVICE_REGISTER_REQUEST;
	pdu.tid = htons(++ss->tid);
	pdu.len = htons(sizeof(uuid) + sizeof(*bdaddr) + datalen);

	uuid = htons(uuid);

	iov[0].iov_base = (void *) &pdu;
	iov[0].iov_len = sizeof(pdu);

	iov[1].iov_base = (void *) &uuid;
	iov[1].iov_len = sizeof(uuid);

	iov[2].iov_base = (void *) bdaddr;
	iov[2].iov_len = sizeof(*bdaddr);

	iov[3].iov_base = (void *) data;
	iov[3].iov_len = datalen;

	do {
		len = writev(ss->s, iov, sizeof(iov)/sizeof(iov[0]));
	} while (len < 0 && errno == EINTR);

	if (len < 0) {
		ss->error = errno;
		return (-1);
	}

	len = sdp_receive_error_pdu(ss);
	if (len < 0)
		return (-1);
	if (len != sizeof(pdu) + sizeof(uint16_t) + sizeof(uint32_t)) {
		ss->error = EIO;
		return (-1);
	}

	if (handle != NULL) {
		*handle  = (uint32_t) ss->rsp[--len];
		*handle |= (uint32_t) ss->rsp[--len] << 8;
		*handle |= (uint32_t) ss->rsp[--len] << 16;
		*handle |= (uint32_t) ss->rsp[--len] << 24;
	}

	return (0);
}
static void *
replay_thread(void *arg)
{
	struct iovec iov[6];
	char space[1] = " ", crlf[2] = "\r\n";
	struct replay_thread *thr = arg;
	struct message *msg;
	enum shmlogtag tag;
	size_t len;
	char *ptr;
	const char *next;

	int i;

	int reopen = 1;

	while ((msg = mailbox_get(&thr->mbox)) != NULL) {
		tag = msg->tag;
		len = msg->len;
		ptr = msg->ptr;

		thread_log(2, 0, "%s(%s)", VSL_tags[tag], msg->ptr);

		switch (tag) {
		case SLT_RxRequest:
			if (thr->method != NULL)
				thr->bogus = 1;
			else
				thr->method = trimline(thr, ptr);
			break;

		case SLT_RxURL:
			if (thr->url != NULL)
				thr->bogus = 1;
			else
				thr->url = trimline(thr, ptr);
			break;

		case SLT_RxProtocol:
			if (thr->proto != NULL)
				thr->bogus = 1;
			else
				thr->proto = trimline(thr, ptr);
			break;

		case SLT_RxHeader:
			if (thr->nhdr >= sizeof thr->hdr / sizeof *thr->hdr) {
				thr->bogus = 1;
			} else {
				thr->hdr[thr->nhdr++] = trimline(thr, ptr);
				if (isprefix(ptr, "connection:", &next))
					thr->conn = trimline(thr, next);
			}
			break;

		default:
			break;
		}

		freez(msg->ptr);
		freez(msg);

		if (tag != SLT_ReqEnd)
			continue;

		if (!thr->method || !thr->url || !thr->proto) {
			thr->bogus = 1;
		} else if (strcmp(thr->method, "GET") != 0 &&
		    strcmp(thr->method, "HEAD") != 0) {
			thr->bogus = 1;
		} else if (strcmp(thr->proto, "HTTP/1.0") == 0) {
			reopen = !(thr->conn &&
			    strcasecmp(thr->conn, "keep-alive") == 0);
		} else if (strcmp(thr->proto, "HTTP/1.1") == 0) {
			reopen = (thr->conn &&
			    strcasecmp(thr->conn, "close") == 0);
		} else {
			thr->bogus = 1;
		}

		if (thr->bogus) {
			thread_log(1, 0, "bogus");
			goto clear;
		}

		if (thr->sock == -1) {
			for (;;) {
				thread_log(1, 0, "sleeping before connect...");
				usleep(1000 * (thr->fd % 3001));
				if ((thr->sock = VSS_connect(addr_info)) >= 0)
					break;
				thread_log(0, errno, "connect failed");
			}
		}

		thread_log(1, 0, "%s %s %s", thr->method, thr->url, thr->proto);

		iov[0].iov_base = thr->method;
		iov[0].iov_len = strlen(thr->method);
		iov[2].iov_base = thr->url;
		iov[2].iov_len = strlen(thr->url);
		iov[4].iov_base = thr->proto;
		iov[4].iov_len = strlen(thr->proto);
		iov[1].iov_base = iov[3].iov_base = space;
		iov[1].iov_len = iov[3].iov_len = 1;
		iov[5].iov_base = crlf;
		iov[5].iov_len = 2;
		if (writev(thr->sock, iov, 6) == -1) {
			thread_log(0, errno, "writev()");
			goto close;
		}

		for (i = 0; i < thr->nhdr; ++i) {
			thread_log(2, 0, "%d %s", i, thr->hdr[i]);
			iov[0].iov_base = thr->hdr[i];
			iov[0].iov_len = strlen(thr->hdr[i]);
			iov[1].iov_base = crlf;
			iov[1].iov_len = 2;
			if (writev(thr->sock, iov, 2) == -1) {
				thread_log(0, errno, "writev()");
				goto close;
			}
		}
		if (write(thr->sock, crlf, 2) == -1) {
			thread_log(0, errno, "writev()");
			goto close;
		}
		if (receive_response(thr) || reopen) {
close:
			thread_log(1, 0, "close");
			assert(thr->sock != -1);
			close(thr->sock);
			thr->sock = -1;
		}

		sleep(1);
clear:
		/* clean up */
		thread_clear(thr);
	}

	/* leftovers */
	thread_clear(thr);

	return (0);
}
Пример #6
0
apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
                                 apr_hdtr_t *hdtr, apr_off_t *offset,
                                 apr_size_t *len, apr_int32_t flags)
{
    int i;
    apr_ssize_t rc;
    apr_size_t nbytes = *len, headerlen, trailerlen;
    struct iovec hdtrarray[2];
    char *headerbuf, *trailerbuf;

    if (!hdtr) {
        hdtr = &no_hdtr;
    }

    /* Ignore flags for now. */
    flags = 0;

    /* HP-UX can only send one header iovec and one footer iovec; try to
     * only allocate storage to combine input iovecs when we really have to
     */

    switch(hdtr->numheaders) {
    case 0:
        hdtrarray[0].iov_base = NULL;
        hdtrarray[0].iov_len = 0;
        break;
    case 1:
        hdtrarray[0] = hdtr->headers[0];
        break;
    default:
        headerlen = 0;
        for (i = 0; i < hdtr->numheaders; i++) {
            headerlen += hdtr->headers[i].iov_len;
        }

        /* XXX:  BUHHH? wow, what a memory leak! */
        headerbuf = hdtrarray[0].iov_base = apr_palloc(sock->cntxt, headerlen);
        hdtrarray[0].iov_len = headerlen;

        for (i = 0; i < hdtr->numheaders; i++) {
            memcpy(headerbuf, hdtr->headers[i].iov_base,
                   hdtr->headers[i].iov_len);
            headerbuf += hdtr->headers[i].iov_len;
        }
    }

    switch(hdtr->numtrailers) {
    case 0:
        hdtrarray[1].iov_base = NULL;
        hdtrarray[1].iov_len = 0;
        break;
    case 1:
        hdtrarray[1] = hdtr->trailers[0];
        break;
    default:
        trailerlen = 0;
        for (i = 0; i < hdtr->numtrailers; i++) {
            trailerlen += hdtr->trailers[i].iov_len;
        }

        /* XXX:  BUHHH? wow, what a memory leak! */
        trailerbuf = hdtrarray[1].iov_base = apr_palloc(sock->cntxt, trailerlen);
        hdtrarray[1].iov_len = trailerlen;

        for (i = 0; i < hdtr->numtrailers; i++) {
            memcpy(trailerbuf, hdtr->trailers[i].iov_base,
                   hdtr->trailers[i].iov_len);
            trailerbuf += hdtr->trailers[i].iov_len;
        }
    }

    do {
        if (nbytes) {       /* any bytes to send from the file? */
            rc = sendfile(sock->socketdes,      /* socket  */
                          file->filedes,        /* file descriptor to send */
                          *offset,              /* where in the file to start */
                          nbytes,               /* number of bytes to send from file */
                          hdtrarray,            /* Headers/footers */
                          flags);               /* undefined, set to 0 */
        }
        else {              /* we can't call sendfile() with no bytes to send from the file */
            rc = writev(sock->socketdes, hdtrarray, 2);
        }
    } while (rc == -1 && errno == EINTR);

    while (rc == -1 &&
            (errno == EAGAIN || errno == EWOULDBLOCK) &&
            apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) {
        apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0);

        if (arv != APR_SUCCESS) {
            *len = 0;
            return arv;
        }
        else {
            do {
                if (nbytes) {
                    rc = sendfile(sock->socketdes,    /* socket  */
                                  file->filedes,      /* file descriptor to send */
                                  *offset,            /* where in the file to start */
                                  nbytes,             /* number of bytes to send from file */
                                  hdtrarray,          /* Headers/footers */
                                  flags);             /* undefined, set to 0 */
                }
                else {      /* we can't call sendfile() with no bytes to send from the file */
                    rc = writev(sock->socketdes, hdtrarray, 2);
                }
            } while (rc == -1 && errno == EINTR);
        }
    }

    if (rc == -1) {
        *len = 0;
        return errno;
    }

    /* Set len to the number of bytes written */
    *len = rc;
    return APR_SUCCESS;
}
Пример #7
0
/* On success returns NULL. On error returns a pointer to the write request
 * which had the error.
 */
static void uv__write(uv_stream_t* stream) {
  uv_write_t* req;
  struct iovec* iov;
  int iovcnt;
  ssize_t n;

  if (stream->flags & UV_CLOSING) {
    /* Handle was closed this tick. We've received a stale
     * 'is writable' callback from the event loop, ignore.
     */
    return;
  }

start:

  assert(stream->fd >= 0);

  /* Get the request at the head of the queue. */
  req = uv_write_queue_head(stream);
  if (!req) {
    assert(stream->write_queue_size == 0);
    return;
  }

  assert(req->handle == stream);

  /*
   * Cast to iovec. We had to have our own uv_buf_t instead of iovec
   * because Windows's WSABUF is not an iovec.
   */
  assert(sizeof(uv_buf_t) == sizeof(struct iovec));
  iov = (struct iovec*) &(req->bufs[req->write_index]);
  iovcnt = req->bufcnt - req->write_index;

  /*
   * Now do the actual writev. Note that we've been updating the pointers
   * inside the iov each time we write. So there is no need to offset it.
   */

  if (req->send_handle) {
    struct msghdr msg;
    char scratch[64];
    struct cmsghdr *cmsg;
    int fd_to_send = req->send_handle->fd;

    assert(fd_to_send >= 0);

    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = iovcnt;
    msg.msg_flags = 0;

    msg.msg_control = (void*) scratch;
    msg.msg_controllen = CMSG_LEN(sizeof(fd_to_send));

    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = msg.msg_controllen;

    /* silence aliasing warning */
    {
      void* pv = CMSG_DATA(cmsg);
      int* pi = pv;
      *pi = fd_to_send;
    }

    do {
      n = sendmsg(stream->fd, &msg, 0);
    }
    while (n == -1 && errno == EINTR);
  } else {
    do {
      if (iovcnt == 1) {
        n = write(stream->fd, iov[0].iov_base, iov[0].iov_len);
      } else {
        n = writev(stream->fd, iov, iovcnt);
      }
    }
    while (n == -1 && errno == EINTR);
  }

  if (n < 0) {
    if (errno != EAGAIN && errno != EWOULDBLOCK) {
      /* Error */
      req->error = errno;
      stream->write_queue_size -= uv__write_req_size(req);
      uv__write_req_finish(req);
      return;
    } else if (stream->flags & UV_STREAM_BLOCKING) {
      /* If this is a blocking stream, try again. */
      goto start;
    }
  } else {
    /* Successful write */

    while (n >= 0) {
      uv_buf_t* buf = &(req->bufs[req->write_index]);
      size_t len = buf->len;

      assert(req->write_index < req->bufcnt);

      if ((size_t)n < len) {
        buf->base += n;
        buf->len -= n;
        stream->write_queue_size -= n;
        n = 0;

        /* There is more to write. */
        if (stream->flags & UV_STREAM_BLOCKING) {
          /*
           * If we're blocking then we should not be enabling the write
           * watcher - instead we need to try again.
           */
          goto start;
        } else {
          /* Break loop and ensure the watcher is pending. */
          break;
        }

      } else {
        /* Finished writing the buf at index req->write_index. */
        req->write_index++;

        assert((size_t)n >= len);
        n -= len;

        assert(stream->write_queue_size >= len);
        stream->write_queue_size -= len;

        if (req->write_index == req->bufcnt) {
          /* Then we're done! */
          assert(n == 0);
          uv__write_req_finish(req);
          /* TODO: start trying to write the next request. */
          return;
        }
      }
    }
  }

  /* Either we've counted n down to zero or we've got EAGAIN. */
  assert(n == 0 || n == -1);

  /* Only non-blocking streams should use the write_watcher. */
  assert(!(stream->flags & UV_STREAM_BLOCKING));

  /* We're not done. */
  uv__io_start(stream->loop, &stream->write_watcher);
}
Пример #8
0
void* log_thread_function(void* arg)
{
	log_item* item;
	
	int len;
	int done;
	int total_size;
	time_t now;
	char* p = NULL;
	char* time_str;
	struct iovec iv[3];
	
	char end = '\n';

	char log_type_info[6][12] = {{"LOG_INFO\t"}, {"LOG_WARING\t"}, {"LOG_NOTICE\t"}, {"LOG_ERROR\t"}, {"LOG_DEBUG\t"}, {"LOG_CRIT\t"}};

	syslog(LOG_DEBUG, "log thread start\n");	

	assert(log_que.fd > 0 && log_que.buf);

	while(1) {
		pthread_mutex_lock(&log_que.buf_lock);
		while(log_que.curr == 0)
			pthread_cond_wait(&log_que.log_cond, &log_que.buf_lock);
		
		done = 0;
		while(done < log_que.curr) {
			p = log_que.buf + done;
			item = (log_item*)p;
		
			now = time(NULL);
			time_str = ctime(&now);
			len = strlen(time_str);
	
			// 去掉时间字符串最后的那个\n
			time_str[len-1] = '\0';
			strcat(time_str, "\t");

			iv[0].iov_len = len;
			iv[0].iov_base = (void*)time_str;	

			iv[1].iov_len = strlen(log_type_info[item->type]);
			iv[1].iov_base = (void*)log_type_info[item->type];	
			iv[2].iov_len = item->len;
			iv[2].iov_base = p + sizeof(log_item);
			
			if(iv[2].iov_len <= 0) {
				iv[2].iov_len = 1;
				iv[2].iov_base = &end;
			}

			total_size = iv[0].iov_len + iv[1].iov_len + iv[2].iov_len;
			while(total_size > 0) {
				if((len = writev(log_que.fd, iv, 3)) < 0) {
					if(errno == EINTR)
						continue;
					syslog(LOG_WARNING, "error occured:%s when write log", strerror(errno));
					pthread_mutex_unlock(&log_que.buf_lock);
					return NULL;
				}

				total_size -= len;
			}

			done += sizeof(log_item) + item->len;
		}
		
		log_que.curr = 0;
		pthread_mutex_unlock(&log_que.buf_lock);
	}
	
	return NULL;
}
Пример #9
0
void test_file(void)
{
    int fd, i, len, ret;
    uint8_t buf[FILE_BUF_SIZE];
    uint8_t buf2[FILE_BUF_SIZE];
    uint8_t buf3[FILE_BUF_SIZE];
    char cur_dir[1024];
    struct stat st;
    struct utimbuf tbuf;
    struct iovec vecs[2];
    DIR *dir;
    struct dirent *de;

    /* clean up, just in case */
    unlink(TESTPATH "/file1");
    unlink(TESTPATH "/file2");
    unlink(TESTPATH "/file3");
    rmdir(TESTPATH);

    if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
        error("getcwd");

    chk_error(mkdir(TESTPATH, 0755));

    chk_error(chdir(TESTPATH));

    /* open/read/write/close/readv/writev/lseek */

    fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644));
    for(i=0;i < FILE_BUF_SIZE; i++)
        buf[i] = i;
    len = chk_error(qemu_write(fd, buf, FILE_BUF_SIZE / 2));
    if (len != (FILE_BUF_SIZE / 2))
        error("write");
    vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2);
    vecs[0].iov_len = 16;
    vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16;
    vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16;
    len = chk_error(writev(fd, vecs, 2));
    if (len != (FILE_BUF_SIZE / 2))
     error("writev");
    chk_error(close(fd));

    chk_error(rename("file1", "file2"));

    fd = chk_error(open("file2", O_RDONLY));

    len = chk_error(read(fd, buf2, FILE_BUF_SIZE));
    if (len != FILE_BUF_SIZE)
        error("read");
    if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0)
        error("memcmp");

#define FOFFSET 16
    ret = chk_error(lseek(fd, FOFFSET, SEEK_SET));
    if (ret != 16)
        error("lseek");
    vecs[0].iov_base = buf3;
    vecs[0].iov_len = 32;
    vecs[1].iov_base = buf3 + 32;
    vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32;
    len = chk_error(readv(fd, vecs, 2));
    if (len != FILE_BUF_SIZE - FOFFSET)
        error("readv");
    if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0)
        error("memcmp");

    chk_error(close(fd));

    /* access */
    chk_error(access("file2", R_OK));

    /* stat/chmod/utime/truncate */

    chk_error(chmod("file2", 0600));
    tbuf.actime = 1001;
    tbuf.modtime = 1000;
    chk_error(truncate("file2", 100));
    chk_error(utime("file2", &tbuf));
    chk_error(stat("file2", &st));
    if (st.st_size != 100)
        error("stat size");
    if (!S_ISREG(st.st_mode))
        error("stat mode");
    if ((st.st_mode & 0777) != 0600)
        error("stat mode2");
    if (st.st_atime != 1001 ||
        st.st_mtime != 1000)
        error("stat time");

    chk_error(stat(TESTPATH, &st));
    if (!S_ISDIR(st.st_mode))
        error("stat mode");

    /* fstat */
    fd = chk_error(open("file2", O_RDWR));
    chk_error(ftruncate(fd, 50));
    chk_error(fstat(fd, &st));
    chk_error(close(fd));

    if (st.st_size != 50)
        error("stat size");
    if (!S_ISREG(st.st_mode))
        error("stat mode");

    /* symlink/lstat */
    chk_error(symlink("file2", "file3"));
    chk_error(lstat("file3", &st));
    if (!S_ISLNK(st.st_mode))
        error("stat mode");

    /* getdents */
    dir = opendir(TESTPATH);
    if (!dir)
        error("opendir");
    len = 0;
    for(;;) {
        de = readdir(dir);
        if (!de)
            break;
        if (strcmp(de->d_name, ".") != 0 &&
            strcmp(de->d_name, "..") != 0 &&
            strcmp(de->d_name, "file2") != 0 &&
            strcmp(de->d_name, "file3") != 0)
            error("readdir");
        len++;
    }
    closedir(dir);
    if (len != 4)
        error("readdir");

    chk_error(unlink("file3"));
    chk_error(unlink("file2"));
    chk_error(chdir(cur_dir));
    chk_error(rmdir(TESTPATH));
}
Пример #10
0
ssize_t uwsgi_redis_logger(struct uwsgi_logger *ul, char *message, size_t len) {

	ssize_t ret,ret2;
	struct uwsgi_redislog_state *uredislog = NULL;

	if (!ul->configured) {

		if (!ul->data) {
			ul->data = uwsgi_calloc(sizeof(struct uwsgi_redislog_state));
			uredislog = (struct uwsgi_redislog_state *) ul->data;
		}

		if (ul->arg != NULL) {
			char *logarg = uwsgi_str(ul->arg);
			char *comma1 = strchr(logarg, ',');
			if (!comma1) {
				uredislog->address = logarg;
				goto done;
			}
			*comma1 = 0;
			uredislog->address = logarg;
			comma1++;
			if (*comma1 == 0) goto done;

			char *comma2 = strchr(comma1,',');
			if (!comma2) {
				uredislog->command = uwsgi_redis_logger_build_command(comma1);
				goto done;
			}

			*comma2 = 0;
			uredislog->command = uwsgi_redis_logger_build_command(comma1);
			comma2++;
			if (*comma2 == 0) goto done;

			uredislog->prefix = comma2;
		}

done:

		if (!uredislog->address) uredislog->address = uwsgi_str("127.0.0.1:6379");
		if (!uredislog->command) uredislog->command = "*3\r\n$7\r\npublish\r\n$5\r\nuwsgi\r\n";
		if (!uredislog->prefix) uredislog->prefix = "";

		uredislog->fd = -1;

		uredislog->iovec[0].iov_base = uredislog->command;
		uredislog->iovec[0].iov_len = strlen(uredislog->command);
		uredislog->iovec[1].iov_base = "$";
		uredislog->iovec[1].iov_len = 1;

		uredislog->iovec[2].iov_base = uredislog->msgsize;

		uredislog->iovec[3].iov_base = "\r\n";
		uredislog->iovec[3].iov_len = 2;

		uredislog->iovec[4].iov_base = uredislog->prefix;
		uredislog->iovec[4].iov_len = strlen(uredislog->prefix);

		uredislog->iovec[6].iov_base = "\r\n";
		uredislog->iovec[6].iov_len = 2;

		ul->configured = 1;
	}

	uredislog = (struct uwsgi_redislog_state *) ul->data;
	if (uredislog->fd == -1) {
		uredislog->fd = uwsgi_connect(uredislog->address, uwsgi.socket_timeout, 0);
	}

	if (uredislog->fd == -1) return -1;

	// drop newline
        if (message[len-1] == '\n') len--;

	uwsgi_num2str2(len + uredislog->iovec[4].iov_len, uredislog->msgsize);
	uredislog->iovec[2].iov_len = strlen(uredislog->msgsize);

	uredislog->iovec[5].iov_base = message;
	uredislog->iovec[5].iov_len = len;
	
	ret = writev(uredislog->fd, uredislog->iovec, 7);
	if (ret <= 0) {
		close(uredislog->fd);
		uredislog->fd = -1;
		return -1;
	}

again:
	// read til a \n is found (ugly but fast)
	ret2 = read(uredislog->fd, uredislog->response, 8);
	if (ret2 <= 0) {
		close(uredislog->fd);
		uredislog->fd = -1;
		return -1;
	}

	if (!memchr(uredislog->response, '\n', ret2)) {
		goto again;
	}

	return ret;

}
Пример #11
0
/*
 * Write a line to log file (unbuffered)
 */
static void
direct_write_log_line (rspamd_logger_t *rspamd_log,
		void *data,
		gsize count,
		gboolean is_iov)
{
	gchar errmsg[128];
	struct iovec *iov;
	const gchar *line;
	glong r;

	if (rspamd_log->enabled) {
		if (!rspamd_log->no_lock) {
#ifndef DISABLE_PTHREAD_MUTEX
			if (rspamd_log->mtx) {
				rspamd_mempool_lock_mutex (rspamd_log->mtx);
			}
			else {
				rspamd_file_lock (rspamd_log->fd, FALSE);
			}
#else
			rspamd_file_lock (rspamd_log->fd, FALSE);
#endif
		}

		if (is_iov) {
			iov = (struct iovec *) data;
			r = writev (rspamd_log->fd, iov, count);
		}
		else {
			line = (const gchar *) data;
			r = write (rspamd_log->fd, line, count);
		}

		if (!rspamd_log->no_lock) {
#ifndef DISABLE_PTHREAD_MUTEX
			if (rspamd_log->mtx) {
				rspamd_mempool_unlock_mutex (rspamd_log->mtx);
			}
			else {
				rspamd_file_unlock (rspamd_log->fd, FALSE);
			}
#else
			rspamd_file_unlock (rspamd_log->fd, FALSE);
#endif
		}

		if (r == -1) {
			/* We cannot write message to file, so we need to detect error and make decision */
			if (errno == EINTR) {
				/* Try again */
				direct_write_log_line (rspamd_log, data, count, is_iov);
				return;
			}

			r = rspamd_snprintf (errmsg,
					sizeof (errmsg),
					"direct_write_log_line: cannot write log line: %s",
					strerror (errno));
			if (errno == EFAULT || errno == EINVAL || errno == EFBIG ||
				errno == ENOSPC) {
				/* Rare case */
				rspamd_log->throttling = TRUE;
				rspamd_log->throttling_time = time (NULL);
			}
			else if (errno == EPIPE || errno == EBADF) {
				/* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */
				rspamd_log->enabled = FALSE;
			}
		}
		else if (rspamd_log->throttling) {
			rspamd_log->throttling = FALSE;
		}
	}
}
Пример #12
0
/*
 * Display the contents of a uio structure on a terminal.  Used by wall(1),
 * syslogd(8), and talkd(8).  Forks and finishes in child if write would block,
 * waiting up to tmout seconds.  Returns pointer to error string on unexpected
 * error; string is not newline-terminated.  Various "normal" errors are
 * ignored (exclusive-use, lack of permission, etc.).
 */
const char *
ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
{
	struct iovec localiov[7];
	ssize_t left, wret;
	int cnt, fd;
	static char device[MAXNAMLEN] = _PATH_DEV;
	static char errbuf[1024];
	char *p;
	int forked;

	forked = 0;
	if (iovcnt > (int)(sizeof(localiov) / sizeof(localiov[0])))
		return ("too many iov's (change code in wall/ttymsg.c)");

	p = device + sizeof(_PATH_DEV) - 1;
	strlcpy(p, line, sizeof(device));
	if (strncmp(p, "pts/", 4) == 0)
		p += 4;
	if (strchr(p, '/') != NULL) {
		/* A slash is an attempt to break security... */
		(void) snprintf(errbuf, sizeof(errbuf),
		    "Too many '/' in \"%s\"", device);
		return (errbuf);
	}

	/*
	 * open will fail on slip lines or exclusive-use lines
	 * if not running as root; not an error.
	 */
	if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
		if (errno == EBUSY || errno == EACCES)
			return (NULL);
		(void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device,
		    strerror(errno));
		return (errbuf);
	}

	for (cnt = 0, left = 0; cnt < iovcnt; ++cnt)
		left += iov[cnt].iov_len;

	for (;;) {
		wret = writev(fd, iov, iovcnt);
		if (wret >= left)
			break;
		if (wret >= 0) {
			left -= wret;
			if (iov != localiov) {
				bcopy(iov, localiov, 
				    iovcnt * sizeof(struct iovec));
				iov = localiov;
			}
			for (cnt = 0; (size_t)wret >= iov->iov_len; ++cnt) {
				wret -= iov->iov_len;
				++iov;
				--iovcnt;
			}
			if (wret) {
				iov->iov_base = (char *)iov->iov_base + wret;
				iov->iov_len -= wret;
			}
			continue;
		}
		if (errno == EWOULDBLOCK) {
			int cpid;

			if (forked) {
				(void) close(fd);
				_exit(1);
			}
			cpid = fork();
			if (cpid < 0) {
				(void) snprintf(errbuf, sizeof(errbuf),
				    "fork: %s", strerror(errno));
				(void) close(fd);
				return (errbuf);
			}
			if (cpid) {	/* parent */
				(void) close(fd);
				return (NULL);
			}
			forked++;
			/* wait at most tmout seconds */
			(void) signal(SIGALRM, SIG_DFL);
			(void) signal(SIGTERM, SIG_DFL); /* XXX */
			(void) sigsetmask(0);
			(void) alarm((u_int)tmout);
			(void) fcntl(fd, F_SETFL, 0);	/* clear O_NONBLOCK */
			continue;
		}
		/*
		 * We get ENODEV on a slip line if we're running as root,
		 * and EIO if the line just went away.
		 */
		if (errno == ENODEV || errno == EIO)
			break;
		(void) close(fd);
		if (forked)
			_exit(1);
		(void) snprintf(errbuf, sizeof(errbuf),
		    "%s: %s", device, strerror(errno));
		return (errbuf);
	}

	(void) close(fd);
	if (forked)
		_exit(0);
	return (NULL);
}
Пример #13
0
static int     /* R: bytes written, or -1 on error */
retry_writev (
  /* PARAMETERS */
  int fd,                              /* I: fd to write on */
  struct iovec *iov,                   /* U: iovec array base
                                        *    modified as data written */
  int iovcnt                           /* I: number of iovec entries */
  /* END PARAMETERS */
  )
{
    /* VARIABLES */
    int n;                             /* return value from writev() */
    int i;                             /* loop counter */
    int written;                       /* bytes written so far */
    static int iov_max;                        /* max number of iovec entries */
    /* END VARIABLES */

    /* initialization */
#ifdef MAXIOV
    iov_max = MAXIOV;
#else /* ! MAXIOV */
# ifdef IOV_MAX
    iov_max = IOV_MAX;
# else /* ! IOV_MAX */
    iov_max = 8192;
# endif /* ! IOV_MAX */
#endif /* ! MAXIOV */
    written = 0;

    for (;;) {

       while (iovcnt && iov[0].iov_len == 0) {
           iov++;
           iovcnt--;
       }

       if (!iovcnt) {
           return written;
       }

       n = writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt);
       if (n == -1) {
           if (errno == EINVAL && iov_max > 10) {
               iov_max /= 2;
               continue;
           }
           if (errno == EINTR) {
               continue;
           }
           return -1;
       } else {
           written += n;
       }

       for (i = 0; i < iovcnt; i++) {
           if (iov[i].iov_len > (unsigned) n) {
               iov[i].iov_base = (char *)iov[i].iov_base + n;
               iov[i].iov_len -= n;
               break;
           }
           n -= iov[i].iov_len;
           iov[i].iov_len = 0;
       }

       if (i == iovcnt) {
           return written;
       }
    }
    /* NOTREACHED */
}
Пример #14
0
apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
                                 apr_hdtr_t *hdtr, apr_off_t *offset,
                                 apr_size_t *len, apr_int32_t flags)
{
    int i;
    apr_ssize_t rc;
    apr_size_t nbytes = *len, headerlen, trailerlen;
    struct iovec hdtrarray[2];
    char *headerbuf, *trailerbuf;

#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64)
    /* later HP-UXes have a sendfile64() */
#define sendfile sendfile64
    apr_off_t off = *offset;

#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4
    /* HP-UX 11.00 doesn't have a sendfile64(): fail if trying to send
     * past the 2Gb limit */
    off_t off;

    if ((apr_int64_t)*offset + *len > INT_MAX) {
        return EINVAL;
    }
    off = *offset;
#else
    apr_off_t off = *offset;
#endif

    if (!hdtr) {
        hdtr = &no_hdtr;
    }

    /* Ignore flags for now. */
    flags = 0;

    /* HP-UX can only send one header iovec and one footer iovec; try to
     * only allocate storage to combine input iovecs when we really have to
     */

    switch(hdtr->numheaders) {
    case 0:
        hdtrarray[0].iov_base = NULL;
        hdtrarray[0].iov_len = 0;
        break;
    case 1:
        hdtrarray[0] = hdtr->headers[0];
        break;
    default:
        headerlen = 0;
        for (i = 0; i < hdtr->numheaders; i++) {
            headerlen += hdtr->headers[i].iov_len;
        }  

        /* XXX:  BUHHH? wow, what a memory leak! */
        headerbuf = hdtrarray[0].iov_base = apr_palloc(sock->pool, headerlen);
        hdtrarray[0].iov_len = headerlen;

        for (i = 0; i < hdtr->numheaders; i++) {
            memcpy(headerbuf, hdtr->headers[i].iov_base,
                   hdtr->headers[i].iov_len);
            headerbuf += hdtr->headers[i].iov_len;
        }
    }

    switch(hdtr->numtrailers) {
    case 0:
        hdtrarray[1].iov_base = NULL;
        hdtrarray[1].iov_len = 0;
        break;
    case 1:
        hdtrarray[1] = hdtr->trailers[0];
        break;
    default:
        trailerlen = 0;
        for (i = 0; i < hdtr->numtrailers; i++) {
            trailerlen += hdtr->trailers[i].iov_len;
        }

        /* XXX:  BUHHH? wow, what a memory leak! */
        trailerbuf = hdtrarray[1].iov_base = apr_palloc(sock->pool, trailerlen);
        hdtrarray[1].iov_len = trailerlen;

        for (i = 0; i < hdtr->numtrailers; i++) {
            memcpy(trailerbuf, hdtr->trailers[i].iov_base,
                   hdtr->trailers[i].iov_len);
            trailerbuf += hdtr->trailers[i].iov_len;
        }
    }

    do {
        if (nbytes) {       /* any bytes to send from the file? */
            rc = sendfile(sock->socketdes,      /* socket  */
                          file->filedes,        /* file descriptor to send */
                          off,                  /* where in the file to start */
                          nbytes,               /* number of bytes to send from file */
                          hdtrarray,            /* Headers/footers */
                          flags);               /* undefined, set to 0 */
        }
        else {              /* we can't call sendfile() with no bytes to send from the file */
            rc = writev(sock->socketdes, hdtrarray, 2);
        }
    } while (rc == -1 && errno == EINTR);

    while ((rc == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) 
                      && (sock->timeout > 0)) {
        apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0);

        if (arv != APR_SUCCESS) {
            *len = 0;
            return arv;
        }
        else {
            do {
                if (nbytes) {
                    rc = sendfile(sock->socketdes,    /* socket  */
                                  file->filedes,      /* file descriptor to send */
                                  off,                /* where in the file to start */
                                  nbytes,             /* number of bytes to send from file */
                                  hdtrarray,          /* Headers/footers */
                                  flags);             /* undefined, set to 0 */
                }
                else {      /* we can't call sendfile() with no bytes to send from the file */
                    rc = writev(sock->socketdes, hdtrarray, 2);
                }
            } while (rc == -1 && errno == EINTR);
        }
    }

    if (rc == -1) {
        *len = 0;
        return errno;
    }

    /* Set len to the number of bytes written */
    *len = rc;
    return APR_SUCCESS;
}
Пример #15
0
ngx_chain_t *
ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
    u_char        *prev;
    ssize_t        n, size, sent;
    off_t          send, prev_send;
    ngx_uint_t     eintr, complete;
    ngx_err_t      err;
    ngx_array_t    vec;
    ngx_chain_t   *cl;
    ngx_event_t   *wev;
    struct iovec  *iov, iovs[NGX_IOVS];

    wev = c->write;

    if (!wev->ready) {
        return in;
    }

#if (NGX_HAVE_KQUEUE)

    if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
        (void) ngx_connection_error(c, wev->kq_errno,
                               "kevent() reported about an closed connection");
        wev->error = 1;
        return NGX_CHAIN_ERROR;
    }

#endif

    /* the maximum limit size is the maximum size_t value - the page size */

    if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
        limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
    }

    send = 0;
    complete = 0;

    vec.elts = iovs;
    vec.size = sizeof(struct iovec);
    vec.nalloc = NGX_IOVS;
    vec.pool = c->pool;

    for ( ;; ) {
        prev = NULL;
        iov = NULL;
        eintr = 0;
        prev_send = send;

        vec.nelts = 0;

        /* create the iovec and coalesce the neighbouring bufs */

        for (cl = in; cl && vec.nelts < IOV_MAX && send < limit; cl = cl->next)
        {
            if (ngx_buf_special(cl->buf)) {
                continue;
            }

#if 1
            if (!ngx_buf_in_memory(cl->buf)) {
                ngx_debug_point();
            }
#endif

            size = cl->buf->last - cl->buf->pos;

            if (send + size > limit) {
                size = (ssize_t) (limit - send);
            }

            if (prev == cl->buf->pos) {
                iov->iov_len += size;

            } else {
                iov = ngx_array_push(&vec);
                if (iov == NULL) {
                    return NGX_CHAIN_ERROR;
                }

                iov->iov_base = (void *) cl->buf->pos;
                iov->iov_len = size;
            }

            prev = cl->buf->pos + size;
            send += size;
        }

        n = writev(c->fd, vec.elts, vec.nelts);

        if (n == -1) {
            err = ngx_errno;

            if (err == NGX_EAGAIN || err == NGX_EINTR) {
                if (err == NGX_EINTR) {
                    eintr = 1;
                }

                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                               "writev() not ready");

            } else {
                wev->error = 1;
                (void) ngx_connection_error(c, err, "writev() failed");
                return NGX_CHAIN_ERROR;
            }
        }

        sent = n > 0 ? n : 0;

        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %z", sent);

        if (send - prev_send == sent) {
            complete = 1;
        }

        c->sent += sent;

        for (cl = in; cl; cl = cl->next) {

            if (ngx_buf_special(cl->buf)) {
                continue;
            }

            if (sent == 0) {
                break;
            }

            size = cl->buf->last - cl->buf->pos;

            if (sent >= size) {
                sent -= size;
                cl->buf->pos = cl->buf->last;

                continue;
            }

            cl->buf->pos += sent;

            break;
        }

        if (eintr) {
            continue;
        }

        if (!complete) {
            wev->ready = 0;
            return cl;
        }

        if (send >= limit || cl == NULL) {
            return cl;
        }

        in = cl;
    }
}
Пример #16
0
int
main(int argc, char *argv[])
{
	int nflag;	/* if not set, output a trailing newline. */
	int veclen;	/* number of writev arguments. */
	struct iovec *iov, *vp; /* Elements to write, current element. */
	char space[] = " ";
	char newline[] = "\n";
	char *progname = argv[0];

	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
		err(1, "capsicum");

	/* This utility may NOT do getopt(3) option parsing. */
	if (*++argv && !strcmp(*argv, "-n")) {
		++argv;
		--argc;
		nflag = 1;
	} else
		nflag = 0;

	veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;

	if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
		errexit(progname, "malloc");

	while (argv[0] != NULL) {
		size_t len;
		
		len = strlen(argv[0]);

		/*
		 * If the next argument is NULL then this is this
		 * the last argument, therefore we need to check
		 * for a trailing \c.
		 */
		if (argv[1] == NULL) {
			/* is there room for a '\c' and is there one? */
			if (len >= 2 &&
			    argv[0][len - 2] == '\\' &&
			    argv[0][len - 1] == 'c') {
				/* chop it and set the no-newline flag. */
				len -= 2;
				nflag = 1;
			}
		}
		vp->iov_base = *argv;
		vp++->iov_len = len;
		if (*++argv) {
			vp->iov_base = space;
			vp++->iov_len = 1;
		}
	}
	if (!nflag) {
		veclen++;
		vp->iov_base = newline;
		vp++->iov_len = 1;
	}
	/* assert(veclen == (vp - iov)); */
	while (veclen) {
		int nwrite;

		nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
		if (writev(STDOUT_FILENO, iov, nwrite) == -1)
			errexit(progname, "write");
		iov += nwrite;
		veclen -= nwrite;
	}
	return 0;
}
Пример #17
0
/* Release 3.1 or greater */
apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
                                 apr_hdtr_t * hdtr, apr_off_t * offset,
                                 apr_size_t * len, apr_int32_t flags)
{
    off_t nbytes = 0;
    int rv, i;
    struct sf_hdtr headerstruct;
    apr_size_t bytes_to_send = *len;

    /* Ignore flags for now. */
    flags = 0;

    if (!hdtr) {
        hdtr = &no_hdtr;
    }

    else if (hdtr->numheaders && include_hdrs_in_length()) {

        /* On early versions of FreeBSD sendfile, the number of bytes to send
         * must include the length of the headers.  Don't look at the man page
         * for this :(  Instead, look at the the logic in
         * src/sys/kern/uipc_syscalls::sendfile().
         *
         * This was fixed in the middle of 4.6-STABLE
         */
        for (i = 0; i < hdtr->numheaders; i++) {
            bytes_to_send += hdtr->headers[i].iov_len;
        }
    }

    headerstruct.headers = hdtr->headers;
    headerstruct.hdr_cnt = hdtr->numheaders;
    headerstruct.trailers = hdtr->trailers;
    headerstruct.trl_cnt = hdtr->numtrailers;

    /* FreeBSD can send the headers/footers as part of the system call */
    do {
        if (sock->netmask & APR_INCOMPLETE_WRITE) {
            apr_status_t arv;
            sock->netmask &= ~APR_INCOMPLETE_WRITE;
            arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
            if (arv != APR_SUCCESS) {
                *len = 0;
                return arv;
            }
        }
        if (bytes_to_send) {
            /* We won't dare call sendfile() if we don't have
             * header or file bytes to send because bytes_to_send == 0
             * means send the whole file.
             */
            rv = sendfile(file->filedes, /* file to be sent */
                          sock->socketdes, /* socket */
                          *offset,       /* where in the file to start */
                          bytes_to_send, /* number of bytes to send */
                          &headerstruct, /* Headers/footers */
                          &nbytes,       /* number of bytes written */
                          flags);        /* undefined, set to 0 */

            if (rv == -1) {
                if (errno == EAGAIN) {
                    if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) {
                        sock->netmask |= APR_INCOMPLETE_WRITE;
                    }
                    /* FreeBSD's sendfile can return -1/EAGAIN even if it
                     * sent bytes.  Sanitize the result so we get normal EAGAIN
                     * semantics w.r.t. bytes sent.
                     */
                    if (nbytes) {
                        /* normal exit for a big file & non-blocking io */
                        (*len) = nbytes;
                        return APR_SUCCESS;
                    }
                }
            }
            else {       /* rv == 0 (or the kernel is broken) */
                if (nbytes == 0) {
                    /* Most likely the file got smaller after the stat.
                     * Return an error so the caller can do the Right Thing.
                     */
                    (*len) = nbytes;
                    return APR_EOF;
                }
            }
        }
        else {
            /* just trailer bytes... use writev()
             */
            rv = writev(sock->socketdes,
                        hdtr->trailers,
                        hdtr->numtrailers);
            if (rv > 0) {
                nbytes = rv;
                rv = 0;
            }
            else {
                nbytes = 0;
            }
        }
        if (rv == -1 &&
                errno == EAGAIN &&
                apr_is_option_set(sock->netmask, APR_SO_TIMEOUT)) {
            apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0);
            if (arv != APR_SUCCESS) {
                *len = 0;
                return arv;
            }
        }
    } while (rv == -1 && (errno == EINTR || errno == EAGAIN));

    (*len) = nbytes;
    if (rv == -1) {
        return errno;
    }
    return APR_SUCCESS;
}
Пример #18
0
int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
        Machine *m = userdata;
        int r;

        assert(message);
        assert(m);

        r = sd_bus_message_new_method_return(message, &reply);
        if (r < 0)
                return r;

        r = sd_bus_message_open_container(reply, 'a', "(iay)");
        if (r < 0)
                return r;

        switch (m->class) {

        case MACHINE_HOST: {
                _cleanup_free_ struct local_address *addresses = NULL;
                struct local_address *a;
                int n, i;

                n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
                if (n < 0)
                        return n;

                for (a = addresses, i = 0; i < n; a++, i++) {

                        r = sd_bus_message_open_container(reply, 'r', "iay");
                        if (r < 0)
                                return r;

                        r = sd_bus_message_append(reply, "i", addresses[i].family);
                        if (r < 0)
                                return r;

                        r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family));
                        if (r < 0)
                                return r;

                        r = sd_bus_message_close_container(reply);
                        if (r < 0)
                                return r;
                }

                break;
        }

        case MACHINE_CONTAINER: {
                _cleanup_close_pair_ int pair[2] = { -1, -1 };
                _cleanup_free_ char *us = NULL, *them = NULL;
                _cleanup_close_ int netns_fd = -1;
                const char *p;
                siginfo_t si;
                pid_t child;

                r = readlink_malloc("/proc/self/ns/net", &us);
                if (r < 0)
                        return r;

                p = procfs_file_alloca(m->leader, "ns/net");
                r = readlink_malloc(p, &them);
                if (r < 0)
                        return r;

                if (streq(us, them))
                        return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);

                r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL);
                if (r < 0)
                        return r;

                if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
                        return -errno;

                child = fork();
                if (child < 0)
                        return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");

                if (child == 0) {
                        _cleanup_free_ struct local_address *addresses = NULL;
                        struct local_address *a;
                        int i, n;

                        pair[0] = safe_close(pair[0]);

                        r = namespace_enter(-1, -1, netns_fd, -1, -1);
                        if (r < 0)
                                _exit(EXIT_FAILURE);

                        n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
                        if (n < 0)
                                _exit(EXIT_FAILURE);

                        for (a = addresses, i = 0; i < n; a++, i++) {
                                struct iovec iov[2] = {
                                        { .iov_base = &a->family, .iov_len = sizeof(a->family) },
                                        { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
                                };

                                r = writev(pair[1], iov, 2);
                                if (r < 0)
                                        _exit(EXIT_FAILURE);
                        }

                        pair[1] = safe_close(pair[1]);

                        _exit(EXIT_SUCCESS);
                }
ngx_chain_t *
ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
    int              rc;
    u_char          *prev;
    off_t            size, send, prev_send, aligned, sent, fprev;
    off_t            header_size, file_size;
    ngx_uint_t       eintr, complete;
    ngx_err_t        err;
    ngx_buf_t       *file;
    ngx_array_t      header, trailer;
    ngx_event_t     *wev;
    ngx_chain_t     *cl;
    struct sf_hdtr   hdtr;
    struct iovec    *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS];

    wev = c->write;

    if (!wev->ready) {
        return in;
    }

#if (NGX_HAVE_KQUEUE)

    if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) {
        (void) ngx_connection_error(c, wev->kq_errno,
                               "kevent() reported about an closed connection");
        wev->error = 1;
        return NGX_CHAIN_ERROR;
    }

#endif

    /* the maximum limit size is the maximum size_t value - the page size */

    if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
        limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize;
    }

    send = 0;

    header.elts = headers;
    header.size = sizeof(struct iovec);
    header.nalloc = NGX_HEADERS;
    header.pool = c->pool;

    trailer.elts = trailers;
    trailer.size = sizeof(struct iovec);
    trailer.nalloc = NGX_TRAILERS;
    trailer.pool = c->pool;

    for ( ;; ) {
        file = NULL;
        file_size = 0;
        header_size = 0;
        eintr = 0;
        complete = 0;
        prev_send = send;

        header.nelts = 0;
        trailer.nelts = 0;

        /* create the header iovec and coalesce the neighbouring bufs */

        prev = NULL;
        iov = NULL;

        for (cl = in;
             cl && header.nelts < IOV_MAX && send < limit;
             cl = cl->next)
        {
            if (ngx_buf_special(cl->buf)) {
                continue;
            }

            if (!ngx_buf_in_memory_only(cl->buf)) {
                break;
            }

            size = cl->buf->last - cl->buf->pos;

            if (send + size > limit) {
                size = limit - send;
            }

            if (prev == cl->buf->pos) {
                iov->iov_len += (size_t) size;

            } else {
                iov = ngx_array_push(&header);
                if (iov == NULL) {
                    return NGX_CHAIN_ERROR;
                }

                iov->iov_base = (void *) cl->buf->pos;
                iov->iov_len = (size_t) size;
            }

            prev = cl->buf->pos + (size_t) size;
            header_size += size;
            send += size;
        }


        if (cl && cl->buf->in_file && send < limit) {
            file = cl->buf;

            /* coalesce the neighbouring file bufs */

            do {
                size = cl->buf->file_last - cl->buf->file_pos;

                if (send + size > limit) {
                    size = limit - send;

                    aligned = (cl->buf->file_pos + size + ngx_pagesize - 1)
                               & ~((off_t) ngx_pagesize - 1);

                    if (aligned <= cl->buf->file_last) {
                        size = aligned - cl->buf->file_pos;
                    }
                }

                file_size += size;
                send += size;
                fprev = cl->buf->file_pos + size;
                cl = cl->next;

            } while (cl
                     && cl->buf->in_file
                     && send < limit
                     && file->file->fd == cl->buf->file->fd
                     && fprev == cl->buf->file_pos);
        }

        if (file && header.nelts == 0) {

            /* create the tailer iovec and coalesce the neighbouring bufs */

            prev = NULL;
            iov = NULL;

            while (cl && header.nelts < IOV_MAX && send < limit) {

                if (ngx_buf_special(cl->buf)) {
                    cl = cl->next;
                    continue;
                }

                if (!ngx_buf_in_memory_only(cl->buf)) {
                    break;
                }

                size = cl->buf->last - cl->buf->pos;

                if (send + size > limit) {
                    size = limit - send;
                }

                if (prev == cl->buf->pos) {
                    iov->iov_len += (size_t) size;

                } else {
                    iov = ngx_array_push(&trailer);
                    if (iov == NULL) {
                        return NGX_CHAIN_ERROR;
                    }

                    iov->iov_base = (void *) cl->buf->pos;
                    iov->iov_len = (size_t) size;
                }

                prev = cl->buf->pos + (size_t) size;
                send += size;
                cl = cl->next;
            }
        }

        if (file) {

            /*
             * sendfile() returns EINVAL if sf_hdtr's count is 0,
             * but corresponding pointer is not NULL
             */

            hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL;
            hdtr.hdr_cnt = header.nelts;
            hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL;
            hdtr.trl_cnt = trailer.nelts;

            sent = header_size + file_size;

            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
                           "sendfile: @%O %O h:%O",
                           file->file_pos, sent, header_size);

            rc = sendfile(file->file->fd, c->fd, file->file_pos,
                          &sent, &hdtr, 0);

            if (rc == -1) {
                err = ngx_errno;

                switch (err) {
                case NGX_EAGAIN:
                    break;

                case NGX_EINTR:
                    eintr = 1;
                    break;

                default:
                    wev->error = 1;
                    (void) ngx_connection_error(c, err, "sendfile() failed");
                    return NGX_CHAIN_ERROR;
                }

                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
                               "sendfile() sent only %O bytes", sent);
            }

            if (rc == 0 && sent == 0) {

                /*
                 * if rc and sent equal to zero, then someone
                 * has truncated the file, so the offset became beyond
                 * the end of the file
                 */

                ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                              "sendfile() reported that \"%s\" was truncated",
                              file->file->name.data);

                return NGX_CHAIN_ERROR;
            }

            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0,
                           "sendfile: %d, @%O %O:%O",
                           rc, file->file_pos, sent, file_size + header_size);

        } else {
            rc = writev(c->fd, header.elts, header.nelts);

            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
                           "writev: %d of %uz", rc, send);

            if (rc == -1) {
                err = ngx_errno;

                switch (err) {
                case NGX_EAGAIN:
                    break;

                case NGX_EINTR:
                    eintr = 1;
                    break;

                default:
                    wev->error = 1;
                    ngx_connection_error(c, err, "writev() failed");
                    return NGX_CHAIN_ERROR;
                }

                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                               "writev() not ready");
            }

            sent = rc > 0 ? rc : 0;
        }

        if (send - prev_send == sent) {
            complete = 1;
        }

        c->sent += sent;

        for (cl = in; cl; cl = cl->next) {

            if (ngx_buf_special(cl->buf)) {
                continue;
            }

            if (sent == 0) {
                break;
            }

            size = ngx_buf_size(cl->buf);

            if (sent >= size) {
                sent -= size;

                if (ngx_buf_in_memory(cl->buf)) {
                    cl->buf->pos = cl->buf->last;
                }

                if (cl->buf->in_file) {
                    cl->buf->file_pos = cl->buf->file_last;
                }

                continue;
            }

            if (ngx_buf_in_memory(cl->buf)) {
                cl->buf->pos += (size_t) sent;
            }

            if (cl->buf->in_file) {
                cl->buf->file_pos += sent;
            }

            break;
        }

        if (eintr) {
            continue;
        }

        if (!complete) {
            wev->ready = 0;
            return cl;
        }

        if (send >= limit || cl == NULL) {
            return cl;
        }

        in = cl;
    }
}
Пример #20
0
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
		  st_utime_t timeout)
{
  ssize_t n, rv;
  size_t nleft, nbyte;
  int index, iov_cnt;
  struct iovec *tmp_iov;
  struct iovec local_iov[_LOCAL_MAXIOV];

  /* Calculate the total number of bytes to be sent */
  nbyte = 0;
  for (index = 0; index < iov_size; index++)
    nbyte += iov[index].iov_len;

  rv = (ssize_t)nbyte;
  nleft = nbyte;
  tmp_iov = (struct iovec *) iov;	/* we promise not to modify iov */
  iov_cnt = iov_size;

  while (nleft > 0) {
    if (iov_cnt == 1) {
      if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft)
	rv = -1;
      break;
    }
    if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) {
      if (errno == EINTR)
	continue;
      if (!_IO_NOT_READY_ERROR) {
	rv = -1;
	break;
      }
    } else {
      if ((size_t) n == nleft)
	break;
      nleft -= n;
      /* Find the next unwritten vector */
      n = (ssize_t)(nbyte - nleft);
      for (index = 0; (size_t) n >= iov[index].iov_len; index++)
	n -= iov[index].iov_len;

      if (tmp_iov == iov) {
	/* Must copy iov's around */
	if (iov_size - index <= _LOCAL_MAXIOV) {
	  tmp_iov = local_iov;
	} else {
	  tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec));
	  if (tmp_iov == NULL)
	    return -1;
	}
      }

      /* Fill in the first partial read */
      tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]);
      tmp_iov[0].iov_len = iov[index].iov_len - n;
      index++;
      /* Copy the remaining vectors */
      for (iov_cnt = 1; index < iov_size; iov_cnt++, index++) {
	tmp_iov[iov_cnt].iov_base = iov[index].iov_base;
	tmp_iov[iov_cnt].iov_len = iov[index].iov_len;
      }
    }
    /* Wait until the socket becomes writable */
    if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
      rv = -1;
      break;
    }
  }

  if (tmp_iov != iov && tmp_iov != local_iov)
    free(tmp_iov);

  return rv;
}
Пример #21
0
static int writeData(void* _call)
{
    WriterAVCallData_t* call = (WriterAVCallData_t*) _call;

    int len = 0;

    wma_printf(10, "\n");

    if (call == NULL)
    {
        wma_err("call data is NULL...\n");
        return 0;
    }

    wma_printf(10, "AudioPts %lld\n", call->Pts);

    if ((call->data == NULL) || (call->len <= 0))
    {
        wma_err("parsing NULL Data. ignoring...\n");
        return 0;
    }

    if (call->fd < 0)
    {
        wma_err("file pointer < 0. ignoring ...\n");
        return 0;
    }

    if (initialHeader) {

        unsigned char  PesHeader[PES_MAX_HEADER_SIZE];

        if ((call->private_size <= 0) || (call->private_data == NULL))
        {
            wma_err("private NULL.\n");
            return -1;
        }


	struct iovec iov[2];
	iov[0].iov_base = PesHeader;
	iov[0].iov_len = InsertPesHeader (PesHeader, call->private_size, MPEG_AUDIO_PES_START_CODE, 0, 0);
	iov[1].iov_base = call->private_data;
	iov[1].iov_len = call->private_size;

        len = writev(call->fd, iov, 2);

        initialHeader = 0;
    }

    if (len > -1 && call->len > 0 && call->data)
    {
        unsigned char  PesHeader[PES_MAX_HEADER_SIZE];


	struct iovec iov[2];
	iov[0].iov_base = PesHeader;
	iov[0].iov_len = InsertPesHeader (PesHeader, call->len, MPEG_AUDIO_PES_START_CODE, call->Pts, 0);
	iov[1].iov_base = call->data;
	iov[1].iov_len = call->len;

        ssize_t l = writev(call->fd, iov, 2);
	if (l > -1)
		len += l;
	else
		len = l;
    }

    wma_printf(10, "wma < %d\n", len);

    return len;
}
Пример #22
0
static void dotest(int testers, int me, int fd)
{
	char *bits;
	char val, val0;
	int count, collide, chunk, whenmisc, xfr, i;

	/* Stuff for the readv call */
	struct iovec r_iovec[MAXIOVCNT];
	int r_ioveclen;

	/* Stuff for the writev call */
	struct iovec val0_iovec[MAXIOVCNT];
	struct iovec val_iovec[MAXIOVCNT];
	int w_ioveclen;

	nchunks = max_size / (testers * csize);
	whenmisc = 0;

	if ((bits = malloc((nchunks + 7) / 8)) == NULL) {
		tst_brkm(TBROK, NULL, "\tmalloc failed(bits)");
	}

	/* Allocate memory for the iovec buffers and init the iovec arrays */
	r_ioveclen = w_ioveclen = csize / MAXIOVCNT;

	/* Please note that the above statement implies that csize
	 * be evenly divisible by MAXIOVCNT.
	 */
	for (i = 0; i < MAXIOVCNT; i++) {
		if ((r_iovec[i].iov_base = malloc(r_ioveclen)) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed(iov_base)");
		}
		r_iovec[i].iov_len = r_ioveclen;

		/* Allocate unused memory areas between all the buffers to
		 * make things more diffult for the OS.
		 */
		if (malloc((i + 1) * 8) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed((i+1)*8)");
		}

		if ((val0_iovec[i].iov_base = malloc(w_ioveclen)) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed(val0_iovec)");
		}

		val0_iovec[i].iov_len = w_ioveclen;

		if (malloc((i + 1) * 8) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed((i+1)*8)");
		}

		if ((val_iovec[i].iov_base = malloc(w_ioveclen)) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed(iov_base)");
		}
		val_iovec[i].iov_len = w_ioveclen;

		if (malloc((i + 1) * 8) == NULL) {
			tst_brkm(TBROK, NULL, "\tmalloc failed(((i+1)*8)");
		}
	}

	/*
	 * No init sectors; file-sys makes 0 to start.
	 */
	val = (64 / testers) * me + 1;
	val0 = 0;

	/*
	 * For each iteration:
	 *      zap bits array
	 *      loop:
	 *              pick random chunk, read it.
	 *              if corresponding bit off {
	 *                      verify == 0. (sparse file)
	 *                      ++count;
	 *              } else
	 *                      verify == val.
	 *              write "val" on it.
	 *              repeat until count = nchunks.
	 *      ++val.
	 */
	srand(getpid());

	if (misc_intvl)
		whenmisc = NEXTMISC;

	while (iterations-- > 0) {
		for (i = 0; i < NMISC; i++)
			misc_cnt[i] = 0;
		memset(bits, 0, (nchunks + 7) / 8);
		/* Have to fill the val0 and val iov buffers in a different manner
		 */
		for (i = 0; i < MAXIOVCNT; i++) {
			memset(val0_iovec[i].iov_base, val0,
			       val0_iovec[i].iov_len);
			memset(val_iovec[i].iov_base, val,
			       val_iovec[i].iov_len);

		}

		count = 0;
		collide = 0;

		while (count < nchunks) {
			chunk = rand() % nchunks;
			/*
			 * Read it.
			 */
			if (lseek64(fd, CHUNK(chunk), 0) < 0) {
				tst_brkm(TFAIL,
					 NULL, "\tTest[%d]: lseek64(0) fail at %"
					 PRIx64 "x, errno = %d.", me,
					 CHUNK(chunk), errno);
			}
			if ((xfr = readv(fd, &r_iovec[0], MAXIOVCNT)) < 0) {
				tst_brkm(TFAIL,
					 NULL, "\tTest[%d]: readv fail at %" PRIx64
					 "x, errno = %d.", me, CHUNK(chunk),
					 errno);
			}
			/*
			 * If chunk beyond EOF just write on it.
			 * Else if bit off, haven't seen it yet.
			 * Else, have.  Verify values.
			 */
			if (xfr == 0) {
				bits[chunk / 8] |= (1 << (chunk % 8));
			} else if ((bits[chunk / 8] & (1 << (chunk % 8))) == 0) {
				if (xfr != csize) {
					tst_brkm(TFAIL,
						 NULL,
						 "\tTest[%d]: xfr=%d != %d, zero read.",
						 me, xfr, csize);
				}
				for (i = 0; i < MAXIOVCNT; i++) {
					if (memcmp
					    (r_iovec[i].iov_base,
					     val0_iovec[i].iov_base,
					     r_iovec[i].iov_len)) {
						tst_resm(TFAIL,
							 "\tTest[%d] bad verify @ 0x%"
							 PRIx64
							 " for val %d count %d xfr %d.",
							 me, CHUNK(chunk), val0,
							 count, xfr);
						ft_dumpiov(&r_iovec[i]);
						ft_dumpbits(bits,
							    (nchunks + 7) / 8);
						tst_exit();
					}
				}
				bits[chunk / 8] |= (1 << (chunk % 8));
				++count;
			} else {
				if (xfr != csize) {
					tst_brkm(TFAIL,
						 NULL,
						 "\tTest[%d]: xfr=%d != %d, val read.",
						 me, xfr, csize);
				}
				++collide;
				for (i = 0; i < MAXIOVCNT; i++) {
					if (memcmp
					    (r_iovec[i].iov_base,
					     val_iovec[i].iov_base,
					     r_iovec[i].iov_len)) {
						tst_resm(TFAIL,
							 "\tTest[%d] bad verify @ 0x%"
							 PRIx64
							 " for val %d count %d xfr %d.",
							 me, CHUNK(chunk), val,
							 count, xfr);
						ft_dumpiov(&r_iovec[i]);
						ft_dumpbits(bits,
							    (nchunks + 7) / 8);
						tst_exit();
					}
				}
			}
			/*
			 * Write it.
			 */
			if (lseek64(fd, -xfr, 1) < 0) {
				tst_brkm(TFAIL,
					 NULL, "\tTest[%d]: lseek64(1) fail at %"
					 PRIx64 ", errno = %d.", me,
					 CHUNK(chunk), errno);
			}
			if ((xfr =
			     writev(fd, &val_iovec[0], MAXIOVCNT)) < csize) {
				if (errno == ENOSPC) {
					tst_resm(TFAIL,
						 "\tTest[%d]: no space, exiting.",
						 me);
					fsync(fd);
					tst_exit();
				}
				tst_brkm(TFAIL,
					 NULL, "\tTest[%d]: writev fail at %" PRIx64
					 "x xfr %d, errno = %d.", me,
					 CHUNK(chunk), xfr, errno);
			}
			/*
			 * If hit "misc" interval, do it.
			 */
			if (misc_intvl && --whenmisc <= 0) {
				domisc(me, fd);
				whenmisc = NEXTMISC;
			}
			if (count + collide > 2 * nchunks)
				break;
		}

		/*
		 * End of iteration, maybe before doing all chunks.
		 */

		if (count < nchunks) {
			//tst_resm(TINFO, "\tTest{%d} val %d stopping @ %d, collide = {%d}.",
			//              me, val, count, collide);
			for (i = 0; i < nchunks; i++) {
				if ((bits[i / 8] & (1 << (i % 8))) == 0) {
					if (lseek64(fd, CHUNK(i), 0) <
					    (off64_t) 0) {
						tst_brkm(TFAIL,
							 NULL, "\tTest[%d]: lseek64 fail at %"
							 PRIx64
							 "x, errno = %d.", me,
							 CHUNK(i), errno);
					}
					if (writev(fd, &val_iovec[0], MAXIOVCNT)
					    != csize) {
						tst_brkm(TFAIL,
							 NULL, "\tTest[%d]: writev fail at %"
							 PRIx64
							 "x, errno = %d.", me,
							 CHUNK(i), errno);
					}
				}
			}
		}

		fsync(fd);
		++misc_cnt[m_fsync];
		//tst_resm(TINFO, "\tTest[%d] val %d done, count = %d, collide = %d.",
		//              me, val, count, collide);
		//for (i = 0; i < NMISC; i++)
		//      tst_resm(TINFO, "\t\tTest[%d]: %d %s's.", me, misc_cnt[i], m_str[i]);
		val0 = val++;
	}
}
int32_t TransportUDP::write(uint8_t* buffer, uint32_t size)
{
  {
    boost::mutex::scoped_lock lock(close_mutex_);

    if (closed_)
    {
      ROSCPP_LOG_DEBUG("Tried to write on a closed socket [%d]", sock_);
      return -1;
    }
  }

  ROS_ASSERT((int32_t)size > 0);

  const uint32_t max_payload_size = max_datagram_size_ - sizeof(TransportUDPHeader);

  uint32_t bytes_sent = 0;
  uint32_t this_block = 0;
  if (++current_message_id_ == 0)
    ++current_message_id_;
  while (bytes_sent < size)
  {
    TransportUDPHeader header;
    header.connection_id_ = connection_id_;
    header.message_id_ = current_message_id_;
    if (this_block == 0)
    {
      header.op_ = ROS_UDP_DATA0;
      header.block_ = (size + max_payload_size - 1) / max_payload_size;
    }
    else
    {
      header.op_ = ROS_UDP_DATAN;
      header.block_ = this_block;
    }
    ++this_block;
#if defined(WIN32)
    WSABUF iov[2];
    iov[0].buf = reinterpret_cast<char*>(&header);
    iov[0].len = sizeof(header);
    iov[1].buf = reinterpret_cast<char*>(buffer + bytes_sent);
    iov[1].len = std::min(max_payload_size, size - bytes_sent);
    ssize_t num_bytes;
    if (WSASend(sock_, iov, 2, reinterpret_cast<LPDWORD>(&num_bytes), 0, NULL,
                NULL) == SOCKET_ERROR) {
        num_bytes = -1;
    }
#else
    struct iovec iov[2];
    iov[0].iov_base = &header;
    iov[0].iov_len = sizeof(header);
    iov[1].iov_base = buffer + bytes_sent;
    iov[1].iov_len = std::min(max_payload_size, size - bytes_sent);
    ssize_t num_bytes = writev(sock_, iov, 2);
#endif
    //usleep(100);
    if (num_bytes < 0)
    {
      if( last_socket_error_is_would_block() )
      {
        ROSCPP_LOG_DEBUG("writev() failed with error [%s]", last_socket_error_string());
        close();
        break;
      }
      else
      {
        num_bytes = 0;
      }
    }
    else if (num_bytes < ssize_t(sizeof(header)))
    {
      ROSCPP_LOG_DEBUG("Socket [%d] short write (%d bytes), closing", sock_, int(num_bytes));
      close();
      break;
    }
    else
    {
      num_bytes -= sizeof(header);
    }
    bytes_sent += num_bytes;
  }

  return bytes_sent;
}
Пример #24
0
/* WARNING: all parameters MUST be valid,
 *          NULL pointers lead to a crash.
 */
ret_t
cherokee_socket_writev (cherokee_socket_t  *socket,
			const struct iovec *vector,
			uint16_t            vector_len,
			size_t             *pcnt_written)
{
	int    re;
	int    i;
	ret_t  ret;
	size_t cnt;

	*pcnt_written = 0;

	/* There must be something to send, otherwise behaviour is undefined
	 * and as we don't want this case, we have to enforce assertions.
	 */
	return_if_fail (vector != NULL && vector_len > 0, ret_error);

	if (likely (socket->is_tls != TLS))
	{
#ifdef _WIN32
		int i;
		size_t total;

		for (i = 0, re = 0, total = 0; i < vector_len; i++) {
			if (vector[i].iov_len == 0)
				continue;
			do {
				re = send (SOCKET_FD(socket), vector[i].iov_base, vector[i].iov_len, 0);
			} while ((re == -1) && (errno == EINTR));

			if (re < 0)
				break;

			total += re;

			/* if it is a partial send, then stop sending data
			 */
			if (re != vector[i].iov_len)
				break;
		}
		*pcnt_written = total;

		/* if we have sent at least one byte,
		 * then return OK.
		 */
		if (likely (total > 0))
			return ret_ok;

		if (re == 0) {
			int err = SOCK_ERRNO();
			if (i == vector_len)
				return ret_ok;
			/* Retry later.
			 */
			return ret_eagain;
		}

#else	/* ! WIN32 */

		do {
			re = writev (SOCKET_FD(socket), vector, vector_len);
		} while ((re == -1) && (errno == EINTR));

		if (likely (re > 0)) {
			*pcnt_written = (size_t) re;
			return ret_ok;
		}
		if (re == 0) {
			int i;
			/* Find out whether there was something to send or not.
			 */
			for (i = 0; i < vector_len; i++) {
				if (vector[i].iov_base != NULL && vector[i].iov_len > 0)
					break;
			}
			if (i < vector_len)
				return ret_eagain;
			/* No, nothing to send, so return ok.
			 */
			return ret_ok;
		}
#endif
		if (re < 0) {
			int err = SOCK_ERRNO();

			switch (err) {
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
			case EWOULDBLOCK:
#endif
			case EAGAIN:
				return ret_eagain;

			case EPIPE:
#ifdef ENOTCONN
			case ENOTCONN:
#endif
			case ECONNRESET:
				socket->status = socket_closed;
			case ETIMEDOUT:
			case EHOSTUNREACH:
				return ret_error;
			}

			LOG_ERRNO (errno, cherokee_err_error,
				   CHEROKEE_ERROR_SOCKET_WRITEV, SOCKET_FD(socket));
		}
		return ret_error;

	}

	/* TLS connection: Here we don't worry about sparing a few CPU
	 * cycles, so we reuse the single send case for TLS.
	 */
	for (i = 0; i < vector_len; i++) {
		if ((vector[i].iov_len == 0) ||
		    (vector[i].iov_base == NULL))
			continue;

		cnt = 0;
		ret = cherokee_socket_write (socket, vector[i].iov_base, vector[i].iov_len, &cnt);
		if (ret != ret_ok) {
			return ret;
		}

		*pcnt_written += cnt;
		if (cnt == vector[i].iov_len)
			continue;

		/* Unfinished */
		return ret_ok;
	}

	/* Did send everything */
	return ret_ok;
}
/*
 * Write a filtered log message to stderr.
 *
 * Log format parsing taken from the long-dead utils/Log.cpp.
 */
static void showLog(LogState *state,
        int logPrio, const char* tag, const char* msg)
{
#if defined(HAVE_LOCALTIME_R)
    struct tm tmBuf;
#endif
    struct tm* ptm;
    char timeBuf[32];
    char prefixBuf[128], suffixBuf[128];
    char priChar;
    time_t when;
    pid_t pid, tid;

    TRACE("LOG %d: %s %s", logPrio, tag, msg);

    priChar = getPriorityString(logPrio)[0];
    when = time(NULL);
    pid = tid = getpid();       // find gettid()?

    /*
     * Get the current date/time in pretty form
     *
     * It's often useful when examining a log with "less" to jump to
     * a specific point in the file by searching for the date/time stamp.
     * For this reason it's very annoying to have regexp meta characters
     * in the time stamp.  Don't use forward slashes, parenthesis,
     * brackets, asterisks, or other special chars here.
     */
#if defined(HAVE_LOCALTIME_R)
    ptm = localtime_r(&when, &tmBuf);
#else
    ptm = localtime(&when);
#endif
    //strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm);
    strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);

    /*
     * Construct a buffer containing the log header and log message.
     */
    size_t prefixLen, suffixLen;

    switch (state->outputFormat) {
    case FORMAT_TAG:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "%c/%-8s: ", priChar, tag);
        strcpy(suffixBuf, "\n"); suffixLen = 1;
        break;
    case FORMAT_PROCESS:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "%c(%5d) ", priChar, pid);
        suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
            "  (%s)\n", tag);
        break;
    case FORMAT_THREAD:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "%c(%5d:%5d) ", priChar, pid, tid);
        strcpy(suffixBuf, "\n"); suffixLen = 1;
        break;
    case FORMAT_RAW:
        prefixBuf[0] = 0; prefixLen = 0;
        strcpy(suffixBuf, "\n"); suffixLen = 1;
        break;
    case FORMAT_TIME:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "%s %-8s\n\t", timeBuf, tag);
        strcpy(suffixBuf, "\n"); suffixLen = 1;
        break;
    case FORMAT_THREADTIME:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "%s %5d %5d %c %-8s \n\t", timeBuf, pid, tid, priChar, tag);
        strcpy(suffixBuf, "\n"); suffixLen = 1;
        break;
    case FORMAT_LONG:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "[ %s %5d:%5d %c/%-8s ]\n",
            timeBuf, pid, tid, priChar, tag);
        strcpy(suffixBuf, "\n\n"); suffixLen = 2;
        break;
    default:
        prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
            "%c/%-8s(%5d): ", priChar, tag, pid);
        strcpy(suffixBuf, "\n"); suffixLen = 1;
        break;
     }

    /*
     * Figure out how many lines there will be.
     */
    const char* end = msg + strlen(msg);
    size_t numLines = 0;
    const char* p = msg;
    while (p < end) {
        if (*p++ == '\n') numLines++;
    }
    if (p > msg && *(p-1) != '\n') numLines++;

    /*
     * Create an array of iovecs large enough to write all of
     * the lines with a prefix and a suffix.
     */
    const size_t INLINE_VECS = 6;
    const size_t MAX_LINES   = ((size_t)~0)/(3*sizeof(struct iovec*));
    struct iovec stackVec[INLINE_VECS];
    struct iovec* vec = stackVec;
    size_t numVecs;

    if (numLines > MAX_LINES)
        numLines = MAX_LINES;

    numVecs = numLines*3;  // 3 iovecs per line.
    if (numVecs > INLINE_VECS) {
        vec = (struct iovec*)malloc(sizeof(struct iovec)*numVecs);
        if (vec == NULL) {
            msg = "LOG: write failed, no memory";
            numVecs = 3;
            numLines = 1;
            vec = stackVec;
        }
    }

    /*
     * Fill in the iovec pointers.
     */
    p = msg;
    struct iovec* v = vec;
    int totalLen = 0;
    while (numLines > 0 && p < end) {
        if (prefixLen > 0) {
            v->iov_base = prefixBuf;
            v->iov_len = prefixLen;
            totalLen += prefixLen;
            v++;
        }
        const char* start = p;
        while (p < end && *p != '\n') p++;
        if ((p-start) > 0) {
            v->iov_base = (void*)start;
            v->iov_len = p-start;
            totalLen += p-start;
            v++;
        }
        if (*p == '\n') p++;
        if (suffixLen > 0) {
            v->iov_base = suffixBuf;
            v->iov_len = suffixLen;
            totalLen += suffixLen;
            v++;
        }
        numLines -= 1;
    }
    
    /*
     * Write the entire message to the log file with a single writev() call.
     * We need to use this rather than a collection of printf()s on a FILE*
     * because of multi-threading and multi-process issues.
     *
     * If the file was not opened with O_APPEND, this will produce interleaved
     * output when called on the same file from multiple processes.
     *
     * If the file descriptor is actually a network socket, the writev()
     * call may return with a partial write.  Putting the writev() call in
     * a loop can result in interleaved data.  This can be alleviated
     * somewhat by wrapping the writev call in the Mutex.
     */

    for(;;) {
        int cc = writev(fileno(stderr), vec, v-vec);

        if (cc == totalLen) break;
        
        if (cc < 0) {
            if(errno == EINTR) continue;
            
                /* can't really log the failure; for now, throw out a stderr */
            fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
            break;
        } else {
                /* shouldn't happen when writing to file or tty */
            fprintf(stderr, "+++ LOG: write partial (%d of %d)\n", cc, totalLen);
            break;
        }
    }

    /* if we allocated storage for the iovecs, free it */
    if (vec != stackVec)
        free(vec);
}
Пример #26
0
static int write_message(Server *s, const char *buf, struct ucred *ucred) {
        ssize_t k;
        char priority[6], pid[16];
        struct iovec iovec[5];
        unsigned i = 0;
        char *process = NULL;
        int r = 0;
        int prio = LOG_USER | LOG_INFO;

        assert(s);
        assert(buf);

        parse_syslog_priority((char**) &buf, &prio);

        if (*buf == 0)
                return 0;

        if ((prio & LOG_FACMASK) == 0)
                prio = LOG_USER | LOG_PRI(prio);

        /* First, set priority field */
        snprintf(priority, sizeof(priority), "<%i>", prio);
        char_array_0(priority);
        IOVEC_SET_STRING(iovec[i++], priority);

        /* Second, skip date */
        skip_date(&buf);

        /* Then, add process if set */
        if (read_process(&buf, &iovec[i]) > 0)
                i++;
        else if (ucred &&
                 ucred->pid > 0 &&
                 get_process_name(ucred->pid, &process) >= 0)
                IOVEC_SET_STRING(iovec[i++], process);

        /* Skip the stored PID if we have a better one */
        if (ucred) {
                snprintf(pid, sizeof(pid), "[%lu]: ", (unsigned long) ucred->pid);
                char_array_0(pid);
                IOVEC_SET_STRING(iovec[i++], pid);

                skip_pid(&buf);

                if (*buf == ':')
                        buf++;

                buf += strspn(buf, WHITESPACE);
        }

        /* Is the remaining message empty? */
        if (*buf) {

                /* And the rest is the message */
                IOVEC_SET_STRING(iovec[i++], buf);
                IOVEC_SET_STRING(iovec[i++], "\n");

                if ((k = writev(s->kmsg_fd, iovec, i)) <= 0) {
                        log_error("Failed to write log message to kmsg: %s", k < 0 ? strerror(errno) : "short write");
                        r = k < 0 ? -errno : -EIO;
                }
        }

        free(process);

        return r;
}
Пример #27
0
int echo_main(int argc, char **argv)
{
	struct iovec io[argc];
	struct iovec *cur_io = io;
	char *arg;
	char *p;
#if !ENABLE_FEATURE_FANCY_ECHO
	enum {
		eflag = '\\',
		nflag = 1,  /* 1 -- print '\n' */
	};
	arg = *++argv;
	if (!arg)
		goto newline_ret;
#else
	char nflag = 1;
	char eflag = 0;

	while (1) {
		arg = *++argv;
		if (!arg)
			goto newline_ret;
		if (*arg != '-')
			break;

		/* If it appears that we are handling options, then make sure
		 * that all of the options specified are actually valid.
		 * Otherwise, the string should just be echoed.
		 */
		p = arg + 1;
		if (!*p)	/* A single '-', so echo it. */
			goto just_echo;

		do {
			if (!strrchr("neE", *p))
				goto just_echo;
		} while (*++p);

		/* All of the options in this arg are valid, so handle them. */
		p = arg + 1;
		do {
			if (*p == 'n')
				nflag = 0;
			if (*p == 'e')
				eflag = '\\';
		} while (*++p);
	}
 just_echo:
#endif

	while (1) {
		/* arg is already == *argv and isn't NULL */
		int c;

		cur_io->iov_base = p = arg;

		if (!eflag) {
			/* optimization for very common case */
			p += strlen(arg);
		} else while ((c = *arg++)) {
			if (c == eflag) {	/* Check for escape seq. */
				if (*arg == 'c') {
					/* '\c' means cancel newline and
					 * ignore all subsequent chars. */
					cur_io->iov_len = p - (char*)cur_io->iov_base;
					cur_io++;
					goto ret;
				}
#if !ENABLE_FEATURE_FANCY_ECHO
				/* SUSv3 specifies that octal escapes must begin with '0'. */
				if ( (((unsigned char)*arg) - '1') >= 7)
#endif
				{
					/* Since SUSv3 mandates a first digit of 0, 4-digit octals
					* of the form \0### are accepted. */
					if (*arg == '0' && ((unsigned char)(arg[1]) - '0') < 8) {
						arg++;
					}
					/* bb_process_escape_sequence can handle nul correctly */
					c = bb_process_escape_sequence( (void*) &arg);
				}
			}
			*p++ = c;
		}

		arg = *++argv;
		if (arg)
			*p++ = ' ';
		cur_io->iov_len = p - (char*)cur_io->iov_base;
		cur_io++;
		if (!arg)
			break;
	}

 newline_ret:
	if (nflag) {
		cur_io->iov_base = (char*)"\n";
		cur_io->iov_len = 1;
		cur_io++;
	}
 ret:
	/* TODO: implement and use full_writev? */
	return writev(1, io, (cur_io - io)) >= 0;
}
Пример #28
0
int status_vprintf(const char *status, bool ellipse, bool ephemeral, const char *format, va_list ap) {
        static const char status_indent[] = "         "; /* "[" STATUS "] " */
        _cleanup_free_ char *s = NULL;
        _cleanup_close_ int fd = -1;
        struct iovec iovec[6] = {};
        int n = 0;
        static bool prev_ephemeral;

        assert(format);

        /* This is independent of logging, as status messages are
         * optional and go exclusively to the console. */

        if (vasprintf(&s, format, ap) < 0)
                return log_oom();

        fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
        if (fd < 0)
                return fd;

        if (ellipse) {
                char *e;
                size_t emax, sl;
                int c;

                c = fd_columns(fd);
                if (c <= 0)
                        c = 80;

                sl = status ? sizeof(status_indent)-1 : 0;

                emax = c - sl - 1;
                if (emax < 3)
                        emax = 3;

                e = ellipsize(s, emax, 50);
                if (e) {
                        free(s);
                        s = e;
                }
        }

        if (prev_ephemeral)
                IOVEC_SET_STRING(iovec[n++], "\r" ANSI_ERASE_TO_END_OF_LINE);
        prev_ephemeral = ephemeral;

        if (status) {
                if (!isempty(status)) {
                        IOVEC_SET_STRING(iovec[n++], "[");
                        IOVEC_SET_STRING(iovec[n++], status);
                        IOVEC_SET_STRING(iovec[n++], "] ");
                } else
                        IOVEC_SET_STRING(iovec[n++], status_indent);
        }

        IOVEC_SET_STRING(iovec[n++], s);
        if (!ephemeral)
                IOVEC_SET_STRING(iovec[n++], "\n");

        if (writev(fd, iovec, n) < 0)
                return -errno;

        return 0;
}
Пример #29
0
void module_generate(int fd)
{
    size_t i;
    DIR* proc_listing;

    /* Set up an iovec array. We'll fill this with buffers that'll
     * be part of our output, growing it dynamically as necessary. */

    /* The number of elements in the array that we've used. */
    size_t vec_length = 0;

    /* The allocate size of the array. */
    size_t vec_size = 16;

    /* The array of iovcec elements. */
    struct iovec* vec = (struct iovec*)
            xmalloc(vec_size * sizeof(struct iovec));

    /* The first buffer is the HTML source for the start of the pate. */
    vec[vec_length].iov_base = page_start;
    vec[vec_length].iov_len = strlen(page_start);
    ++vec_length;

    /* Start a directory listing for /proc. */
    proc_listing = opendir("/proc");
    if (proc_listing == NULL) {
        system_error("opendir");
    }

    /* Loop over directory entries in /proc. */
    while (1) {
        struct dirent* proc_entry;
        const char* name;
        pid_t pid;
        char* process_info;

        /* Get the next entry in /proc. */
        proc_entry = readdir(proc_listing);
        if (proc_entry == NULL) {
            /* We've hit the end of the listing. */
            break;
        }

        /* If this entry is not composed purely of digits, it's not a
         * process directory, so skip it. */
        name = proc_entry->d_name;
        if (strspn(name, "0123456789") != strlen(name)) {
            continue;
        }

        /* The name of the entry is the process ID. */
        pid = (pid_t) atoi(name);

        /* Generate HTML for a table row describing this process. */
        process_info = format_process_info(pid);
        if (process_info == NULL) {
            /* Something went wrong. The process may have vanished
             * while we were looking at it. Use a placeholder row
             * instead. */
            process_info = "    <tr><td colspan=\"5\">ERROR</td></tr>";
        }

        /* Make sure the iovec array is long enough to hold this buffer
         * (plus one more because we'll add an extra element when we're
         * done listing processes). If not, grow it to twice its current
         * size. */
        if (vec_length == vec_size - 1) {
            vec_size *= 2;
            vec = xrealloc(vec, vec_size * sizeof(struct iovec));
        }

        /* Store this buffer as the next element of the array. */
        vec[vec_length].iov_base = process_info;
        vec[vec_length].iov_len = strlen(process_info);
        ++vec_length;
    }

    /* End the directory listing operation. */
    closedir(proc_listing);

    /* Add one last buffer with HTML that ends the page. */
    vec[vec_length].iov_base = page_end;
    vec[vec_length].iov_len = strlen(page_end);
    ++vec_length;

    /* Output the entire page to the client file descriptor all
     * at once. */
    writev(fd, vec, vec_length);

    /* Deallocate the buffers we created. The first and last are
     * static and should not be deallocated. */
    for (i = 1; i < vec_length - 1; ++i) {
        free(vec[i].iov_base);
    }

    /* Deallocate the iovec array. */
    free(vec);
}
Пример #30
0
/*****************************************************************************
 * output_Flush
 *****************************************************************************/
static void output_Flush( output_t *p_output )
{
    packet_t *p_packet = p_output->p_packets;
    int i_block_cnt = output_BlockCount( p_output );
    struct iovec p_iov[i_block_cnt + 2];
    uint8_t p_rtp_hdr[RTP_HEADER_SIZE];
    int i_iov = 0, i_payload_len, i_block;

    if ( (p_output->config.i_config & OUTPUT_RAW) )
    {
        p_iov[i_iov].iov_base = &p_output->raw_pkt_header;
        p_iov[i_iov].iov_len = sizeof(struct udprawpkt);
        i_iov++;
    }

    if ( !(p_output->config.i_config & OUTPUT_UDP) )
    {
        p_iov[i_iov].iov_base = p_rtp_hdr;
        p_iov[i_iov].iov_len = sizeof(p_rtp_hdr);

        rtp_set_hdr( p_rtp_hdr );
        rtp_set_type( p_rtp_hdr, RTP_TYPE_TS );
        rtp_set_seqnum( p_rtp_hdr, p_output->i_seqnum++ );
        rtp_set_timestamp( p_rtp_hdr,
                           p_output->i_ref_timestamp
                            + (p_packet->i_dts - p_output->i_ref_wallclock)
                               * 9 / 100 );
        rtp_set_ssrc( p_rtp_hdr, p_output->config.pi_ssrc );

        i_iov++;
    }

    for ( i_block = 0; i_block < p_packet->i_depth; i_block++ )
    {
        /* Do pid mapping here if needed.
         * save the original pid in the block.
         * set the pid to the new pid
         * later we re-instate the old pid for the next output
         */
        if ( b_do_remap || p_output->b_do_remap ) {
            block_t *p_block = p_packet->pp_blocks[i_block];
            uint16_t i_pid = ts_get_pid( p_block->p_ts );
            p_block->tmp_pid = UNUSED_PID;
            if ( p_output->pi_newpids[i_pid] != UNUSED_PID )
            {
                uint16_t i_newpid = p_output->pi_newpids[i_pid];
                /* Need to map this pid to the new pid */
                ts_set_pid( p_block->p_ts, i_newpid );
                p_block->tmp_pid = i_pid;
            }
        }

        p_iov[i_iov].iov_base = p_packet->pp_blocks[i_block]->p_ts;
        p_iov[i_iov].iov_len = TS_SIZE;
        i_iov++;
    }

    for ( ; i_block < i_block_cnt; i_block++ )
    {
        p_iov[i_iov].iov_base = p_pad_ts;
        p_iov[i_iov].iov_len = TS_SIZE;
        i_iov++;
    }

    
    if ( (p_output->config.i_config & OUTPUT_RAW) )
    {
        i_payload_len = 0;
        for ( i_block = 1; i_block < i_iov; i_block++ ) {
            i_payload_len += p_iov[i_block].iov_len; 
        }
        p_output->raw_pkt_header.udph.len = htons(sizeof(struct udpheader) + i_payload_len);
    }

    if ( writev( p_output->i_handle, p_iov, i_iov ) < 0 )
    {
        msg_Err( NULL, "couldn't writev to %s (%s)",
                 p_output->config.psz_displayname, strerror(errno) );
    }
    /* Update the wallclock because writev() can take some time. */
    i_wallclock = mdate();

    for ( i_block = 0; i_block < p_packet->i_depth; i_block++ )
    {
        p_packet->pp_blocks[i_block]->i_refcount--;
        if ( !p_packet->pp_blocks[i_block]->i_refcount )
            block_Delete( p_packet->pp_blocks[i_block] );
        else if ( b_do_remap || p_output->b_do_remap ) {
            /* still referenced so re-instate the orignial pid if remapped */
            block_t * p_block = p_packet->pp_blocks[i_block];
            if (p_block->tmp_pid != UNUSED_PID)
                ts_set_pid( p_block->p_ts, p_block->tmp_pid );
        }
    }
    p_output->p_packets = p_packet->p_next;
    free( p_packet );
    if ( p_output->p_packets == NULL )
        p_output->p_last_packet = NULL;
}