Compare commits

...

72 Commits

Author SHA1 Message Date
Frederik Hertzum 93e6da2e2e added wrap file 2025-08-12 22:52:42 +02:00
Samuel Thibault 6a7661f60a Get rid of PATH_MAX
There could be no upper limit on the length of a path according
to POSIX, therefore these macros may not be defined at all on
some systems (such as GNU Hurd). There is however a limit on
sizeof(struct sockaddr_un.sun_path), so use it.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxcb/-/merge_requests/65>
2025-07-08 23:05:34 +02:00
Alan Coopersmith daf2c53976 add pure & const function attributes suggested by gcc -Wsuggest-attribute
This only covers the ones in the pre-written code.  There are many more
suggested in the generated code, which will require changing the generator
and will thus be handled separately.

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxcb/-/merge_requests/64>
2024-12-15 10:17:22 -08:00
Alan Coopersmith 021e887de9 xcb.h: use __has_attribute to check for attribute((__packed__)) support
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxcb/-/merge_requests/64>
2024-12-15 10:17:22 -08:00
Alan Coopersmith 124690ba63 xcb.h: remove __solaris__ ifdef
Nothing was defining __solaris__ on Solaris in current build setup, and
it's not needed on Solaris 10 (released 2005) and later, which has
stdint.h.  (Solaris 2.6 - 9 had inttypes.h, but no stdint.h.)

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxcb/-/merge_requests/64>
2024-12-15 10:17:22 -08:00
Xi Ruoyao ebea71700f c_client.py: Always open output files in UTF-8
The UTF-8 quotes can appear in man pages etc as well, not only C code.
For example, in xcb_composite_redirect_subwindows.3:

    xcb_composite_redirect_subwindows - Redirect all current and future
    children of ‘window’

Note that window is quoted by a pair of UTF-8 single quotes.

Closes: #72
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libxcb/-/merge_requests/60>
2024-06-06 03:11:02 +08:00
Matt Turner 622152ee42 libxcb 1.17.0 2024-04-15 14:53:31 +00:00
Matt Turner 4574ab269b configure.ac: Require xcb-proto >= 1.17.0
Signed-off-by: Matt Turner <mattst88@gmail.com>
2024-04-15 14:53:31 +00:00
Uli Schlachter b78d304531 Always write C code in UTF-8
Some people apparently use non-utf8 locales and this caused errors when
xcb-proto started using some "fancy" quote marks. Fix this by always
using utf8 encoding.

Fixes: https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/72
Signed-off-by: Uli Schlachter <psychon@znc.in>
2024-04-15 14:40:41 +00:00
Erik Kurzinger 389f22d1cb Add xcb-dri3 dependency to xcb-present.pc.in
Present version 1.4 introduces a dependency on DRI3 for the DRI3Syncobj
protocol type.

Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
2024-03-20 07:06:12 -07:00
Alan Coopersmith 86a478032b xcb_popcount: Use __builtin_popcount if compiler supports it
If the compiler knows of a better implementation for counting the number
of bits set in a word for the target CPU, let it use that, instead of the
classic algorithm optimized for PDP-6.

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2024-03-08 22:11:43 +00:00
Alan Coopersmith c268499c30 tests: fix -Werror=discarded-qualifiers errors in check_public.c
check_public.c: In function ‘parse_display_pass’:
check_public.c:32:32: error: passing argument 1 of ‘putenv’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
   32 |                         putenv("DISPLAY=");
      |                                ^~~~~~~~~~
In file included from check_public.c:4:
/usr/include/stdlib.h:148:19: note: expected ‘char *’ but argument is of type ‘const char *’
  148 | extern int putenv(char *);
      |                   ^~~~~~
check_public.c:57:16: error: passing argument 1 of ‘putenv’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
   57 |         putenv("DISPLAY=");
      |                ^~~~~~~~~~
/usr/include/stdlib.h:148:19: note: expected ‘char *’ but argument is of type ‘const char *’
  148 | extern int putenv(char *);
      |                   ^~~~~~
check_public.c: In function ‘parse_display_fail’:
check_public.c:73:32: error: passing argument 1 of ‘putenv’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
   73 |                         putenv("DISPLAY=");
      |                                ^~~~~~~~~~
/usr/include/stdlib.h:148:19: note: expected ‘char *’ but argument is of type ‘const char *’
  148 | extern int putenv(char *);
      |                   ^~~~~~
check_public.c:99:16: error: passing argument 1 of ‘putenv’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
   99 |         putenv("DISPLAY=");
      |                ^~~~~~~~~~
/usr/include/stdlib.h:148:19: note: expected ‘char *’ but argument is of type ‘const char *’
  148 | extern int putenv(char *);
      |                   ^~~~~~
check_public.c: In function ‘public_suite’:
check_public.c:244:16: error: passing argument 1 of ‘putenv’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
  244 |         putenv("DISPLAY=");
      |                ^~~~~~~~~~
/usr/include/stdlib.h:148:19: note: expected ‘char *’ but argument is of type ‘const char *’
  148 | extern int putenv(char *);
      |                   ^~~~~~
cc1: all warnings being treated as errors

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2024-03-02 11:47:47 -08:00
Alan Coopersmith c671b9b30a
libxcb 1.16.1
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2024-03-02 11:13:37 -08:00
Fergus Dall 3c946010c8 Enable large file support
Signed-off-by: Fergus Dall <sidereal@google.com>
2023-11-07 17:42:42 +11:00
Peter Williams 02a7bbed39 Fix compilation on Windows
Merge request !30 broke compilation on Windows by introducing unbalanced
curly braces. This change restores the previous behavior on Windows:
only TCP is supported.
2023-08-28 18:01:39 +00:00
Alan Coopersmith 18c3f055e7 gitlab CI: use latest xcbproto from git to build against
Closes issue #70

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2023-08-20 11:36:40 -07:00
Thomas Klausner 453115f7ee configure.ac: drop `pthread-stubs` dependency on NetBSD 2023-08-20 17:38:39 +00:00
Alan Coopersmith f11691a098 gitlab CI: regenerate container used for builds
This updates the included xcb-proto to the newly required 1.16.
As explained in issue #70, this is a quick workaround, not the
long-term fix for this problem.

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2023-08-20 10:30:11 -07:00
Matt Turner cc4b93c9cd libxcb 1.16
Signed-off-by: Matt Turner <mattst88@gmail.com>
2023-08-16 16:18:09 -04:00
Matt Turner 1519334652 configure.ac: Require xcb-proto >= 1.16.0
Signed-off-by: Matt Turner <mattst88@gmail.com>
2023-08-16 16:18:09 -04:00
Ilya Pominov 038636786a c_client: Fix crash in xcb_randr_set_monitor
Take into account c_need_sizeof when evaluating
xcb_protocol_request_t.count

Incorrect xcb_protocol_request_t.count causes a segmentation fault when
calling functions:
- xcb_randr_set_monitor{_checked}
- xcb_input_change_feedback_control{_checked}
- xcb_input_change_device_control{_unchecked}

Steps to reproduce:
Call xcb_randr_set_monitor() with valid arguments

OBSERVED RESULT
Segmentation fault
```
Process terminating with default action of signal 11 (SIGSEGV)
  Access not within mapped region at address 0x780
    at 0x4852925: memmove (in /usr/libexec/valgrind/vgpreload_memcheck-
amd64-linux.so)
    by 0x486967C: memcpy (string_fortified.h:29)
    by 0x486967C: send_request (xcb_out.c:59)
    by 0x486967C: send_request (xcb_out.c:46)
    by 0x486967C: xcb_send_request_with_fds64 (xcb_out.c:338)
    by 0x48699FC: xcb_send_request (xcb_out.c:359)
    by 0x4891F11: xcb_randr_set_monitor_checked (randr.c:5350)
```

EXPECTED RESULT
Function returns cookie

Amend: 77b594f958

Signed-off-by: Ilya Pominov <ipominov@astralinux.ru>
2023-04-10 20:06:52 +03:00
Demi Marie Obenour 8935793f1f Add tests for unix socket parsing
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2023-03-25 15:27:50 -04:00
Demi Marie Obenour 095255531b DISPLAY starting with / or unix: is always a socket path
If DISPLAY starts with / or unix:, do not check for anything but a full
filesystem socket path.  In particular, abstract AF_UNIX sockets and TCP
sockets will not be used in this case.   Also be stricter about parsing
the screen part of /path.screen displays, and bail out after all stat()
errors other than ENOENT.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2023-03-25 13:15:08 -04:00
Demi Marie Obenour ccdef1a8a5 Allow full paths to sockets on non-macOS
When combined with xorg/lib/libxtrans!7, this allows CVE-2020-25697 to
be mitigated by placing the AF_UNIX socket in a secure directory on the
filesystem.

This enables HAVE_LAUNCHD unconditionally and deletes the configure
switch.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2023-03-25 13:15:08 -04:00
Matthieu Herrb 18e109d755 Fix xcb_connect() call with a custom xcb_auth_info_t
If the function implementing xcb_connect is called directly with a
custom xcb_auth_info_t then checking that the screen in $DISPLAY
is valid is skipped.

Reported by chohag AT jtan DOT com

Signed-off-by: Matthieu Herrb <matthieu@herrb.eu>
2023-02-28 14:21:07 +01:00
Jan Beich fd04ab24a5 configure.ac: drop `pthread-stubs` dependency on DragonFly and FreeBSD
All `pthread_*` symbols used by libxcb have stubs in libc. So, stop
linking against libpthread.
2023-02-11 18:15:23 +00:00
Alan Coopersmith 4d1a578dd5 Raise minimum required version of Python from 2.6 to 3.0
Trying to build with Python 2.7.14 fails with:
  File "./c_client.py", line 2270
    key = (*self.name[:-1], field.enum)
           ^
SyntaxError: invalid syntax

Fixes: 33f3dbe ("Fix handling of documented enum parameters")
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2023-02-09 14:58:12 -08:00
Alan Coopersmith e2a3e80eb8 configure.ac: Remove obsolete AC_HEADER_STDC
Nothing checks for the STDC_HEADERS flag this set, and all supported
systems have C89 compatible headers now.

