...
 
Commits (19)
......@@ -16,9 +16,15 @@ endif
if BUILD_DRI2
pkgconfig_DATA += xcb-dri2.pc
endif
if BUILD_DRI3
pkgconfig_DATA += xcb-dri3.pc
endif
if BUILD_GLX
pkgconfig_DATA += xcb-glx.pc
endif
if BUILD_PRESENT
pkgconfig_DATA += xcb-present.pc
endif
if BUILD_RANDR
pkgconfig_DATA += xcb-randr.pc
endif
......
Release 1.9.1 (2013-05-30)
==========================
* Fix python code to work with python-3
* Security fix for integer overflow in read_packet() [CVE-2013-2064]
Release 1.9 (2012-10-05)
========================
......
......@@ -4,18 +4,19 @@
# Initialize Autoconf
AC_PREREQ(2.57)
AC_INIT([libxcb],
1.9,
1.9.3,
[xcb@lists.freedesktop.org])
AC_CONFIG_SRCDIR([xcb.pc.in])
# Set common system defines for POSIX extensions, such as _GNU_SOURCE
# Must be called before any macros that run the compiler (like AC_PROG_LIBTOOL)
# to avoid autoconf errors.
AC_USE_SYSTEM_EXTENSIONS
# Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-bzip2])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Set common system defines for POSIX extensions, such as _GNU_SOURCE
# Must be called before any macros that run the compiler (like AC_PROG_LIBTOOL)
# to avoid autoconf errors.
AC_USE_SYSTEM_EXTENSIONS
AM_PATH_PYTHON([2.6])
PKG_CHECK_MODULES(CHECK, [check >= 0.9.4], [HAVE_CHECK=yes], [HAVE_CHECK=no])
......@@ -41,7 +42,7 @@ fi
AC_SUBST(HTML_CHECK_RESULT)
# Checks for pkg-config packages
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.7)
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.9)
NEEDED="pthread-stubs xau >= 0.99.2"
PKG_CHECK_MODULES(NEEDED, $NEEDED)
......@@ -81,6 +82,55 @@ AC_HEADER_STDC
AC_SEARCH_LIBS(getaddrinfo, socket)
AC_SEARCH_LIBS(connect, socket)
AC_ARG_ENABLE(sendfds, AS_HELP_STRING([--disable-sendfds], [Support FD passing (default: auto)]),
[sendfds=$enableval], [sendfds=auto])
case x$sendfds in
xauto)
AC_SEARCH_LIBS(sendmsg, socket, [sendfds="yes"], [sendfds="no"])
;;
esac
# XPG4v2/UNIX95 added msg_control - check to see if we need to define
# _XOPEN_SOURCE to get it (such as on Solaris)
AC_CHECK_MEMBER([struct msghdr.msg_control], [], [],
[
AC_INCLUDES_DEFAULT
#include <sys/socket.h>
])
# First try for Solaris in C99 compliant mode, which requires XPG6/UNIX03
if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then
unset ac_cv_member_struct_msghdr_msg_control
AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=600])
AC_CHECK_MEMBER([struct msghdr.msg_control],
[AC_DEFINE([_XOPEN_SOURCE], [600],
[Defined if needed to expose struct msghdr.msg_control])
], [], [
#define _XOPEN_SOURCE 600
AC_INCLUDES_DEFAULT
#include <sys/socket.h>
])
fi
# If that didn't work, fall back to XPG5/UNIX98 with C89
if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then
unset ac_cv_member_struct_msghdr_msg_control
AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=500])
AC_CHECK_MEMBER([struct msghdr.msg_control],
[AC_DEFINE([_XOPEN_SOURCE], [500],
[Defined if needed to expose struct msghdr.msg_control])
], [sendfds="no"], [
#define _XOPEN_SOURCE 500
AC_INCLUDES_DEFAULT
#include <sys/socket.h>
])
fi
case x$sendfds in
xyes)
AC_DEFINE([HAVE_SENDMSG],1,[Define if your platform supports sendmsg])
;;
esac
have_win32="no"
lt_enable_auto_import=""
case $host_os in
......@@ -128,7 +178,7 @@ xcbincludedir='${includedir}/xcb'
AC_SUBST(xcbincludedir)
if test "x$GCC" = xyes ; then
CWARNFLAGS="-Wall -pedantic -Wpointer-arith \
CWARNFLAGS="-Wall -Wpointer-arith \
-Wstrict-prototypes -Wmissing-declarations -Wnested-externs"
else
AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"])
......@@ -178,7 +228,9 @@ XCB_EXTENSION(Composite, "yes")
XCB_EXTENSION(Damage, "yes")
XCB_EXTENSION(DPMS, "yes")
XCB_EXTENSION(DRI2, "yes")
XCB_EXTENSION(DRI3, "$sendfds")
XCB_EXTENSION(GLX, "yes")
XCB_EXTENSION(Present, "yes")
XCB_EXTENSION(RandR, "yes")
XCB_EXTENSION(Record, "yes")
XCB_EXTENSION(Render, "yes")
......@@ -222,7 +274,9 @@ xcb-composite.pc
xcb-damage.pc
xcb-dpms.pc
xcb-dri2.pc
xcb-dri3.pc
xcb-glx.pc
xcb-present.pc
xcb-randr.pc
xcb-record.pc
xcb-render.pc
......@@ -257,6 +311,7 @@ echo " Package: ${PACKAGE_NAME} ${PACKAGE_VERSION}"
echo ""
echo " Configuration"
echo " XDM support.........: ${have_xdmcp}"
echo " sendmsg fd passing..: ${sendfds}"
echo " Build unit tests....: ${HAVE_CHECK}"
echo " XCB buffer size.....: ${xcb_queue_buffer_size}"
echo ""
......@@ -265,6 +320,7 @@ echo " Composite...........: ${BUILD_COMPOSITE}"
echo " Damage..............: ${BUILD_DAMAGE}"
echo " Dpms................: ${BUILD_DPMS}"
echo " Dri2................: ${BUILD_DRI2}"
echo " Dri3................: ${BUILD_DRI3}"
echo " Glx.................: ${BUILD_GLX}"
echo " Randr...............: ${BUILD_RANDR}"
echo " Record..............: ${BUILD_RECORD}"
......
......@@ -3,7 +3,9 @@ composite.*
damage.*
dpms.*
dri2.*
dri3.*
glx.*
present.*
randr.*
record.*
render.*
......
......@@ -56,6 +56,22 @@ libxcb_dri2_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h
endif
EXTSOURCES += dri3.c
if BUILD_DRI3
lib_LTLIBRARIES += libxcb-dri3.la
libxcb_dri3_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_dri3_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_dri3_la_SOURCES = dri3.c dri3.h
endif
EXTSOURCES += present.c
if BUILD_PRESENT
lib_LTLIBRARIES += libxcb-present.la
libxcb_present_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_present_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_present_la_SOURCES = present.c present.h
endif
EXTSOURCES += glx.c
if BUILD_GLX
lib_LTLIBRARIES += libxcb-glx.la
......@@ -233,7 +249,7 @@ EXTRA_DIST = $(STATIC_MANS)
BUILT_SOURCES = $(EXTSOURCES) $(BUILT_MANS)
CLEANFILES = $(EXTSOURCES) $(EXTHEADERS) $(BUILT_MANS)
$(EXTSOURCES): c_client.py
$(EXTSOURCES): c_client.py $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml)
$(PYTHON) $(srcdir)/c_client.py -p $(XCBPROTO_XCBPYTHONDIR) $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml)
$(man_MANS): $(EXTSOURCES)
......@@ -303,6 +303,7 @@ def _c_type_setup(self, name, postfix):
self.c_reply_name = _n(name + ('reply',))
self.c_reply_type = _t(name + ('reply',))
self.c_cookie_type = _t(name + ('cookie',))
self.c_reply_fds_name = _n(name + ('reply_fds',))
self.need_aux = False
self.need_serialize = False
......@@ -687,10 +688,20 @@ def _c_serialize_helper_switch(context, self, complex_name,
switch_expr = _c_accessor_get_expr(self.expr, None)
for b in self.bitcases:
bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
# code_lines.append(' printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' %
# (self.name[-1], b.type.name[-1], bitcase_expr))
len_expr = len(b.type.expr)
for n, expr in enumerate(b.type.expr):
bitcase_expr = _c_accessor_get_expr(expr, None)
# only one <enumref> in the <bitcase>
if len_expr == 1:
code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
# multiple <enumref> in the <bitcase>
elif n == 0: # first
code_lines.append(' if((%s & %s) ||' % (switch_expr, bitcase_expr))
elif len_expr == (n + 1): # last
code_lines.append(' (%s & %s)) {' % (switch_expr, bitcase_expr))
else: # between first and last
code_lines.append(' (%s & %s) ||' % (switch_expr, bitcase_expr))
b_prefix = prefix
if b.type.has_name:
b_prefix = prefix + [(b.c_field_name, '.', b.type)]
......@@ -1825,7 +1836,7 @@ def c_union(self, name):
_c_complex(self)
_c_iterator(self, name)
def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
'''
Declares a request function.
'''
......@@ -1854,6 +1865,12 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
# What flag is passed to xcb_request
func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
if reply_fds:
if func_flags == '0':
func_flags = 'XCB_REQUEST_REPLY_FDS'
else:
func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
# Global extension id variable or NULL for xproto
func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
......@@ -2139,6 +2156,10 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
# no padding necessary - _serialize() keeps track of padding automatically
_c(' ')
for field in param_fields:
if field.isfd:
_c(' xcb_send_fd(c, %s);', field.c_field_name)
_c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
# free dyn. all. data, if any
......@@ -2242,6 +2263,51 @@ def _c_reply(self, name):
_c('}')
def _c_reply_has_fds(self):
for field in self.fields:
if field.isfd:
return True
return False
def _c_reply_fds(self, name):
'''
Declares the function that returns fds related to the reply.
'''
spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
_h('')
_h('/**')
_h(' * Return the reply fds')
_h(' * @param c The connection')
_h(' * @param reply The reply')
_h(' *')
_h(' * Returns the array of reply fds of the request asked by')
_h(' * ')
_h(' * The returned value must be freed by the caller using free().')
_h(' */')
_c('')
_hc('')
_hc('/*****************************************************************************')
_hc(' **')
_hc(' ** int * %s', self.c_reply_fds_name)
_hc(' ** ')
_hc(' ** @param xcb_connection_t%s *c', spacing1)
_hc(' ** @param %s *reply', self.c_reply_type)
_hc(' ** @returns int *')
_hc(' **')
_hc(' *****************************************************************************/')
_hc(' ')
_hc('int *')
_hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
_h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
_c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
_c('{')
_c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
_c('}')
def _c_opcode(name, opcode):
'''
Declares the opcode define for requests, events, and errors.
......@@ -2802,14 +2868,17 @@ def c_request(self, name):
# Reply structure definition
_c_complex(self.reply)
# Request prototypes
_c_request_helper(self, name, self.c_cookie_type, False, True)
_c_request_helper(self, name, self.c_cookie_type, False, False)
has_fds = _c_reply_has_fds(self.reply)
_c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
_c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
if self.need_aux:
_c_request_helper(self, name, self.c_cookie_type, False, True, True)
_c_request_helper(self, name, self.c_cookie_type, False, False, True)
_c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
_c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
# Reply accessors
_c_accessors(self.reply, name + ('reply',), name)
_c_reply(self, name)
if has_fds:
_c_reply_fds(self, name)
else:
# Request prototypes
_c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
......@@ -2827,6 +2896,23 @@ def c_event(self, name):
'''
Exported function that handles event declarations.
'''
# The generic event structure xcb_ge_event_t has the full_sequence field
# at the 32byte boundary. That's why we've to inject this field into GE
# events while generating the structure for them. Otherwise we would read
# garbage (the internal full_sequence) when accessing normal event fields
# there.
if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
event_size = 0
for field in self.fields:
if field.type.size != None and field.type.nmemb != None:
event_size += field.type.size * field.type.nmemb
if event_size == 32:
full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
idx = self.fields.index(field)
self.fields.insert(idx + 1, full_sequence)
break
_c_type_setup(self, name, ('event',))
# Opcode define
......
......@@ -87,6 +87,9 @@ extern "C" {
/** Connection closed because the server does not have a screen matching the display. */
#define XCB_CONN_CLOSED_INVALID_SCREEN 6
/** Connection closed because some FD passing operation failed */
#define XCB_CONN_CLOSED_FDPASSING_FAILED 7
#define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
/* Opaque structures */
......@@ -137,23 +140,6 @@ typedef struct {
uint32_t full_sequence; /**< full sequence */
} xcb_generic_event_t;
/**
* @brief GE event
*
* An event as sent by the XGE extension. The length field specifies the
* number of 4-byte blocks trailing the struct.
*/
typedef struct {
uint8_t response_type; /**< Type of the response */
uint8_t pad0; /**< Padding */
uint16_t sequence; /**< Sequence number */
uint32_t length;
uint16_t event_type;
uint16_t pad1;
uint32_t pad[5]; /**< Padding */
uint32_t full_sequence; /**< full sequence */
} xcb_ge_event_t;
/**
* @brief Generic error.
*
......@@ -305,6 +291,39 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c);
*/
xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c);
typedef struct xcb_special_event xcb_special_event_t;
/**
* @brief Returns the next event from a special queue
*/
xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
/**
* @brief Returns the next event from a special queue, blocking until one arrives
*/
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
/**
* @typedef typedef struct xcb_extension_t xcb_extension_t
*/
typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */
/**
* @brief Listen for a special event
*/
xcb_special_event_t *xcb_register_for_special_xge(xcb_connection_t *c,
xcb_extension_t *ext,
uint32_t eid,
uint32_t *stamp);
/**
* @brief Stop listening for a special event
*/
void xcb_unregister_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
/**
* @brief Return the error for a request, or NULL if none can ever arrive.
* @param c: The connection to the X server.
......@@ -342,11 +361,6 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence);
/* xcb_ext.c */
/**
* @typedef typedef struct xcb_extension_t xcb_extension_t
*/
typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */
/**
* @brief Caches reply information from QueryExtension requests.
* @param c: The connection.
......
......@@ -214,9 +214,39 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
if (n > IOV_MAX)
n = IOV_MAX;
n = writev(c->fd, *vector, n);
if(n < 0 && errno == EAGAIN)
return 1;
#if HAVE_SENDMSG
if (c->out.out_fd.nfd) {
char cmsgbuf[CMSG_SPACE(sizeof(int) * XCB_MAX_PASS_FD)];
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = *vector,
.msg_iovlen = n,
.msg_control = cmsgbuf,
.msg_controllen = CMSG_LEN(c->out.out_fd.nfd * sizeof (int)),
};
int i;
struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
hdr->cmsg_len = msg.msg_controllen;
hdr->cmsg_level = SOL_SOCKET;
hdr->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(hdr), c->out.out_fd.fd, c->out.out_fd.nfd * sizeof (int));
n = sendmsg(c->fd, &msg, 0);
if(n < 0 && errno == EAGAIN)
return 1;
for (i = 0; i < c->out.out_fd.nfd; i++)
close(c->out.out_fd.fd[i]);
c->out.out_fd.nfd = 0;
} else
#endif
{
n = writev(c->fd, *vector, n);
if(n < 0 && errno == EAGAIN)
return 1;
}
#endif /* _WIN32 */
if(n <= 0)
......
This diff is collapsed.
......@@ -260,6 +260,24 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
return request;
}
void
xcb_send_fd(xcb_connection_t *c, int fd)
{
#if HAVE_SENDMSG
if (c->has_error)
return;
pthread_mutex_lock(&c->iolock);
while (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
_xcb_out_flush_to(c, c->out.request);
if (c->has_error)
break;
}
if (!c->has_error)
c->out.out_fd.fd[c->out.out_fd.nfd++] = fd;
pthread_mutex_unlock(&c->iolock);
#endif
}
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent)
{
int ret;
......
......@@ -54,11 +54,14 @@ typedef struct {
enum xcb_send_request_flags_t {
XCB_REQUEST_CHECKED = 1 << 0,
XCB_REQUEST_RAW = 1 << 1,
XCB_REQUEST_DISCARD_REPLY = 1 << 2
XCB_REQUEST_DISCARD_REPLY = 1 << 2,
XCB_REQUEST_REPLY_FDS = 1 << 3
};
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
void xcb_send_fd(xcb_connection_t *c, int fd);
/* xcb_take_socket allows external code to ask XCB for permission to
* take over the write side of the socket and send raw data with
* xcb_writev. xcb_take_socket provides the sequence number of the last
......@@ -88,6 +91,7 @@ int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t re
void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e);
int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error);
int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen);
/* xcb_util.c */
......
......@@ -79,6 +79,18 @@ void *_xcb_map_remove(_xcb_map *q, unsigned int key);
/* xcb_out.c */
typedef void (*xcb_return_socket_func_t)(void *closure);
#if HAVE_SENDMSG
#define XCB_MAX_PASS_FD 16
typedef struct _xcb_fd {
int fd[XCB_MAX_PASS_FD];
int nfd;
int ifd;
} _xcb_fd;
#endif
typedef struct _xcb_out {
pthread_cond_t cond;
int writing;
......@@ -100,6 +112,9 @@ typedef struct _xcb_out {
xcb_big_requests_enable_cookie_t cookie;
uint32_t value;
} maximum_request_length;
#if HAVE_SENDMSG
_xcb_fd out_fd;
#endif
} _xcb_out;
int _xcb_out_init(_xcb_out *out);
......@@ -132,6 +147,10 @@ typedef struct _xcb_in {
struct pending_reply *pending_replies;
struct pending_reply **pending_replies_tail;
#if HAVE_SENDMSG
_xcb_fd in_fd;
#endif
struct xcb_special_event *special_events;
} _xcb_in;
int _xcb_in_init(_xcb_in *in);
......
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: XCB DRI3
Description: XCB DRI3 Extension
Version: @PACKAGE_VERSION@
Requires: xcb
Libs: -L${libdir} -lxcb-dri3
Cflags: -I${includedir}
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: XCB Present
Description: XCB Present Extension
Version: @PACKAGE_VERSION@
Requires: xcb
Libs: -L${libdir} -lxcb-present
Cflags: -I${includedir}