Example #1
0
static int
decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
{
	struct cmsghdr *cmsg;
	size_t size, max, i;
	int overflow = 0;

	for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
	     cmsg = CMSG_NXTHDR(msg, cmsg)) {
		if (cmsg->cmsg_level != SOL_SOCKET ||
		    cmsg->cmsg_type != SCM_RIGHTS)
			continue;

		size = cmsg->cmsg_len - CMSG_LEN(0);
		max = sizeof(buffer->data) - wl_buffer_size(buffer);
		if (size > max || overflow) {
			overflow = 1;
			size /= sizeof(int32_t);
			for (i = 0; i < size; i++)
				close(((int*)CMSG_DATA(cmsg))[i]);
		} else if (wl_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) {
				return -1;
		}
	}

	if (overflow) {
		errno = EOVERFLOW;
		return -1;
	}

	return 0;
}
Example #2
0
static int
wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
{
	if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
		connection->want_flush = 1;
		if (wl_connection_flush(connection) < 0)
			return -1;
	}

	return wl_buffer_put(&connection->fds_out, &fd, sizeof fd);
}
Example #3
0
static int
wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
{
	if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd)
		if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
			return -1;

	wl_buffer_put(&connection->fds_out, &fd, sizeof fd);

	return 0;
}
Example #4
0
void
wl_connection_write(struct wl_connection *connection,
		    const void *data, size_t count)
{
	wl_buffer_put(&connection->out, data, count);

	if (connection->out.head - connection->out.tail == count)
		connection->update(connection,
				   WL_CONNECTION_READABLE |
				   WL_CONNECTION_WRITABLE,
				   connection->data);
}
Example #5
0
int
wl_connection_queue(struct wl_connection *connection,
		    const void *data, size_t count)
{
	if (connection->out.head - connection->out.tail +
	    count > ARRAY_LENGTH(connection->out.data)) {
		connection->want_flush = 1;
		if (wl_connection_flush(connection) < 0)
			return -1;
	}

	return wl_buffer_put(&connection->out, data, count);
}
Example #6
0
int
wl_connection_queue(struct wl_connection *connection,
		    const void *data, size_t count)
{
	if (connection->out.head - connection->out.tail +
	    count > ARRAY_LENGTH(connection->out.data))
		if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
			return -1;

	wl_buffer_put(&connection->out, data, count);

	return 0;
}
Example #7
0
static void
decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg)
{
	struct cmsghdr *cmsg;
	size_t size;

	for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
	     cmsg = CMSG_NXTHDR(msg, cmsg)) {
		if (cmsg->cmsg_level == SOL_SOCKET &&
		    cmsg->cmsg_type == SCM_RIGHTS) {
			size = cmsg->cmsg_len - CMSG_LEN(0);
			wl_buffer_put(buffer, CMSG_DATA(cmsg), size);
		}
	}
}
Example #8
0
int
wl_connection_write(struct wl_connection *connection,
		    const void *data, size_t count)
{
	if (connection->out.head - connection->out.tail +
	    count > ARRAY_LENGTH(connection->out.data))
		if (wl_connection_data(connection, WL_CONNECTION_WRITABLE))
			return -1;

	wl_buffer_put(&connection->out, data, count);

	if (!connection->write_signalled) {
		connection->update(connection,
				   WL_CONNECTION_READABLE |
				   WL_CONNECTION_WRITABLE,
				   connection->data);
		connection->write_signalled = 1;
	}

	return 0;
}
Example #9
0
struct wl_closure *
wl_connection_vmarshal(struct wl_connection *connection,
		       struct wl_object *sender,
		       uint32_t opcode, va_list ap,
		       const struct wl_message *message)
{
	struct wl_closure *closure = &connection->send_closure;
	struct wl_object **objectp, *object;
	uint32_t length, *p, *start, size;
	int dup_fd;
	struct wl_array **arrayp, *array;
	const char **sp, *s;
	char *extra;
	int i, count, fd, extra_size, *fd_ptr;

	extra_size = wl_message_size_extra(message);
	count = strlen(message->signature) + 2;
	extra = (char *) closure->buffer;
	start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
	p = &start[2];
	for (i = 2; i < count; i++) {
		switch (message->signature[i - 2]) {
		case 'u':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p;
			*p++ = va_arg(ap, uint32_t);
			break;
		case 'i':
			closure->types[i] = &ffi_type_sint32;
			closure->args[i] = p;
			*p++ = va_arg(ap, int32_t);
			break;
		case 's':
			closure->types[i] = &ffi_type_pointer;
			closure->args[i] = extra;
			sp = (const char **) extra;
			extra += sizeof *sp;

			s = va_arg(ap, const char *);
			length = s ? strlen(s) + 1: 0;
			*p++ = length;

			if (length > 0)
				*sp = (const char *) p;
			else
				*sp = NULL;

			memcpy(p, s, length);
			p += DIV_ROUNDUP(length, sizeof *p);
			break;
		case 'o':
			closure->types[i] = &ffi_type_pointer;
			closure->args[i] = extra;
			objectp = (struct wl_object **) extra;
			extra += sizeof *objectp;

			object = va_arg(ap, struct wl_object *);
			*objectp = object;
			*p++ = object ? object->id : 0;
			break;

		case 'n':
			closure->types[i] = &ffi_type_uint32;
			closure->args[i] = p;
			object = va_arg(ap, struct wl_object *);
			*p++ = object->id;
			break;

		case 'a':
			closure->types[i] = &ffi_type_pointer;
			closure->args[i] = extra;
			arrayp = (struct wl_array **) extra;
			extra += sizeof *arrayp;

			*arrayp = (struct wl_array *) extra;
			extra += sizeof **arrayp;

			array = va_arg(ap, struct wl_array *);
			if (array == NULL || array->size == 0) {
				*p++ = 0;
				break;
			}
			*p++ = array->size;
			memcpy(p, array->data, array->size);

			(*arrayp)->size = array->size;
			(*arrayp)->alloc = array->alloc;
			(*arrayp)->data = p;

			p += DIV_ROUNDUP(array->size, sizeof *p);
			break;

		case 'h':
			closure->types[i] = &ffi_type_sint;
			closure->args[i] = extra;
			fd_ptr = (int *) extra;
			extra += sizeof *fd_ptr;

			fd = va_arg(ap, int);
			dup_fd = dup(fd);
			if (dup_fd < 0) {
				fprintf(stderr, "dup failed: %m");
				abort();
			}
			*fd_ptr = dup_fd;
			wl_buffer_put(&connection->fds_out,
				      &dup_fd, sizeof dup_fd);
			break;
		default:
			assert(0);
			break;
		}
	}

	size = (p - start) * sizeof *p;
	start[0] = sender->id;
	start[1] = opcode | (size << 16);

	closure->start = start;
	closure->message = message;
	closure->count = count;

	return closure;
}