Clears autoconf warnings of:
configure.ac:93: warning: The macro `AC_HEADER_STDC' is obsolete.
configure.ac:93: You should run autoupdate.
./lib/autoconf/headers.m4:704: AC_HEADER_STDC is expanded from...
configure.ac:93: the top level

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2023-02-06 15:55:23 -08:00
Daniel G 3333d5bde8 Fix indentation. 2023-01-09 16:21:35 +00:00
Daniel G 973b510e95 Fix windows build. 2023-01-07 19:35:47 +00:00
Jeremy Huddleston Sequoia cb8c70f5a6
xcb_conn: Add a check for NULL to silence a UBSan runtime error
xcb_conn.c:314:60: runtime error: applying zero offset to null pointer

Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
2022-11-26 22:48:00 -08:00
Demi Marie Obenour 33f3dbe369 Fix handling of documented enum parameters
Previously this would crash the code generator.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2022-10-16 15:44:42 -04:00
Demi Marie Obenour c9513aac2d Fix a compiler warning
The warning is harmless but annoying.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2022-10-16 01:55:30 -04:00
Alan Coopersmith 06e1ef43bb configure.ac: drop dependency `pthread-stubs` on Solaris
On Solaris 10 and later, the pthread functions are directly in libc,
and libpthread only has metadata to redirect calls from it to the
libc functions.

On Solaris 9 and older (no longer supported), libc contained its own
thread stubs that libpthread then overrode.

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2022-10-04 11:30:09 -07:00
PaperChalice d53ad60d77 configure.ac: drop dependency `pthread-stubs` on macOS
`libpthread.dylib` on macOS is an alias of `libSystem.B.dylib`,
every program should link against `libSystem.B.dylib`.
2022-09-28 22:55:38 +00:00
Uli Schlachter e2ee5aabe9 Improve tutorial example
This tutorial example only handles XCB_EXPOSURE and XCB_KEY_RELEASE
events and ignores everything else. Thus, there is no point in asking
for more kinds of events.

A while ago, I ported this tutorial to x11rb [1]. Recently, I received a
pull request [2] removing these unnecessary event masks. This commit is
thus only partially by me and the 'issue' was originally found by the
author of [2].

[1]: https://github.com/psychon/x11rb/blob/master/x11rb/examples/tutorial.rs
[2]: https://github.com/psychon/x11rb/pull/754

Signed-off-by: Uli Schlachter <psychon@znc.in>
2022-09-28 22:39:32 +00:00
Mihail Konev 9dcb081708 autogen: add default patch prefix
Signed-off-by: Mihail Konev <k.mvc@ya.ru>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2022-07-24 14:26:03 -07:00
Emil Velikov 7d798d3ccb autogen.sh: use quoted string variables
Place quotes around the $srcdir, $ORIGDIR and $0 variables to prevent
fall-outs, when they contain space.

Signed-off-by: Emil Velikov <emil.l.velikov@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2022-07-24 14:25:54 -07:00
Peter Hutterer 7071b4a13c autogen.sh: use exec instead of waiting for configure to finish
Syncs the invocation of configure with the one from the server.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2022-07-24 14:25:53 -07:00
Alan Coopersmith ee60239b73 gitlab CI: add a basic build test
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2022-07-18 17:55:43 -07:00
Mike Sharov 3123dfe723 Require xcb-proto >= 1.15.1, which has Dbe
Signed-off-by: Mike Sharov <msharov@users.sourceforge.net>
2022-06-22 10:56:37 -04:00
Mike Sharov 816407655f Build DOUBLE-BUFFER extension.
Signed-off-by: Mike Sharov <msharov@users.sourceforge.net>
2022-06-02 13:27:48 -04:00
Matt Turner c2c4a2cd19 libxcb 1.15
Signed-off-by: Matt Turner <mattst88@gmail.com>
2022-05-03 15:09:54 -07:00
Hodong ddafdba11f Fix a memory leak
Signed-off-by: Hodong <hodong@yozmos.com>
2022-01-15 02:32:04 +09:00
Demi Marie Obenour 43fbf03e54 Fix integer overflows in xcb_in.c
This fixes an integer overflow security vulnerability in xcb_in.c, which
may allow for memory corruption.
2021-11-17 12:09:02 -05:00
Thomas Anderson 233d7b7f1f Fix hang in xcb_request_check()
This fixes https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/53

The issue was that libxcb expected to get a reply based on the request_expected
variable, but a reply would never arrive because the request was never actually
written.  To resolve this, a separate request_expected_written variable is
added.
2021-09-30 23:32:35 +00:00
Ran Benita dc28118747 Avoid request counter truncation in replies map after 2**32 requests
The c->in request counters are uint64_t, and can realistically go over
2**32 over a lifetime of a client. The c->in->replies map however uses
unsigned int keys and the passed request numbers are silently truncated.

I haven't analyzed in depth what happens what it wraps around but it's
probably nothing good.

The only user of the xcb_list.c map code is c->in->replies, so just
change it to use uint64_t keys.

Reviewed-by: Uli Schlachter <psychon@znc.in>
Signed-off-by: Ran Benita <ran@unusedvar.com>
2021-09-30 17:22:06 +00:00
Julien Cristau 26396bf156 Add newline when printing auth/connection failure string to stderr
The reason strings returned by the server don't all include a newline,
so make sure we add one to avoid confusing clients.  Xlib used to do
this before it delegated that work to libxcb.

Fixes #34

Signed-off-by: Julien Cristau <jcristau@debian.org>
2021-09-30 17:18:18 +00:00
Uli Schlachter a503167f75 Improve/fix docs for reply fds functions
Fixes: https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/56
Signed-off-by: Uli Schlachter <psychon@znc.in>
2021-09-20 18:40:08 +00:00
Povilas Kanapickas 3c76c0579f c_client.py: Implement handling of <length> element
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2021-07-30 22:58:47 +03:00
Povilas Kanapickas bdc3f21a52 c_client: Extract _c_get_field_mapping_for_expr() 2021-07-30 22:58:46 +03:00
Povilas Kanapickas 068af21cb3 c_client.py: Use get_expr_field_names directly to resolve list fields
Using get_expr_fields() is only needed in case we are doing things that
can span multiple types easily, e.g. when deciding what data to pass via
function parameters and so on.

In _c_serialize_helper_list_field() we are building function body, so
acquiring field names via get_expr_field_names() is enough.

Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2021-07-30 22:58:45 +03:00
Povilas Kanapickas 4d678b162b c_client.py: Extract get_expr_field_names()
Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
2021-07-30 22:58:44 +03:00
Peter Harris 21414e7c44 Fix writev emulation on Windows
There are at least two bugs in the previous implementation:

- If an early iovec is partially written, there can be a gap of missing
  data (as a later iovec will be started before the early iovec is
  completed).
- If a late iovec returns WSAEWOULDBLOCK, *vector and *count are not
  updated, leading to a re-send of the entire request.

Move the *vector update into the send() loop to update piecemeal as
individual iovecs are sent.

Example program that demonstrates the issue (this program should run
forever after these bugs have been fixed):

#include <stdio.h>
#include <stdlib.h>
#include "xcb.h"

// Non-cryptographic random number generator from http://burtleburtle.net/bob/rand/smallprng.html
// because Microsoft's random number generators either have a too small RAND_MAX or are too slow
typedef struct ranctx { uint32_t a; uint32_t b; uint32_t c; uint32_t d; } ranctx;

static uint32_t ranval(ranctx *x);
static void raninit(ranctx *x, uint32_t seed);


#define MAX_PROP_LEN (128 * 1024)

int main(int argc, char *argv[]) {
    uint32_t seed = 0x12345678;
    if (argc > 1) {
        seed = strtoul(argv[1], NULL, 0);
    }
    ranctx ran;
    raninit(&ran, seed);

    xcb_connection_t *c = xcb_connect(NULL, NULL);
    if (!c || xcb_connection_has_error(c)) {
        printf("Cannot connect to $DISPLAY\n");
        return 1;
    }
    const xcb_setup_t *setup = xcb_get_setup(c);
    char *buf = malloc(MAX_PROP_LEN + 8); // plus a bit of slack so we can run random values off the end
    if (!buf) {
        printf("oom\n");
        return 1;
    }
    for (uint32_t i=0; i < (MAX_PROP_LEN + 3) / 4; i++) {
        ((uint32_t *)buf)[i] = ranval(&ran);
    }

    xcb_window_t win = xcb_generate_id(c);
    xcb_create_window(c, 0, win, xcb_setup_roots_iterator(setup).data[0].root, 0, 0, 1, 1, 0,
            XCB_WINDOW_CLASS_INPUT_ONLY, 0, 0, NULL);
    printf("Created window 0x%X\n", win);

    for (;;) {
        xcb_flush(c);
        xcb_generic_event_t *ev = xcb_poll_for_event(c);
        if (ev) {
            if (ev->response_type == 0) {
                xcb_generic_error_t *err = (xcb_generic_error_t *)ev;
                printf("Unexpected X Error %d\n", err->error_code);
                printf("   Sequence %d\n", err->sequence);
                printf("   Resource ID 0x%X\n", err->resource_id);
                printf("   Opcode: %d.%d\n", err->major_code, err->minor_code);
                return 1;
            }
            printf("Unexpected X Event %d\n", ev->response_type);
            return 1;
        }

        uint32_t siz = ranval(&ran) % MAX_PROP_LEN + 1;
        xcb_change_property(c, XCB_PROP_MODE_REPLACE, win, XCB_ATOM_STRING, XCB_ATOM_STRING, 8, siz, buf);
    }

    return 0;
}


#define rot(x,k) (((x)<<(k))|((x)>>(32-(k))))
static uint32_t ranval(ranctx *x) {
    uint32_t e = x->a - rot(x->b, 27);
    x->a = x->b ^ rot(x->c, 17);
    x->b = x->c + x->d;
    x->c = x->d + e;
    x->d = e + x->a;
    return x->d;
}

static void raninit(ranctx *x, uint32_t seed) {
    uint32_t i;
    x->a = 0xf1ea5eed, x->b = x->c = x->d = seed;
    for (i = 0; i<20; ++i) {
        (void)ranval(x);
    }
}

Signed-off-by: Peter Harris <pharris@opentext.com>
2021-06-04 14:31:13 +00:00
Peter Harris 4b0d9d3868 Fix build on Windows
Notable changes: Protect include of unistd.h (and other POSIX headers).
Use SOCKET (which is larger than int) and closesocket (because close is
not compatible) for sockets. Use <stdint.h>'s intptr_t instead of the
non-portable ssize_t.

Signed-off-by: Peter Harris <pharris@opentext.com>
2021-06-04 14:31:13 +00:00
Alan Coopersmith cd0fba98a2 xcb_auth: Quiet -Wimplicit-fallthrough warning in get_authptr()
xcb_auth.c:135:14: warning: this statement may fall through [-Wimplicit-fallthrough=]
         addr += 12;
         ~~~~~^~~~~
xcb_auth.c:138:5: note: here
     case AF_INET:
     ^~~~

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2021-06-01 18:40:59 -07:00
Julien Cristau 2ef8655987 Increment libtool version info for libxcb-dri3
Somewhat belatedly given the last update was in xcb-proto 1.13 in 2017...

Quoting @smcv from https://bugs.debian.org/921069:
>>>
libxcb-dri3 version 1.13 appears to have added new symbols without increasing
the minor ABI version in its -version-info. This will break anything that
compares libraries by their version info to decide which one is newer.

The Steam Runtime uses libraries' major/minor/micro ABI version info (in this
case 0.0.0) to decide whether to use the system copy of a library or the copy
in the Steam Runtime, depending on which one is newer (#921026). We can
work around this by adding a versioned dependency on libxcb-dri3-0 and
deleting the copy from the Steam Runtime, but this isn't a particularly
scalable solution.
>>>
2021-02-02 10:00:23 +01:00
Ran Benita 4cbcac4eca gitignore: add files generated by make check
Signed-off-by: Ran Benita <ran@unusedvar.com>
2020-11-18 23:06:32 -05:00
Ran Benita f01f3c378e tests: don't use deprecated fail_unless check API
It causes errors like this when running make check:

check_public.c:40:24: error: too many arguments for format [-Werror=format-extra-args]
   40 |   fail_unless(success, "unexpected parse failure %sfor '%s'", test_string[test_type], name);

Closes: https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/49
Tested-by: Matt Turner <mattst88@gmail.com>
Signed-off-by: Ran Benita <ran@unusedvar.com>
2020-11-18 23:06:05 -05:00
Eduardo Sánchez Muñoz 704e0a91b1 Use the 'present' field to properly check that the XC-MISC
extension is available in xcb_generate_id.

Also document the returned value when xcb_generate_id fails.
2020-03-02 19:01:41 +01:00
Matt Turner 4b40b44cb6 Release libxcb 1.14
Signed-off-by: Matt Turner <mattst88@gmail.com>
2020-02-22 12:20:08 -08:00
Matt Turner 78c492deaa Build xz tarballs instead of bzip2
Signed-off-by: Matt Turner <mattst88@gmail.com>
2020-02-22 12:20:08 -08:00
Matt Turner 8f7e4c4e9f configure.ac: Depend on pthread-stubs only on not-Linux
Signed-off-by: Matt Turner <mattst88@gmail.com>
2020-02-22 11:35:44 -08:00
Sam Varshavchik f9f4b00aad Implement xcb_total_read() and xcb_total_written().
Returns raw byte counts that have been read or written to the
xcb_connection_t.

I found it very useful when developing a high level widget toolkit, to
track down inefficient/sub-optimum code that generates a lot of X
protocol traffic.

Signed-off-by: Sam Varshavchik <mrsam@courier-mta.com>
2020-02-22 19:12:51 +00:00
A. Wilcox 59e271e15b tests: Support Check 0.13.0 API
[mattst88]: Keep compatibility 	with old API via preprocessor

Fixes: #43
2020-02-22 11:02:09 -08:00
Martin Dørum 21324989b7 Handle EINTR from recvmsg in _xcb_in_read
I have a GTK application which occasionally crashes with an "interrupted
system call" g_message from gdk. After a lot of debugging, I've found
that the call to recvmsg in _xcb_in_read occasionally fails with EINTR,
and instead of retrying the system call, xcb would just shut down the
connection.

This change makes _xcb_in_read treat EINTR the same as it would treat
EAGAIN; it returns 1 and libX11 ends up calling xcb_poll_for_event
again (from what I have understood).

I have spoken with a few people who think recvmsg failing with EINTR in
this case shouldn't ever happen, and I don't know enough to agree or
disagree with that. In case anyone wants to dig further and try to
figure out why the recvmsg call sometimes fails with EINTR, here's the
backtrace from inside of _xcb_in_read where that happened:

Thread 1 "beanbar" hit Breakpoint 1, _xcb_in_read (c=c@entry=0x55ecbe4aba80) at xcb_in.c:1059
1059                fprintf(stderr, "Hello World am %s:%i, errno is %s\n", __FILE__, __LINE__, strerror(errno));
(gdb) bt
0  0x00007fa48fa48639 in _xcb_in_read (c=c@entry=0x55ecbe4aba80) at xcb_in.c:1059
1  0x00007fa48fa489d8 in poll_for_next_event (c=0x55ecbe4aba80, queued=queued@entry=0) at xcb_in.c:352
2  0x00007fa48fa48a3d in poll_for_next_event (queued=0, c=<optimized out>) at xcb_in.c:722
3  0x00007fa48fa48a3d in xcb_poll_for_event (c=<optimized out>) at xcb_in.c:722
4  0x00007fa4908d1b7e in poll_for_event (dpy=dpy@entry=0x55ecbe4a9730, queued_only=queued_only@entry=0) at xcb_io.c:245
5  0x00007fa4908d1cf0 in poll_for_response (dpy=dpy@entry=0x55ecbe4a9730) at xcb_io.c:303
6  0x00007fa4908d1fed in _XEventsQueued (mode=2, dpy=0x55ecbe4a9730) at xcb_io.c:363
7  0x00007fa4908d1fed in _XEventsQueued (dpy=dpy@entry=0x55ecbe4a9730, mode=mode@entry=2) at xcb_io.c:344
8  0x00007fa4908c3d47 in XPending (dpy=0x55ecbe4a9730) at Pending.c:55
9  0x00007fa493cadbc7 in  () at /usr/lib/libgdk-3.so.0
10 0x00007fa49234d08a in g_main_context_prepare () at /usr/lib/libglib-2.0.so.0
11 0x00007fa49234d6e6 in  () at /usr/lib/libglib-2.0.so.0
12 0x00007fa49234d8ae in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
13 0x00007fa4938b920e in g_application_run () at /usr/lib/libgio-2.0.so.0
14 0x000055ecbc820af4 in main (argc=1, argv=0x7ffd06238098) at src/main.c:190

Signed-off-by: Martin Dørum <martid0311@gmail.com>
2019-05-19 16:05:08 +02:00
Jon Turney 656c08c542
Include time.h before using time()
Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
2019-04-25 17:30:16 +01:00
Alan Coopersmith be1745c8eb Add README.md to EXTRA_DIST
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2019-02-17 12:23:17 -08:00
Eduardo Sánchez Muñoz 58f37377c8 Add "ge.*" to src/.gitignore 2019-02-17 13:33:12 +01:00
Alan Coopersmith 7bac366953 Update README for gitlab migration
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2019-02-16 13:41:28 -08:00
Alan Coopersmith 02ff3eadf4 Update configure.ac bug URL for gitlab migration
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2019-02-16 13:35:06 -08:00
Alan Coopersmith 542befe40a c_client: fix "adress" typo
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2019-01-07 14:42:53 -08:00
27 changed files with 658 additions and 222 deletions

3
.gitignore vendored
View File

@ -23,3 +23,6 @@ mkinstalldirs
stamp-h1 stamp-h1
ChangeLog ChangeLog
INSTALL INSTALL
check-pc-requires.log
check-pc-requires.trs
test-suite.log

123
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,123 @@
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0 filetype=yaml:
#
# This CI uses the freedesktop.org ci-templates.
# Please see the ci-templates documentation for details:
# https://freedesktop.pages.freedesktop.org/ci-templates/
.templates_sha: &template_sha b791bd48996e3ced9ca13f1c5ee82be8540b8adb # see https://docs.gitlab.com/ee/ci/yaml/#includefile
include:
# Arch container builder template
- project: 'freedesktop/ci-templates'
ref: *template_sha
file: '/templates/arch.yml'
- project: 'freedesktop/ci-templates'
ref: *template_sha
file: '/templates/ci-fairy.yml'
- template: Security/SAST.gitlab-ci.yml
stages:
- prep # prep work like rebuilding the container images if there is a change
- install xcbproto
- build # for actually building and testing things in a container
- test
- deploy
variables:
FDO_UPSTREAM_REPO: 'xorg/lib/libxcb'
# The tag should be updated each time the list of packages is updated.
# Changing a tag forces the associated image to be rebuilt.
# Note: the tag has no meaning, we use a date format purely for readability
FDO_DISTRIBUTION_TAG: '2023-08-21.0'
FDO_DISTRIBUTION_PACKAGES: 'git gcc pkgconf autoconf automake libtool make xorg-util-macros python doxygen graphviz check libxslt libxau libxdmcp'
#
# Verify that commit messages are as expected
#
check-commits:
extends:
- .fdo.ci-fairy
stage: prep
script:
- ci-fairy check-commits --junit-xml=results.xml
except:
- master@xorg/lib/libxcb
variables:
GIT_DEPTH: 100
artifacts:
reports:
junit: results.xml
#
# Verify that the merge request has the allow-collaboration checkbox ticked
#
check-merge-request:
extends:
- .fdo.ci-fairy
stage: deploy
script:
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
artifacts:
when: on_failure
reports:
junit: results.xml
allow_failure: true
#
# Build a container with the given tag and the packages pre-installed.
# This only happens if/when the tag changes, otherwise the existing image is
# re-used.
#
container-prep:
extends:
- .fdo.container-build@arch
stage: prep
variables:
GIT_STRATEGY: none
#
# Build latest xcbproto from git, instead of relying on the container
# to package a new enough version.
#
xcbproto-build:
extends:
- .fdo.distribution-image@arch
stage: install xcbproto
script:
- export INSTDIR="$PWD/_inst"
- git clone --depth=1 https://gitlab.freedesktop.org/xorg/proto/xcbproto
- pushd xcbproto > /dev/null
- mkdir _builddir
- pushd _builddir > /dev/null
- ../autogen.sh --disable-silent-rules --prefix="$INSTDIR"
- make -j${FDO_CI_CONCURRENT:-4} install
- popd > /dev/null
- popd > /dev/null
variables:
artifacts:
paths:
- _inst
#
# The default build, runs on the image built above.
#
build:
stage: build
extends:
- .fdo.distribution-image@arch
script:
- export INSTDIR="$PWD/_inst"
- export PKG_CONFIG_PATH=$(find $INSTDIR/ -name '*.pc' -printf "%h:")
- autoreconf -ivf
- mkdir _builddir
- pushd _builddir > /dev/null
- ../configure --disable-silent-rules --enable-devel-docs --with-doxygen
- make
- make check
- make distcheck
- popd > /dev/null

View File

@ -12,6 +12,9 @@ endif
if BUILD_DAMAGE if BUILD_DAMAGE
pkgconfig_DATA += xcb-damage.pc pkgconfig_DATA += xcb-damage.pc
endif endif
if BUILD_DBE
pkgconfig_DATA += xcb-dbe.pc
endif
if BUILD_DPMS if BUILD_DPMS
pkgconfig_DATA += xcb-dpms.pc pkgconfig_DATA += xcb-dpms.pc
endif endif
@ -99,6 +102,7 @@ tools/README \
tools/api_conv.pl \ tools/api_conv.pl \
tools/constants \ tools/constants \
autogen.sh \ autogen.sh \
README.md \
$(TESTS) $(TESTS)
MAINTAINERCLEANFILES = ChangeLog INSTALL MAINTAINERCLEANFILES = ChangeLog INSTALL

7
NEWS
View File

@ -1,3 +1,10 @@
Release 1.14 (2020-02-22)
=========================
* Add xcb_total_read() and xcb_total_written() API
* Support check >= 0.13 API (for make check)
* Bug fix to handle EINTR from recvmsg
* Only require pthread-stubs on non-Linux platforms
Release 1.13.1 (2018-09-27) Release 1.13.1 (2018-09-27)
=========================== ===========================
* Don't flag extra reply in xcb_take_socket * Don't flag extra reply in xcb_take_socket

View File

@ -2,7 +2,7 @@ About libxcb
============ ============
libxcb provides an interface to the X Window System protocol, which libxcb provides an interface to the X Window System protocol, which
replaces the current Xlib interface. It has several advantages over replaces the traditional Xlib interface. It has several advantages over
Xlib, including: Xlib, including:
- size: small, simple library, and lower memory footprint - size: small, simple library, and lower memory footprint
- latency hiding: batch several requests and wait for the replies later - latency hiding: batch several requests and wait for the replies later
@ -10,27 +10,32 @@ Xlib, including:
- proven thread support: transparently access XCB from multiple threads - proven thread support: transparently access XCB from multiple threads
- easy extension implementation: interfaces auto-generated from XML-XCB - easy extension implementation: interfaces auto-generated from XML-XCB
Xlib can also use XCB as a transport layer, allowing software to make Xlib also uses XCB as a transport layer, allowing software to make
requests and receive responses with both, which eases porting to XCB. requests and receive responses with both, which eases porting to XCB.
However, client programs, libraries, and toolkits will gain the most However, client programs, libraries, and toolkits will gain the most
benefit from a native XCB port. benefit from a native XCB port.
More information about xcb is available from our website:
Please report any issues you find to the freedesktop.org bug tracker, https://xcb.freedesktop.org/
at:
<https://bugs.freedesktop.org/enter_bug.cgi?product=XCB> Please report any issues you find to the freedesktop.org bug tracker at:
https://gitlab.freedesktop.org/xorg/lib/libxcb/issues
Discussion about XCB occurs on the XCB mailing list: Discussion about XCB occurs on the XCB mailing list:
<mailto:xcb at lists.freedesktop.org> https://lists.freedesktop.org/mailman/listinfo/xcb
<http://lists.freedesktop.org/mailman/listinfo/xcb>
You can obtain the latest development versions of XCB using GIT. You can obtain the latest development versions of XCB using GIT from
For anonymous checkouts, use: the libxcb code repository at:
git clone git://anongit.freedesktop.org/git/xcb/libxcb https://gitlab.freedesktop.org/xorg/lib/libxcb
For developers, use: For anonymous checkouts, use:
git clone git+ssh://git.freedesktop.org/git/xcb/libxcb git clone https://gitlab.freedesktop.org/xorg/lib/libxcb.git
For developers, use:
git clone git@gitlab.freedesktop.org:xorg/lib/libxcb.git

View File

@ -1,14 +1,17 @@
#! /bin/sh #! /bin/sh
srcdir=`dirname $0` srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=. test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd` ORIGDIR=`pwd`
cd $srcdir cd "$srcdir"
autoreconf -v --install || exit 1 autoreconf -v --install || exit 1
cd $ORIGDIR || exit $? cd "$ORIGDIR" || exit $?
git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
git config --local format.subjectPrefix "PATCH libxcb"
if test -z "$NOCONFIGURE"; then if test -z "$NOCONFIGURE"; then
$srcdir/configure "$@" exec "$srcdir"/configure "$@"
fi fi

View File

@ -2,8 +2,8 @@ dnl Process this file with autoconf to produce a configure script.
# Initialize Autoconf # Initialize Autoconf
AC_PREREQ([2.60]) AC_PREREQ([2.60])
AC_INIT([libxcb],[1.13.1], AC_INIT([libxcb],[1.17.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xcb], [https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues],
[libxcb]) [libxcb])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
@ -11,13 +11,14 @@ AC_CONFIG_SRCDIR([xcb.pc.in])
AC_CONFIG_HEADERS([src/config.h]) AC_CONFIG_HEADERS([src/config.h])
# Initialize Automake # Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_INIT_AUTOMAKE([foreign dist-xz])
AM_PATH_PYTHON([2.6]) AM_PATH_PYTHON([3.0])
# Set common system defines for POSIX extensions, such as _GNU_SOURCE # 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) # Must be called before any macros that run the compiler (like AC_PROG_LIBTOOL)
# to avoid autoconf errors. # to avoid autoconf errors.
AC_USE_SYSTEM_EXTENSIONS AC_USE_SYSTEM_EXTENSIONS
AC_SYS_LARGEFILE
# Initialize libtool # Initialize libtool
LT_PREREQ([2.2]) LT_PREREQ([2.2])
@ -36,7 +37,7 @@ if test x"$HAVE_DOT" = xno; then
AC_MSG_WARN([dot not found - doxygen targets will be skipped]) AC_MSG_WARN([dot not found - doxygen targets will be skipped])
fi fi
PKG_CHECK_MODULES(CHECK, [check >= 0.9.4], [HAVE_CHECK=yes], [HAVE_CHECK=no]) PKG_CHECK_MODULES(CHECK, [check >= 0.9.6], [HAVE_CHECK=yes], [HAVE_CHECK=no])
AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes) AM_CONDITIONAL(HAVE_CHECK, test x$HAVE_CHECK = xyes)
XSLTPROC=no XSLTPROC=no
@ -50,8 +51,12 @@ fi
AC_SUBST(HTML_CHECK_RESULT) AC_SUBST(HTML_CHECK_RESULT)
# Checks for pkg-config packages # Checks for pkg-config packages
PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.13) PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.17.0)
NEEDED="pthread-stubs xau >= 0.99.2" NEEDED="xau >= 0.99.2"
case $host_os in
linux*|darwin*|solaris*|dragonfly*|freebsd*|netbsd*) ;;
*) NEEDED="$NEEDED pthread-stubs" ;;
esac
PKG_CHECK_MODULES(NEEDED, $NEEDED) PKG_CHECK_MODULES(NEEDED, $NEEDED)
have_xdmcp="no" have_xdmcp="no"
@ -86,7 +91,6 @@ XCBPROTO_XCBPYTHONDIR=`$PKG_CONFIG --variable=pythondir xcb-proto`
AC_MSG_RESULT($XCBPROTO_XCBPYTHONDIR) AC_MSG_RESULT($XCBPROTO_XCBPYTHONDIR)
AC_SUBST(XCBPROTO_XCBPYTHONDIR) AC_SUBST(XCBPROTO_XCBPYTHONDIR)
AC_HEADER_STDC
AC_SEARCH_LIBS(getaddrinfo, socket) AC_SEARCH_LIBS(getaddrinfo, socket)
AC_SEARCH_LIBS(connect, socket) AC_SEARCH_LIBS(connect, socket)
@ -217,6 +221,7 @@ esac
XCB_EXTENSION(Composite, yes) XCB_EXTENSION(Composite, yes)
XCB_EXTENSION(Damage, yes) XCB_EXTENSION(Damage, yes)
XCB_EXTENSION(Dbe, yes)
XCB_EXTENSION(DPMS, yes) XCB_EXTENSION(DPMS, yes)
XCB_EXTENSION(DRI2, yes) XCB_EXTENSION(DRI2, yes)
XCB_EXTENSION(DRI3, $have_sendmsg) XCB_EXTENSION(DRI3, $have_sendmsg)
@ -243,16 +248,6 @@ XCB_EXTENSION(XTest, yes)
XCB_EXTENSION(Xv, yes) XCB_EXTENSION(Xv, yes)
XCB_EXTENSION(XvMC, yes) XCB_EXTENSION(XvMC, yes)
AC_ARG_WITH(launchd, AS_HELP_STRING([--with-launchd], [Build with support for Apple's launchd (default: auto)]), [LAUNCHD=$withval], [LAUNCHD=auto])
if test "x$LAUNCHD" = xauto; then
unset LAUNCHD
AC_CHECK_PROG(LAUNCHD, [launchd], [yes], [no], [$PATH$PATH_SEPARATOR/sbin])
fi
if test "x$LAUNCHD" = xyes ; then
AC_DEFINE(HAVE_LAUNCHD, 1, [launchd support available])
fi
AC_ARG_WITH(serverside-support, AS_HELP_STRING([--with-serverside-support], [Build with support for server-side usage of xcb. This is still EXPERIMENTAL! ABI/API may change! (default: no)]), [XCB_SERVERSIDE_SUPPORT=$withval], [XCB_SERVERSIDE_SUPPORT=no]) AC_ARG_WITH(serverside-support, AS_HELP_STRING([--with-serverside-support], [Build with support for server-side usage of xcb. This is still EXPERIMENTAL! ABI/API may change! (default: no)]), [XCB_SERVERSIDE_SUPPORT=$withval], [XCB_SERVERSIDE_SUPPORT=no])
AM_CONDITIONAL(XCB_SERVERSIDE_SUPPORT, test "x$XCB_SERVERSIDE_SUPPORT" = "xyes") AM_CONDITIONAL(XCB_SERVERSIDE_SUPPORT, test "x$XCB_SERVERSIDE_SUPPORT" = "xyes")
@ -269,6 +264,7 @@ AC_CONFIG_FILES([
xcb.pc xcb.pc
xcb-composite.pc xcb-composite.pc
xcb-damage.pc xcb-damage.pc
xcb-dbe.pc
xcb-dpms.pc xcb-dpms.pc
xcb-dri2.pc xcb-dri2.pc
xcb-dri3.pc xcb-dri3.pc
@ -317,6 +313,7 @@ echo ""
echo " X11 extensions" echo " X11 extensions"
echo " Composite...........: ${BUILD_COMPOSITE}" echo " Composite...........: ${BUILD_COMPOSITE}"
echo " Damage..............: ${BUILD_DAMAGE}" echo " Damage..............: ${BUILD_DAMAGE}"
echo " Dbe.................: ${BUILD_DBE}"
echo " Dpms................: ${BUILD_DPMS}" echo " Dpms................: ${BUILD_DPMS}"
echo " Dri2................: ${BUILD_DRI2}" echo " Dri2................: ${BUILD_DRI2}"
echo " Dri3................: ${BUILD_DRI3}" echo " Dri3................: ${BUILD_DRI3}"

View File

@ -2297,9 +2297,7 @@ int main ()
values[0] = screen->white_pixel; values[0] = screen->white_pixel;
values[1] = values[1] =
XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_EXPOSURE;
XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_POINTER_MOTION;
cookie_window = xcb_create_window_checked (c, cookie_window = xcb_create_window_checked (c,
screen->root_depth, screen->root_depth,
window, screen->root, window, screen->root,

4
libxcb.wrap Normal file
View File

@ -0,0 +1,4 @@
[wrap-git]
url = https://gitea.gigo-games.dk/frederik/libxcb.git
revision = HEAD
depth = 1

2
src/.gitignore vendored
View File

@ -1,9 +1,11 @@
bigreq.* bigreq.*
composite.* composite.*
damage.* damage.*
dbe.*
dpms.* dpms.*
dri2.* dri2.*
dri3.* dri3.*
ge.*
glx.* glx.*
present.* present.*
randr.* randr.*

View File

@ -40,6 +40,14 @@ libxcb_damage_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_damage_la_SOURCES = damage.c damage.h nodist_libxcb_damage_la_SOURCES = damage.c damage.h
endif endif
EXTSOURCES += dbe.c
if BUILD_DBE
lib_LTLIBRARIES += libxcb-dbe.la
libxcb_dbe_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@
libxcb_dbe_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_dbe_la_SOURCES = dbe.c dbe.h
endif
EXTSOURCES += dpms.c EXTSOURCES += dpms.c
if BUILD_DPMS if BUILD_DPMS
lib_LTLIBRARIES += libxcb-dpms.la lib_LTLIBRARIES += libxcb-dpms.la
@ -59,7 +67,7 @@ endif
EXTSOURCES += dri3.c EXTSOURCES += dri3.c
if BUILD_DRI3 if BUILD_DRI3
lib_LTLIBRARIES += libxcb-dri3.la lib_LTLIBRARIES += libxcb-dri3.la
libxcb_dri3_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@ libxcb_dri3_la_LDFLAGS = -version-info 1:0:1 -no-undefined @lt_enable_auto_import@
libxcb_dri3_la_LIBADD = $(XCB_LIBS) libxcb_dri3_la_LIBADD = $(XCB_LIBS)
nodist_libxcb_dri3_la_SOURCES = dri3.c dri3.h nodist_libxcb_dri3_la_SOURCES = dri3.c dri3.h
endif endif

View File

@ -331,7 +331,7 @@ def c_close(self):
_h(' */') _h(' */')
# Write header file # Write header file
hfile = open('%s.h' % _ns.header, 'w') hfile = open('%s.h' % _ns.header, 'w', encoding='UTF-8')
for list in _hlines: for list in _hlines:
for line in list: for line in list:
hfile.write(line) hfile.write(line)
@ -339,7 +339,7 @@ def c_close(self):
hfile.close() hfile.close()
# Write source file # Write source file
cfile = open('%s.c' % _ns.header, 'w') cfile = open('%s.c' % _ns.header, 'w', encoding='UTF-8')
for list in _clines: for list in _clines:
for line in list: for line in list:
cfile.write(line) cfile.write(line)
@ -649,39 +649,42 @@ def _c_helper_resolve_field_names (prefix):
return all_fields return all_fields
def get_expr_field_names(expr):
"""
returns a list of field names referenced in an expression
"""
if expr.op is None or expr.op == 'calculate_len':
if expr.lenfield_name is not None:
return [expr.lenfield_name]
# constant value expr
return []
if expr.op == '~':
return get_expr_field_names(expr.rhs)
if expr.op == 'popcount':
return get_expr_field_names(expr.rhs)
if expr.op == 'sumof':
# sumof expr references another list,
# we need that list's length field here
field = None
for f in expr.lenfield_parent.fields:
if f.field_name == expr.lenfield_name:
field = f
break
if field is None:
raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
# referenced list + its length field
return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
if expr.op == 'enumref':
return []
return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
def get_expr_fields(self): def get_expr_fields(self):
""" """
get the Fields referenced by switch or list expression get the Fields referenced by switch or list expression
""" """
def get_expr_field_names(expr):
if expr.op is None or expr.op == 'calculate_len':
if expr.lenfield_name is not None:
return [expr.lenfield_name]
else:
# constant value expr
return []
else:
if expr.op == '~':
return get_expr_field_names(expr.rhs)
elif expr.op == 'popcount':
return get_expr_field_names(expr.rhs)
elif expr.op == 'sumof':
# sumof expr references another list,
# we need that list's length field here
field = None
for f in expr.lenfield_parent.fields:
if f.field_name == expr.lenfield_name:
field = f
break
if field is None:
raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
# referenced list + its length field
return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
elif expr.op == 'enumref':
return []
else:
return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
# get_expr_field_names()
# resolve the field names with the parent structure(s) # resolve the field names with the parent structure(s)
unresolved_fields_names = get_expr_field_names(self.expr) unresolved_fields_names = get_expr_field_names(self.expr)
@ -963,18 +966,15 @@ def _c_get_additional_type_params(type):
param_fields, wire_fields, params = get_serialize_params('sizeof', type) param_fields, wire_fields, params = get_serialize_params('sizeof', type)
return params[1:] return params[1:]
def _c_serialize_helper_list_field(context, self, field,
code_lines, temp_vars, def _c_get_field_mapping_for_expr(self, expr, prefix):
space, prefix):
""" """
helper function to cope with lists of variable length helper function to get field mapping of a particular expression.
""" """
expr = field.type.expr
prefix_str = _c_helper_fieldaccess_expr(prefix)
param_fields, wire_fields, params = get_serialize_params('sizeof', self) param_fields, wire_fields, params = get_serialize_params('sizeof', self)
param_names = [p[2] for p in params] param_names = [p[2] for p in params]
expr_fields_names = [f.field_name for f in get_expr_fields(field.type)] expr_fields_names = get_expr_field_names(expr)
resolved = [x for x in expr_fields_names if x in param_names] resolved = [x for x in expr_fields_names if x in param_names]
unresolved = [x for x in expr_fields_names if x not in param_names] unresolved = [x for x in expr_fields_names if x not in param_names]
@ -993,6 +993,21 @@ def _c_serialize_helper_list_field(context, self, field,
unresolved = [x for x in unresolved if x not in field_mapping] unresolved = [x for x in unresolved if x not in field_mapping]
if len(unresolved)>0: if len(unresolved)>0:
raise Exception('could not resolve the length fields required for list %s' % field.c_field_name) raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
return field_mapping
def _c_serialize_helper_list_field(context, self, field,
code_lines, temp_vars,
space, prefix):
"""
helper function to cope with lists of variable length
"""
expr = field.type.expr
prefix_str = _c_helper_fieldaccess_expr(prefix)
field_mapping = _c_get_field_mapping_for_expr(self, field.type.expr, prefix)
if expr.op == 'calculate_len': if expr.op == 'calculate_len':
list_length = field.type.expr.lenfield_name list_length = field.type.expr.lenfield_name
else: else:
@ -1402,6 +1417,16 @@ def _c_serialize(context, self):
elif 'sizeof' == context: elif 'sizeof' == context:
param_names = [p[2] for p in params] param_names = [p[2] for p in params]
if self.length_expr is not None:
_c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
prefix = [('_aux', '->', self)]
field_mapping = _c_get_field_mapping_for_expr(self, self.length_expr, prefix)
_c(' return %s;', _c_accessor_get_expr(self.length_expr, field_mapping))
_c('}')
_c_pre.redirect_end()
return
if self.is_switch: if self.is_switch:
# switch: call _unpack() # switch: call _unpack()
_c(' %s _aux;', self.c_type) _c(' %s _aux;', self.c_type)
@ -1933,7 +1958,7 @@ def _c_accessors_list(self, field):
else: else:
# use the accessor to get the start of the list, then # use the accessor to get the start of the list, then
# compute the length of it by subtracting it from # compute the length of it by subtracting it from
# the adress of the first byte after the end of the # the address of the first byte after the end of the
# request # request
after_end_of_request = '(((char*)R) + R->length * 4)' after_end_of_request = '(((char*)R) + R->length * 4)'
start_of_list = '%s(R)' % (field.c_accessor_name) start_of_list = '%s(R)' % (field.c_accessor_name)
@ -2241,13 +2266,13 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask': elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
field.enum = 'CW' field.enum = 'CW'
if field.enum: if field.enum:
# XXX: why the 'xcb' prefix? assert 2 <= len(self.name) <= 3
key = ('xcb', field.enum) key = (*self.name[:-1], field.enum)
tname = _t(key) tname = _t(key)
if namecount[tname] > 1: if namecount[tname] > 1:
tname = _t(key + ('enum',)) tname = _t(key + ('enum',))
_h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname)) _h(' * @param %s A bitmask of #%s values.', field.c_field_name, tname)
if self.doc and field.field_name in self.doc.fields: if self.doc and field.field_name in self.doc.fields:
desc = self.doc.fields[field.field_name] desc = self.doc.fields[field.field_name]
@ -2255,7 +2280,8 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
desc = desc.replace('`%s`' % name, '\\a %s' % (name)) desc = desc.replace('`%s`' % name, '\\a %s' % (name))
desc = desc.split("\n") desc = desc.split("\n")
desc = [line if line != '' else '\\n' for line in desc] desc = [line if line != '' else '\\n' for line in desc]
_h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc))) _h(' * @param %s %s', field.c_field_name, "\n * ".join(desc))
# If there is no documentation yet, we simply don't generate an # If there is no documentation yet, we simply don't generate an
# @param tag. Doxygen will then warn about missing documentation. # @param tag. Doxygen will then warn about missing documentation.
@ -2314,7 +2340,7 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
for field in param_fields: for field in param_fields:
if not field.type.fixed_size() and field.wire: if not field.type.fixed_size() and field.wire:
count = count + 2 count = count + 2
if field.type.c_need_serialize: if field.type.c_need_serialize or field.type.c_need_sizeof:
# _serialize() keeps track of padding automatically # _serialize() keeps track of padding automatically
count -= 1 count -= 1
dimension = count + 2 dimension = count + 2
@ -2586,9 +2612,10 @@ def _c_reply_fds(self, name):
_h(' * @param c The connection') _h(' * @param c The connection')
_h(' * @param reply The reply') _h(' * @param reply The reply')
_h(' *') _h(' *')
_h(' * Returns the array of reply fds of the request asked by') _h(' * Returns a pointer to the array of reply fds of the reply.')
_h(' *') _h(' *')
_h(' * The returned value must be freed by the caller using free().') _h(' * The returned value points into the reply and must not be free().')
_h(' * The fds are not managed by xcb. You must close() them before freeing the reply.')
_h(' */') _h(' */')
_c('') _c('')
_hc('int *') _hc('int *')
@ -2633,14 +2660,14 @@ def _man_request(self, name, void, aux):
name = 'man/%s.%s' % (linkname, section) name = 'man/%s.%s' % (linkname, section)
if manpaths: if manpaths:
sys.stdout.write(name) sys.stdout.write(name)
f = open(name, 'w') f = open(name, 'w', encoding='UTF-8')
f.write('.so man%s/%s.%s' % (section, func_name, section)) f.write('.so man%s/%s.%s' % (section, func_name, section))
f.close() f.close()
if manpaths: if manpaths:
sys.stdout.write('man/%s.%s ' % (func_name, section)) sys.stdout.write('man/%s.%s ' % (func_name, section))
# Our CWD is src/, so this will end up in src/man/ # Our CWD is src/, so this will end up in src/man/
f = open('man/%s.%s' % (func_name, section), 'w') f = open('man/%s.%s' % (func_name, section), 'w', encoding='UTF-8')
f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer)) f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
# Left-adjust instead of adjusting to both sides # Left-adjust instead of adjusting to both sides
f.write('.ad l\n') f.write('.ad l\n')
@ -3008,7 +3035,7 @@ def _man_event(self, name):
if manpaths: if manpaths:
sys.stdout.write('man/%s.%s ' % (self.c_type, section)) sys.stdout.write('man/%s.%s ' % (self.c_type, section))
# Our CWD is src/, so this will end up in src/man/ # Our CWD is src/, so this will end up in src/man/
f = open('man/%s.%s' % (self.c_type, section), 'w') f = open('man/%s.%s' % (self.c_type, section), 'w', encoding='UTF-8')
f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer)) f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
# Left-adjust instead of adjusting to both sides # Left-adjust instead of adjusting to both sides
f.write('.ad l\n') f.write('.ad l\n')

View File

@ -29,11 +29,7 @@
#define __XCB_H__ #define __XCB_H__
#include <sys/types.h> #include <sys/types.h>
#if defined(__solaris__)
#include <inttypes.h>
#else
#include <stdint.h> #include <stdint.h>
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <sys/uio.h> #include <sys/uio.h>
@ -51,7 +47,35 @@ extern "C" {
* @file xcb.h * @file xcb.h
*/ */
#ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with older compilers. */
#endif
/*
* For the below checks, we currently assume that __GNUC__ indicates
* gcc 3.0 (released 2001) or later, as we require support for C99.
*/
/* Supported in gcc 2.5 and later */
#if defined(__GNUC__) || __has_attribute(__const__)
#define XCB_CONST_FUNCTION __attribute__((__const__))
#else
#define XCB_CONST_FUNCTION XCB_PURE_FUNCTION
#endif
/* Supported in gcc 2.7 and later */
#if defined(__GNUC__) || __has_attribute(__packed__)
#define XCB_PACKED __attribute__((__packed__)) #define XCB_PACKED __attribute__((__packed__))
#else
#define XCB_PACKED
#endif
/* Supported in gcc 2.96 and later */
#if defined(__GNUC__) || __has_attribute(__pure__)
#define XCB_PURE_FUNCTION __attribute__((__pure__))
#else
#define XCB_PURE_FUNCTION
#endif
/** /**
* @defgroup XCB_Core_API XCB Core API * @defgroup XCB_Core_API XCB Core API
@ -465,6 +489,7 @@ void xcb_prefetch_extension_data(xcb_connection_t *c, xcb_extension_t *ext);
* *
* The result must not be freed. * The result must not be freed.
*/ */
XCB_PURE_FUNCTION
const struct xcb_setup_t *xcb_get_setup(xcb_connection_t *c); const struct xcb_setup_t *xcb_get_setup(xcb_connection_t *c);
/** /**
@ -475,6 +500,7 @@ const struct xcb_setup_t *xcb_get_setup(xcb_connection_t *c);
* Accessor for the file descriptor that was passed to the * Accessor for the file descriptor that was passed to the
* xcb_connect_to_fd call that returned @p c. * xcb_connect_to_fd call that returned @p c.
*/ */
XCB_PURE_FUNCTION
int xcb_get_file_descriptor(xcb_connection_t *c); int xcb_get_file_descriptor(xcb_connection_t *c);
/** /**
@ -495,6 +521,7 @@ int xcb_get_file_descriptor(xcb_connection_t *c);
* @return XCB_CONN_CLOSED_PARSE_ERR, error during parsing display string. * @return XCB_CONN_CLOSED_PARSE_ERR, error during parsing display string.
* @return XCB_CONN_CLOSED_INVALID_SCREEN, because the server does not have a screen matching the display. * @return XCB_CONN_CLOSED_INVALID_SCREEN, because the server does not have a screen matching the display.
*/ */
XCB_PURE_FUNCTION
int xcb_connection_has_error(xcb_connection_t *c); int xcb_connection_has_error(xcb_connection_t *c);
/** /**
@ -591,7 +618,7 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *display, xcb
/** /**
* @brief Allocates an XID for a new object. * @brief Allocates an XID for a new object.
* @param c The connection. * @param c The connection.
* @return A newly allocated XID. * @return A newly allocated XID, or -1 on failure.
* *
* Allocates an XID for a new object. Typically used just prior to * Allocates an XID for a new object. Typically used just prior to
* various object creation functions, such as xcb_create_window. * various object creation functions, such as xcb_create_window.
@ -599,6 +626,35 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *display, xcb
uint32_t xcb_generate_id(xcb_connection_t *c); uint32_t xcb_generate_id(xcb_connection_t *c);
/**
* @brief Obtain number of bytes read from the connection.
* @param c The connection
* @return Number of bytes read from the server.
*
* Returns cumulative number of bytes received from the connection.
*
* This retrieves the total number of bytes read from this connection,
* to be used for diagnostic/monitoring/informative purposes.
*/
uint64_t
xcb_total_read(xcb_connection_t *c);
/**
*
* @brief Obtain number of bytes written to the connection.
* @param c The connection
* @return Number of bytes written to the server.
*
* Returns cumulative number of bytes sent to the connection.
*
* This retrieves the total number of bytes written to this connection,
* to be used for diagnostic/monitoring/informative purposes.
*/
uint64_t
xcb_total_written(xcb_connection_t *c);
/** /**
* @} * @}
*/ */

View File

@ -31,9 +31,8 @@
#include <assert.h> #include <assert.h>
#include <X11/Xauth.h> #include <X11/Xauth.h>
#include <sys/param.h>
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h>
#ifdef __INTERIX #ifdef __INTERIX
/* _don't_ ask. interix has INADDR_LOOPBACK in here. */ /* _don't_ ask. interix has INADDR_LOOPBACK in here. */
@ -48,6 +47,8 @@
#endif #endif
#include "xcb_windefs.h" #include "xcb_windefs.h"
#else #else
#include <sys/param.h>
#include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -72,7 +73,7 @@ enum auth_protos {
#define AUTH_PROTO_XDM_AUTHORIZATION "XDM-AUTHORIZATION-1" #define AUTH_PROTO_XDM_AUTHORIZATION "XDM-AUTHORIZATION-1"
#define AUTH_PROTO_MIT_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1" #define AUTH_PROTO_MIT_MAGIC_COOKIE "MIT-MAGIC-COOKIE-1"
static char *authnames[N_AUTH_PROTOS] = { static const char *authnames[N_AUTH_PROTOS] = {
#ifdef HASXDMAUTH #ifdef HASXDMAUTH
AUTH_PROTO_XDM_AUTHORIZATION, AUTH_PROTO_XDM_AUTHORIZATION,
#endif #endif
@ -133,6 +134,7 @@ static Xauth *get_authptr(struct sockaddr *sockname, int display)
} }
addr += 12; addr += 12;
/* if v4-mapped, fall through. */ /* if v4-mapped, fall through. */
XCB_ALLOW_FALLTHRU
#endif #endif
case AF_INET: case AF_INET:
if(!addr) if(!addr)
@ -163,7 +165,7 @@ static Xauth *get_authptr(struct sockaddr *sockname, int display)
return XauGetBestAuthByAddr (family, return XauGetBestAuthByAddr (family,
(unsigned short) addrlen, addr, (unsigned short) addrlen, addr,
(unsigned short) dispbuflen, dispbuf, (unsigned short) dispbuflen, dispbuf,
N_AUTH_PROTOS, authnames, authnameslen); N_AUTH_PROTOS, (char **)authnames, authnameslen);
} }
#ifdef HASXDMAUTH #ifdef HASXDMAUTH
@ -269,10 +271,17 @@ static int compute_auth(xcb_auth_info_t *info, Xauth *authptr, struct sockaddr *
to the value returned by either getpeername() or getsockname() to the value returned by either getpeername() or getsockname()
(according to POSIX, applications should not assume a particular (according to POSIX, applications should not assume a particular
length for `sockaddr_un.sun_path') */ length for `sockaddr_un.sun_path') */
#ifdef _WIN32
static struct sockaddr *get_peer_sock_name(int(_stdcall *socket_func)(SOCKET,
struct sockaddr *,
socklen_t *),
int fd)
#else
static struct sockaddr *get_peer_sock_name(int (*socket_func)(int, static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
struct sockaddr *, struct sockaddr *,
socklen_t *), socklen_t *),
int fd) int fd)
#endif
{ {
socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK; socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
socklen_t actual_socknamelen = socknamelen; socklen_t actual_socknamelen = socknamelen;

View File

@ -32,7 +32,6 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@ -48,7 +47,9 @@
#ifdef _WIN32 #ifdef _WIN32
#include "xcb_windefs.h" #include "xcb_windefs.h"
#include <io.h>
#else #else
#include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#endif /* _WIN32 */ #endif /* _WIN32 */
@ -169,6 +170,8 @@ static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
static int read_setup(xcb_connection_t *c) static int read_setup(xcb_connection_t *c)
{ {
const char newline = '\n';
/* Read the server response */ /* Read the server response */
c->setup = malloc(sizeof(xcb_setup_generic_t)); c->setup = malloc(sizeof(xcb_setup_generic_t));
if(!c->setup) if(!c->setup)
@ -194,6 +197,7 @@ static int read_setup(xcb_connection_t *c)
{ {
xcb_setup_failed_t *setup = (xcb_setup_failed_t *) c->setup; xcb_setup_failed_t *setup = (xcb_setup_failed_t *) c->setup;
write(STDERR_FILENO, xcb_setup_failed_reason(setup), xcb_setup_failed_reason_length(setup)); write(STDERR_FILENO, xcb_setup_failed_reason(setup), xcb_setup_failed_reason_length(setup));
write(STDERR_FILENO, &newline, 1);
return 0; return 0;
} }
@ -201,6 +205,7 @@ static int read_setup(xcb_connection_t *c)
{ {
xcb_setup_authenticate_t *setup = (xcb_setup_authenticate_t *) c->setup; xcb_setup_authenticate_t *setup = (xcb_setup_authenticate_t *) c->setup;
write(STDERR_FILENO, xcb_setup_authenticate_reason(setup), xcb_setup_authenticate_reason_length(setup)); write(STDERR_FILENO, xcb_setup_authenticate_reason(setup), xcb_setup_authenticate_reason_length(setup));
write(STDERR_FILENO, &newline, 1);
return 0; return 0;
} }
} }
@ -211,33 +216,47 @@ static int read_setup(xcb_connection_t *c)
/* precondition: there must be something for us to write. */ /* precondition: there must be something for us to write. */
static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count) static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
{ {
#ifndef _WIN32
int n; int n;
#endif
assert(!c->out.queue_len); assert(!c->out.queue_len);
#ifdef _WIN32 #ifdef _WIN32
int i = 0;
int ret = 0,err = 0;
struct iovec *vec;
n = 0;
/* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from /* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from
an iovec would require more work and I'm not sure of the benefit....works for now */ an iovec would require more work and I'm not sure of the benefit....works for now */
vec = *vector; while (*count)
while(i < *count)
{ {
ret = send(c->fd,vec->iov_base,vec->iov_len,0); struct iovec *vec = *vector;
if(ret == SOCKET_ERROR) if (vec->iov_len)
{ {
err = WSAGetLastError(); int ret = send(c->fd, vec->iov_base, vec->iov_len, 0);
if(err == WSAEWOULDBLOCK) if (ret == SOCKET_ERROR)
{ {
return 1; int err = WSAGetLastError();
} if (err == WSAEWOULDBLOCK)
} {
n += ret; return 1;
*vec++; }
i++; }
if (ret <= 0)
{
_xcb_conn_shutdown(c, XCB_CONN_ERROR);
return 0;
}
c->out.total_written += ret;
vec->iov_len -= ret;
vec->iov_base = (char *)vec->iov_base + ret;
}
if (vec->iov_len == 0) {
(*vector)++;
(*count)--;
}
} }
if (!*count)
*vector = 0;
#else #else
n = *count; n = *count;
if (n > IOV_MAX) if (n > IOV_MAX)
@ -279,28 +298,32 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count)
return 1; return 1;
} }
#endif /* _WIN32 */
if(n <= 0) if(n <= 0)
{ {
_xcb_conn_shutdown(c, XCB_CONN_ERROR); _xcb_conn_shutdown(c, XCB_CONN_ERROR);
return 0; return 0;
} }
c->out.total_written += n;
for(; *count; --*count, ++*vector) for(; *count; --*count, ++*vector)
{ {
int cur = (*vector)->iov_len; int cur = (*vector)->iov_len;
if(cur > n) if(cur > n)
cur = n; cur = n;
(*vector)->iov_len -= cur; if(cur) {
(*vector)->iov_base = (char *) (*vector)->iov_base + cur; (*vector)->iov_len -= cur;
n -= cur; (*vector)->iov_base = (char *) (*vector)->iov_base + cur;
n -= cur;
}
if((*vector)->iov_len) if((*vector)->iov_len)
break; break;
} }
if(!*count) if(!*count)
*vector = 0; *vector = 0;
assert(n == 0); assert(n == 0);
#endif /* _WIN32 */
return 1; return 1;
} }
@ -344,7 +367,11 @@ xcb_connection_t *xcb_connect_to_fd(int fd, xcb_auth_info_t *auth_info)
c = calloc(1, sizeof(xcb_connection_t)); c = calloc(1, sizeof(xcb_connection_t));
if(!c) { if(!c) {
#ifdef _WIN32
closesocket(fd);
#else
close(fd); close(fd);
#endif
return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ; return _xcb_conn_ret_error(XCB_CONN_CLOSED_MEM_INSUFFICIENT) ;
} }
@ -377,7 +404,11 @@ void xcb_disconnect(xcb_connection_t *c)
/* disallow further sends and receives */ /* disallow further sends and receives */
shutdown(c->fd, SHUT_RDWR); shutdown(c->fd, SHUT_RDWR);
#ifdef _WIN32
closesocket(c->fd);
#else
close(c->fd); close(c->fd);
#endif
pthread_mutex_destroy(&c->iolock); pthread_mutex_destroy(&c->iolock);
_xcb_in_destroy(&c->in); _xcb_in_destroy(&c->in);
@ -528,3 +559,30 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
return ret; return ret;
} }
uint64_t xcb_total_read(xcb_connection_t *c)
{
uint64_t n;
if (xcb_connection_has_error(c))
return 0;
pthread_mutex_lock(&c->iolock);
n = c->in.total_read;
pthread_mutex_unlock(&c->iolock);
return n;
}
uint64_t xcb_total_written(xcb_connection_t *c)
{
uint64_t n;
if (xcb_connection_has_error(c))
return 0;
pthread_mutex_lock(&c->iolock);
n = c->out.total_written;
pthread_mutex_unlock(&c->iolock);
return n;
}

View File

@ -32,7 +32,6 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
@ -40,6 +39,7 @@
#include <poll.h> #include <poll.h>
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
@ -239,9 +239,15 @@ static int read_packet(xcb_connection_t *c)
if(pend && pend->workaround == WORKAROUND_GLX_GET_FB_CONFIGS_BUG) if(pend && pend->workaround == WORKAROUND_GLX_GET_FB_CONFIGS_BUG)
{ {
uint32_t *p = (uint32_t *) c->in.queue; uint32_t *p = (uint32_t *) c->in.queue;
genrep.length = p[2] * p[3] * 2; uint64_t new_length = ((uint64_t)p[2]) * ((uint64_t)p[3]);
if(new_length >= (UINT32_MAX / UINT32_C(16)))
{
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_MEM_INSUFFICIENT);
return 0;
}
genrep.length = (uint32_t)(new_length * UINT64_C(2));
} }
length += genrep.length * 4; length += genrep.length * UINT64_C(4);
/* XXX a bit of a hack -- we "know" that all FD replys place /* XXX a bit of a hack -- we "know" that all FD replys place
* the number of fds in the pad0 byte */ * the number of fds in the pad0 byte */
@ -251,7 +257,7 @@ static int read_packet(xcb_connection_t *c)
/* XGE events may have sizes > 32 */ /* XGE events may have sizes > 32 */
if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT) if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT)
eventlength = genrep.length * 4; eventlength = genrep.length * UINT64_C(4);
bufsize = length + eventlength + nfd * sizeof(int) + bufsize = length + eventlength + nfd * sizeof(int) +
(genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)); (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t));
@ -365,7 +371,7 @@ static void free_reply_list(struct reply_list *head)
} }
} }
static int read_block(const int fd, void *buf, const ssize_t len) static int read_block(const int fd, void *buf, const intptr_t len)
{ {
int done = 0; int done = 0;
while(done < len) while(done < len)
@ -736,11 +742,16 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co
return 0; return 0;
pthread_mutex_lock(&c->iolock); pthread_mutex_lock(&c->iolock);
request = widen(c, cookie.sequence); request = widen(c, cookie.sequence);
if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected) if (XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed))
&& XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed))
{ {
_xcb_out_send_sync(c); if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected))
_xcb_out_flush_to(c, c->out.request); {
_xcb_out_send_sync(c);
}
if (XCB_SEQUENCE_COMPARE(request, >=, c->out.request_expected_written))
{
_xcb_out_flush_to(c, c->out.request);
}
} }
reply = wait_for_reply(c, request, &ret); reply = wait_for_reply(c, request, &ret);
assert(!reply); assert(!reply);
@ -1025,6 +1036,7 @@ int _xcb_in_read(xcb_connection_t *c)
} }
} }
#endif #endif
c->in.total_read += n;
c->in.queue_len += n; c->in.queue_len += n;
} }
while(read_packet(c)) while(read_packet(c))
@ -1051,7 +1063,7 @@ int _xcb_in_read(xcb_connection_t *c)
} }
#endif #endif
#ifndef _WIN32 #ifndef _WIN32
if((n > 0) || (n < 0 && errno == EAGAIN)) if((n > 0) || (n < 0 && (errno == EAGAIN || errno == EINTR)))
#else #else
if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK)) if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK))
#endif /* !_WIN32 */ #endif /* !_WIN32 */

View File

@ -36,7 +36,7 @@
typedef struct node { typedef struct node {
struct node *next; struct node *next;
unsigned int key; uint64_t key;
void *data; void *data;
} node; } node;
@ -73,7 +73,7 @@ void _xcb_map_delete(_xcb_map *list, xcb_list_free_func_t do_free)
free(list); free(list);
} }
int _xcb_map_put(_xcb_map *list, unsigned int key, void *data) int _xcb_map_put(_xcb_map *list, uint64_t key, void *data)
{ {
node *cur = malloc(sizeof(node)); node *cur = malloc(sizeof(node));
if(!cur) if(!cur)
@ -86,7 +86,7 @@ int _xcb_map_put(_xcb_map *list, unsigned int key, void *data)
return 1; return 1;
} }
void *_xcb_map_remove(_xcb_map *list, unsigned int key) void *_xcb_map_remove(_xcb_map *list, uint64_t key)
{ {
node **cur; node **cur;
for(cur = &list->head; *cur; cur = &(*cur)->next) for(cur = &list->head; *cur; cur = &(*cur)->next)

View File

@ -31,7 +31,11 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h> #include <unistd.h>
#endif
#include <string.h> #include <string.h>
#include "xcb.h" #include "xcb.h"
@ -443,6 +447,7 @@ int _xcb_out_init(_xcb_out *out)
out->request = 0; out->request = 0;
out->request_written = 0; out->request_written = 0;
out->request_expected_written = 0;
if(pthread_mutex_init(&out->reqlenlock, 0)) if(pthread_mutex_init(&out->reqlenlock, 0))
return 0; return 0;
@ -453,8 +458,9 @@ int _xcb_out_init(_xcb_out *out)
void _xcb_out_destroy(_xcb_out *out) void _xcb_out_destroy(_xcb_out *out)
{ {
pthread_cond_destroy(&out->cond);
pthread_mutex_destroy(&out->reqlenlock); pthread_mutex_destroy(&out->reqlenlock);
pthread_cond_destroy(&out->cond);
pthread_cond_destroy(&out->socket_cond);
} }
int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count) int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
@ -463,6 +469,7 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count)
while(ret && count) while(ret && count)
ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count); ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count);
c->out.request_written = c->out.request; c->out.request_written = c->out.request;
c->out.request_expected_written = c->in.request_expected;
pthread_cond_broadcast(&c->out.cond); pthread_cond_broadcast(&c->out.cond);
_xcb_in_wake_up_next_reader(c); _xcb_in_wake_up_next_reader(c);
return ret; return ret;

View File

@ -36,12 +36,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#ifdef _WIN32 #ifdef _WIN32
#include "xcb_windefs.h" #include "xcb_windefs.h"
#else #else
#include <unistd.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
@ -60,16 +60,27 @@
# include <sys/stat.h> # include <sys/stat.h>
#endif #endif
#ifdef HAVE_LAUNCHD
#include <sys/stat.h> #include <sys/stat.h>
#ifndef __has_builtin
# define __has_builtin(x) 0
#endif #endif
int xcb_popcount(uint32_t mask) int xcb_popcount(uint32_t mask)
{ {
#if __has_builtin(__builtin_popcount)
return __builtin_popcount(mask);
#else
/*
* Count the number of bits set to 1 in a 32-bit word.
* Algorithm from MIT AI Lab Memo 239: "HAKMEM", ITEM 169.
* https://dspace.mit.edu/handle/1721.1/6086
*/
uint32_t y; uint32_t y;
y = (mask >> 1) & 033333333333; y = (mask >> 1) & 033333333333;
y = mask - y - ((y >> 1) & 033333333333); y = mask - y - ((y >> 1) & 033333333333);
return ((y + (y >> 3)) & 030707070707) % 077; return ((y + (y >> 3)) & 030707070707) % 077;
#endif
} }
int xcb_sumof(uint8_t *list, int len) int xcb_sumof(uint8_t *list, int len)
@ -82,7 +93,6 @@ int xcb_sumof(uint8_t *list, int len)
return s; return s;
} }
#ifdef HAVE_LAUNCHD
/* Return true and parse if name matches <path to socket>[.<screen>] /* Return true and parse if name matches <path to socket>[.<screen>]
* Upon success: * Upon success:
* host = <path to socket> * host = <path to socket>
@ -94,20 +104,33 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char
int *displayp, int *screenp) int *displayp, int *screenp)
{ {
struct stat sbuf; struct stat sbuf;
char path[PATH_MAX]; /* In addition to the AF_UNIX path, there may be a screen number.
int _screen = 0; * The trailing \0 is already accounted in the size of sun_path. */
char path[sizeof(((struct sockaddr_un*)0)->sun_path) + 1 + 10];
size_t len;
int _screen = 0, res;
strlcpy(path, name, sizeof(path)); len = strlen(name);
if (0 != stat(path, &sbuf)) { if (len >= sizeof(path))
char *dot = strrchr(path, '.'); return 0;
if (!dot) memcpy(path, name, len + 1);
res = stat(path, &sbuf);
if (0 != res) {
unsigned long lscreen;
char *dot, *endptr;
if (res != -1 || (errno != ENOENT && errno != ENOTDIR))
return 0;
dot = strrchr(path, '.');
if (!dot || dot[1] < '1' || dot[1] > '9')
return 0; return 0;
*dot = '\0'; *dot = '\0';
errno = 0;
lscreen = strtoul(dot + 1, &endptr, 10);
if (lscreen > INT_MAX || !endptr || *endptr || errno)
return 0;
if (0 != stat(path, &sbuf)) if (0 != stat(path, &sbuf))
return 0; return 0;
_screen = (int)lscreen;
_screen = atoi(dot + 1);
} }
if (host) { if (host) {
@ -133,7 +156,6 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char
return 1; return 1;
} }
#endif
static int _xcb_parse_display(const char *name, char **host, char **protocol, static int _xcb_parse_display(const char *name, char **host, char **protocol,
int *displayp, int *screenp) int *displayp, int *screenp)
@ -146,11 +168,12 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol,
if(!name) if(!name)
return 0; return 0;
#ifdef HAVE_LAUNCHD
/* First check for <path to socket>[.<screen>] */ /* First check for <path to socket>[.<screen>] */
if (_xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp)) if (name[0] == '/')
return 1; return _xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp);
#endif
if (strncmp(name, "unix:", 5) == 0)
return _xcb_parse_display_path_to_socket(name + 5, host, protocol, displayp, screenp);
slash = strrchr(name, '/'); slash = strrchr(name, '/');
@ -236,41 +259,46 @@ static int _xcb_open(const char *host, char *protocol, const int display)
char *file = NULL; char *file = NULL;
int actual_filelen; int actual_filelen;
/* If protocol or host is "unix", fall through to Unix socket code below */ #ifndef _WIN32
if ((!protocol || (strcmp("unix",protocol) != 0)) && if (protocol && strcmp("unix", protocol) == 0 && host && host[0] == '/') {
(*host != '\0') && (strcmp("unix",host) != 0)) /* Full path to socket provided, ignore everything else */
{ filelen = strlen(host) + 1;
/* display specifies TCP */ if (filelen > INT_MAX)
unsigned short port = X_TCP_PORT + display; return -1;
return _xcb_open_tcp(host, protocol, port); file = malloc(filelen);
} if (file == NULL)
return -1;
memcpy(file, host, filelen);
actual_filelen = (int)(filelen - 1);
} else {
#endif
/* If protocol or host is "unix", fall through to Unix socket code below */
if ((!protocol || (strcmp("unix",protocol) != 0)) &&
(*host != '\0') && (strcmp("unix",host) != 0))
{
/* display specifies TCP */
unsigned short port = X_TCP_PORT + display;
return _xcb_open_tcp(host, protocol, port);
}
#ifndef _WIN32 #ifndef _WIN32
#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED) #if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED)
/* Check special path for Unix sockets under Solaris Trusted Extensions */ /* Check special path for Unix sockets under Solaris Trusted Extensions */
if (is_system_labeled()) if (is_system_labeled())
{ {
struct stat sbuf; const char *tsol_base = "/var/tsol/doors/.X11-unix/X";
const char *tsol_base = "/var/tsol/doors/.X11-unix/X"; char tsol_socket[PATH_MAX];
char tsol_socket[PATH_MAX]; struct stat sbuf;
snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display); snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display);
if (stat(tsol_socket, &sbuf) == 0) if (stat(tsol_socket, &sbuf) == 0)
base = tsol_base; base = tsol_base;
} else if (errno != ENOENT)
return 0;
}
#endif #endif
#ifdef HAVE_LAUNCHD
struct stat sbuf;
if (0 == stat(host, &sbuf)) {
file = strdup(host);
if(file == NULL)
return -1;
filelen = actual_filelen = strlen(file);
} else
#endif
{
filelen = strlen(base) + 1 + sizeof(display) * 3 + 1; filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
file = malloc(filelen); file = malloc(filelen);
if(file == NULL) if(file == NULL)
@ -278,24 +306,23 @@ static int _xcb_open(const char *host, char *protocol, const int display)
/* display specifies Unix socket */ /* display specifies Unix socket */
actual_filelen = snprintf(file, filelen, "%s%d", base, display); actual_filelen = snprintf(file, filelen, "%s%d", base, display);
}
if(actual_filelen < 0) if(actual_filelen < 0)
{ {
free(file); free(file);
return -1; return -1;
} }
/* snprintf may truncate the file */ /* snprintf may truncate the file */
filelen = MIN(actual_filelen, filelen - 1); filelen = MIN(actual_filelen, filelen - 1);
#ifdef HAVE_ABSTRACT_SOCKETS #ifdef HAVE_ABSTRACT_SOCKETS
fd = _xcb_open_abstract(protocol, file, filelen); fd = _xcb_open_abstract(protocol, file, filelen);
if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED)) if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED))
{ {
free(file); free(file);
return fd; return fd;
} }
#endif #endif
}
fd = _xcb_open_unix(protocol, file); fd = _xcb_open_unix(protocol, file);
free(file); free(file);
@ -389,7 +416,11 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0) if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
break; break;
#ifdef _WIN32
closesocket(fd);
#else
close(fd); close(fd);
#endif
fd = -1; fd = -1;
} }
freeaddrinfo(results); freeaddrinfo(results);
@ -415,7 +446,11 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0) if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0)
break; break;
#ifdef _WIN32
closesocket(fd);
#else
close(fd); close(fd);
#endif
fd = -1; fd = -1;
++_c; ++_c;
} }
@ -524,10 +559,8 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
if(auth) { if(auth) {
c = xcb_connect_to_fd(fd, auth); c = xcb_connect_to_fd(fd, auth);
goto out;
} }
else if(_xcb_get_auth_info(fd, &ourauth, display))
if(_xcb_get_auth_info(fd, &ourauth, display))
{ {
c = xcb_connect_to_fd(fd, &ourauth); c = xcb_connect_to_fd(fd, &ourauth);
free(ourauth.name); free(ourauth.name);

View File

@ -55,7 +55,7 @@ uint32_t xcb_generate_id(xcb_connection_t *c)
/* check for extension */ /* check for extension */
const xcb_query_extension_reply_t *xc_misc_reply = const xcb_query_extension_reply_t *xc_misc_reply =
xcb_get_extension_data(c, &xcb_xc_misc_id); xcb_get_extension_data(c, &xcb_xc_misc_id);
if (!xc_misc_reply) { if (!xc_misc_reply || !xc_misc_reply->present) {
pthread_mutex_unlock(&c->xid.lock); pthread_mutex_unlock(&c->xid.lock);
return -1; return -1;
} }

View File

@ -297,6 +297,7 @@ int xcb_poll_for_reply64(xcb_connection_t *c, uint64_t request, void **reply, xc
* @param replylen The size of the reply. * @param replylen The size of the reply.
* @return Pointer to the location where received file descriptors are stored. * @return Pointer to the location where received file descriptors are stored.
*/ */
XCB_CONST_FUNCTION
int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen); int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen);
@ -306,6 +307,7 @@ int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen);
* @param mask The mask to check * @param mask The mask to check
* @return The number of set bits in the mask * @return The number of set bits in the mask
*/ */
XCB_CONST_FUNCTION
int xcb_popcount(uint32_t mask); int xcb_popcount(uint32_t mask);
/** /**
@ -313,6 +315,7 @@ int xcb_popcount(uint32_t mask);
* @param len The length of the array * @param len The length of the array
* @return The sum of all entries in the array. * @return The sum of all entries in the array.
*/ */
XCB_PURE_FUNCTION
int xcb_sumof(uint8_t *list, int len); int xcb_sumof(uint8_t *list, int len);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -38,6 +38,16 @@
#pragma GCC visibility push(hidden) #pragma GCC visibility push(hidden)
#endif #endif
#ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with older compilers. */
#endif
#if __has_attribute(fallthrough)
# define XCB_ALLOW_FALLTHRU __attribute__ ((fallthrough));
#else
# define XCB_ALLOW_FALLTHRU /* FALLTHRU */
#endif
enum workarounds { enum workarounds {
WORKAROUND_NONE, WORKAROUND_NONE,
WORKAROUND_GLX_GET_FB_CONFIGS_BUG, WORKAROUND_GLX_GET_FB_CONFIGS_BUG,
@ -73,8 +83,8 @@ typedef struct _xcb_map _xcb_map;
_xcb_map *_xcb_map_new(void); _xcb_map *_xcb_map_new(void);
void _xcb_map_delete(_xcb_map *q, xcb_list_free_func_t do_free); void _xcb_map_delete(_xcb_map *q, xcb_list_free_func_t do_free);
int _xcb_map_put(_xcb_map *q, unsigned int key, void *data); int _xcb_map_put(_xcb_map *q, uint64_t key, void *data);
void *_xcb_map_remove(_xcb_map *q, unsigned int key); void *_xcb_map_remove(_xcb_map *q, uint64_t key);
/* xcb_out.c */ /* xcb_out.c */
@ -103,6 +113,8 @@ typedef struct _xcb_out {
uint64_t request; uint64_t request;
uint64_t request_written; uint64_t request_written;
uint64_t request_expected_written;
uint64_t total_written;
pthread_mutex_t reqlenlock; pthread_mutex_t reqlenlock;
enum lazy_reply_tag maximum_request_length_tag; enum lazy_reply_tag maximum_request_length_tag;
@ -135,6 +147,7 @@ typedef struct _xcb_in {
uint64_t request_expected; uint64_t request_expected;
uint64_t request_read; uint64_t request_read;
uint64_t request_completed; uint64_t request_completed;
uint64_t total_read;
struct reply_list *current_reply; struct reply_list *current_reply;
struct reply_list **current_reply_tail; struct reply_list **current_reply_tail;
@ -212,6 +225,7 @@ struct xcb_connection_t {
void _xcb_conn_shutdown(xcb_connection_t *c, int err); void _xcb_conn_shutdown(xcb_connection_t *c, int err);
XCB_CONST_FUNCTION
xcb_connection_t *_xcb_conn_ret_error(int err); xcb_connection_t *_xcb_conn_ret_error(int err);
int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count); int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vector, int *count);

View File

@ -1,10 +1,19 @@
#include <stdlib.h> #include <stdlib.h>
#include "check_suites.h" #include "check_suites.h"
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13
void suite_add_test(Suite *s, TFun tf, const char *name) void suite_add_test(Suite *s, TFun tf, const char *name)
#else
void suite_add_test(Suite *s, const TTest *tt, const char *name)
#endif
{ {
TCase *tc = tcase_create(name); TCase *tc = tcase_create(name);
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13
tcase_add_test(tc, tf); tcase_add_test(tc, tf);
#else
tcase_add_test(tc, tt);
#endif
suite_add_tcase(s, tc); suite_add_tcase(s, tc);
} }

View File

@ -1,6 +1,10 @@
#include <check.h> #include <check.h>
#include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef __unix__
#include <unistd.h>
#endif
#include "check_suites.h" #include "check_suites.h"
#include "xcb.h" #include "xcb.h"
#include "xcbext.h" #include "xcbext.h"
@ -12,6 +16,10 @@ typedef enum test_type_t {
} test_type_t; } test_type_t;
static const char *const test_string[] = { "", "via $DISPLAY " }; static const char *const test_string[] = { "", "via $DISPLAY " };
/* putenv(3) takes a pointer to a writable string that it adds directly
to the environment, so it must be in persistent memory, not on the stack */
static char display_env[] = "DISPLAY=";
static void parse_display_pass(const char *name, const char *host, const int display, const int screen) static void parse_display_pass(const char *name, const char *host, const int display, const int screen)
{ {
int success; int success;
@ -25,7 +33,7 @@ static void parse_display_pass(const char *name, const char *host, const int dis
if(test_type == TEST_ARGUMENT) if(test_type == TEST_ARGUMENT)
{ {
argument = name; argument = name;
putenv("DISPLAY="); putenv(display_env);
} }
else if(test_type == TEST_ENVIRONMENT) else if(test_type == TEST_ENVIRONMENT)
{ {
@ -37,20 +45,20 @@ static void parse_display_pass(const char *name, const char *host, const int dis
got_display = got_screen = -42; got_display = got_screen = -42;
mark_point(); mark_point();
success = xcb_parse_display(argument, &got_host, &got_display, &got_screen); success = xcb_parse_display(argument, &got_host, &got_display, &got_screen);
fail_unless(success, "unexpected parse failure %sfor '%s'", test_string[test_type], name); ck_assert_msg(success, "unexpected parse failure %sfor '%s'", test_string[test_type], name);
fail_unless(strcmp(host, got_host) == 0, "parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host); ck_assert_msg(strcmp(host, got_host) == 0, "parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host);
fail_unless(display == got_display, "parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display); ck_assert_msg(display == got_display, "parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display);
fail_unless(screen == got_screen, "parse %sproduced unexpected screen '%d' for '%s': expected '%d'", test_string[test_type], got_screen, name, screen); ck_assert_msg(screen == got_screen, "parse %sproduced unexpected screen '%d' for '%s': expected '%d'", test_string[test_type], got_screen, name, screen);
got_host = (char *) -1; got_host = (char *) -1;
got_display = got_screen = -42; got_display = got_screen = -42;
mark_point(); mark_point();
success = xcb_parse_display(argument, &got_host, &got_display, 0); success = xcb_parse_display(argument, &got_host, &got_display, 0);
fail_unless(success, "unexpected screenless parse failure %sfor '%s'", test_string[test_type], name); ck_assert_msg(success, "unexpected screenless parse failure %sfor '%s'", test_string[test_type], name);
fail_unless(strcmp(host, got_host) == 0, "screenless parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host); ck_assert_msg(strcmp(host, got_host) == 0, "screenless parse %sproduced unexpected hostname '%s' for '%s': expected '%s'", test_string[test_type], got_host, name, host);
fail_unless(display == got_display, "screenless parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display); ck_assert_msg(display == got_display, "screenless parse %sproduced unexpected display '%d' for '%s': expected '%d'", test_string[test_type], got_display, name, display);
} }
putenv("DISPLAY="); putenv(display_env);
} }
static void parse_display_fail(const char *name) static void parse_display_fail(const char *name)
@ -66,7 +74,7 @@ static void parse_display_fail(const char *name)
if(test_type == TEST_ARGUMENT) if(test_type == TEST_ARGUMENT)
{ {
argument = name; argument = name;
putenv("DISPLAY="); putenv(display_env);
} }
else if(test_type == TEST_ENVIRONMENT) else if(test_type == TEST_ENVIRONMENT)
{ {
@ -79,24 +87,55 @@ static void parse_display_fail(const char *name)
got_display = got_screen = -42; got_display = got_screen = -42;
mark_point(); mark_point();
success = xcb_parse_display(argument, &got_host, &got_display, &got_screen); success = xcb_parse_display(argument, &got_host, &got_display, &got_screen);
fail_unless(!success, "unexpected parse success %sfor '%s'", test_string[test_type], name); ck_assert_msg(!success, "unexpected parse success %sfor '%s'", test_string[test_type], name);
fail_unless(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host); ck_assert_msg(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host);
fail_unless(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display); ck_assert_msg(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display);
fail_unless(got_screen == -42, "screen changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_screen); ck_assert_msg(got_screen == -42, "screen changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_screen);
got_host = (char *) -1; got_host = (char *) -1;
got_display = got_screen = -42; got_display = got_screen = -42;
mark_point(); mark_point();
success = xcb_parse_display(argument, &got_host, &got_display, 0); success = xcb_parse_display(argument, &got_host, &got_display, 0);
fail_unless(!success, "unexpected screenless parse success %sfor '%s'", test_string[test_type], name); ck_assert_msg(!success, "unexpected screenless parse success %sfor '%s'", test_string[test_type], name);
fail_unless(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host); ck_assert_msg(got_host == (char *) -1, "host changed on parse failure %sfor '%s': got %p", test_string[test_type], name, got_host);
fail_unless(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display); ck_assert_msg(got_display == -42, "display changed on parse failure %sfor '%s': got %d", test_string[test_type], name, got_display);
} }
putenv("DISPLAY="); putenv(display_env);
} }
START_TEST(parse_display_unix) START_TEST(parse_display_unix)
{ {
#ifdef __unix__
char buf[sizeof "/tmp/xcb-test.XXXXXXX"];
char buf2[sizeof(buf) + 7];
int r, v;
memcpy(buf, "/tmp/xcb-test.XXXXXXX", sizeof buf);
v = mkstemp(buf);
ck_assert_msg(v >= 0, "cannot create temporary file");
parse_display_pass(buf, buf, 0, 0);
r = snprintf(buf2, sizeof buf2, "unix:%s", buf);
if (r < 5 || r >= (int)sizeof buf2) {
ck_assert_msg(0, "snprintf() failed (return value %d)", r);
unlink(buf);
return;
}
parse_display_pass(buf2, buf, 0, 0);
r = snprintf(buf2, sizeof buf2, "unix:%s.1", buf);
if (r < 7 || r >= (int)sizeof buf2) {
ck_assert_msg(0, "snprintf() failed (return value %d)", r);
unlink(buf);
return;
}
parse_display_pass(buf2, buf, 0, 1);
r = snprintf(buf2, sizeof buf2, "%s.1", buf);
if (r < 2 || r >= (int)sizeof buf2) {
ck_assert_msg(0, "snprintf() failed (return value %d)", r);
unlink(buf);
return;
}
parse_display_pass(buf2, buf, 0, 1);
unlink(buf);
#endif
parse_display_pass(":0", "", 0, 0); parse_display_pass(":0", "", 0, 0);
parse_display_pass(":1", "", 1, 0); parse_display_pass(":1", "", 1, 0);
parse_display_pass(":0.1", "", 0, 1); parse_display_pass(":0.1", "", 0, 1);
@ -183,7 +222,7 @@ END_TEST
static void popcount_eq(uint32_t bits, int count) static void popcount_eq(uint32_t bits, int count)
{ {
fail_unless(xcb_popcount(bits) == count, "unexpected popcount(%08x) != %d", bits, count); ck_assert_msg(xcb_popcount(bits) == count, "unexpected popcount(%08x) != %d", bits, count);
} }
START_TEST(popcount) START_TEST(popcount)
@ -206,7 +245,7 @@ END_TEST
Suite *public_suite(void) Suite *public_suite(void)
{ {
Suite *s = suite_create("Public API"); Suite *s = suite_create("Public API");
putenv("DISPLAY="); putenv(display_env);
suite_add_test(s, parse_display_unix, "xcb_parse_display unix"); suite_add_test(s, parse_display_unix, "xcb_parse_display unix");
suite_add_test(s, parse_display_ip, "xcb_parse_display ip"); suite_add_test(s, parse_display_ip, "xcb_parse_display ip");
suite_add_test(s, parse_display_ipv4, "xcb_parse_display ipv4"); suite_add_test(s, parse_display_ipv4, "xcb_parse_display ipv4");

View File

@ -1,4 +1,8 @@
#include <check.h> #include <check.h>
#if CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13
void suite_add_test(Suite *s, TFun tf, const char *name); void suite_add_test(Suite *s, TFun tf, const char *name);
#else
void suite_add_test(Suite *s, const TTest *tt, const char *name);
#endif
Suite *public_suite(void); Suite *public_suite(void);

11
xcb-dbe.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: XCB Dbe
Description: XCB Double Buffer Extension
Version: @PACKAGE_VERSION@
Requires.private: xcb
Libs: -L${libdir} -lxcb-dbe
Cflags: -I${includedir}

View File

@ -6,6 +6,6 @@ includedir=@includedir@
Name: XCB Present Name: XCB Present
Description: XCB Present Extension Description: XCB Present Extension
Version: @PACKAGE_VERSION@ Version: @PACKAGE_VERSION@
Requires.private: xcb xcb-randr xcb-xfixes xcb-sync Requires.private: xcb xcb-randr xcb-xfixes xcb-sync xcb-dri3
Libs: -L${libdir} -lxcb-present Libs: -L${libdir} -lxcb-present
Cflags: -I${includedir} Cflags: -I${includedir}