libxres: Changes to 'upstream-unstable'
autogen.sh | 13 +-
configure.ac | 15 +-
include/X11/extensions/XRes.h | 79 +++++++++++++
src/XRes.c | 238 +++++++++++++++++++++++++++++++++++++++---
4 files changed, 322 insertions(+), 23 deletions(-)
New commits:
commit 47f8ced17f5ef0a1f1539fd8837cd8f47aa0eb6e
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat Apr 13 10:34:22 2013 -0700
Use _XEatDataWords to avoid overflow of rep.length shifting
rep.length is a CARD32, so rep.length << 2 could overflow in 32-bit builds
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/configure.ac b/configure.ac
index 5e3703b..b829cc1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,6 +50,12 @@ XORG_CHECK_MALLOC_ZERO
# Obtain compiler/linker options for depedencies
PKG_CHECK_MODULES(XRES, [x11 >= 1.6] xext xextproto [resourceproto >= 1.2.0])
+# Check for _XEatDataWords function that may be patched into older Xlib release
+SAVE_LIBS="$LIBS"
+LIBS="$XRES_LIBS"
+AC_CHECK_FUNCS([_XEatDataWords])
+LIBS="$SAVE_LIBS"
+
AC_CONFIG_FILES([Makefile
src/Makefile
man/Makefile
commit 84b9156c7833dfd91c65d33542420ff4fe226948
Author: Adam Jackson <ajax@redhat.com>
Date: Wed Oct 11 11:11:01 2017 -0400
libXRes 1.2.0
Signed-off-by: Adam Jackson <ajax@redhat.com>
diff --git a/configure.ac b/configure.ac
index b082de8..5e3703b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_PREREQ([2.60])
# digit in the version number to track changes which don't affect the
# protocol, so XRes version l.n.m corresponds to protocol version l.n
#
-AC_INIT([libXres], [1.1.99.0],
+AC_INIT([libXres], [1.2.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXres])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([config.h])
commit 1bc34457619c0d9b94ebd1cadac53366da20fbe3
Author: Mihail Konev <k.mvc@ya.ru>
Date: Thu Jan 26 13:52:49 2017 +1000
autogen: add default patch prefix
Signed-off-by: Mihail Konev <k.mvc@ya.ru>
diff --git a/autogen.sh b/autogen.sh
index 0006de8..86e51a2 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -9,6 +9,9 @@ cd "$srcdir"
autoreconf -v --install || exit 1
cd "$ORIGDIR" || exit $?
+git config --local --get format.subjectPrefix >/dev/null 2>&1 ||
+ git config --local format.subjectPrefix "PATCH libXRes"
+
if test -z "$NOCONFIGURE"; then
exec "$srcdir"/configure "$@"
fi
commit e5fbb99729d460eda477bf6e299728bc47542ccb
Author: Emil Velikov <emil.l.velikov@gmail.com>
Date: Mon Mar 9 12:00:52 2015 +0000
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>
diff --git a/autogen.sh b/autogen.sh
index fd9c59a..0006de8 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,14 +1,14 @@
#! /bin/sh
-srcdir=`dirname $0`
+srcdir=`dirname "$0"`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
-cd $srcdir
+cd "$srcdir"
autoreconf -v --install || exit 1
-cd $ORIGDIR || exit $?
+cd "$ORIGDIR" || exit $?
if test -z "$NOCONFIGURE"; then
- exec $srcdir/configure "$@"
+ exec "$srcdir"/configure "$@"
fi
commit 16b2d184302d259a8481693285976045386fcc01
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date: Tue Jan 24 10:32:07 2017 +1000
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>
diff --git a/autogen.sh b/autogen.sh
index fc34bd5..fd9c59a 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -10,5 +10,5 @@ autoreconf -v --install || exit 1
cd $ORIGDIR || exit $?
if test -z "$NOCONFIGURE"; then
- $srcdir/configure "$@"
+ exec $srcdir/configure "$@"
fi
commit ae0ddaa9c960aee1b7845da01270b00177f95f3d
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri Nov 22 23:22:36 2013 -0800
Remove fallback for _XEatDataWords, require libX11 1.6 for it
_XEatDataWords was orignally introduced with the May 2013 security
patches, and in order to ease the process of delivering those,
fallback versions of _XEatDataWords were included in the X extension
library patches so they could be applied to older versions that didn't
have libX11 1.6 yet. Now that we're past that hurdle, we can drop
the fallbacks and just require libX11 1.6 for building new versions
of the extension libraries.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/configure.ac b/configure.ac
index f68b689..b082de8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -48,13 +48,7 @@ XORG_DEFAULT_OPTIONS
XORG_CHECK_MALLOC_ZERO
# Obtain compiler/linker options for depedencies
-PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= 1.2.0])
-
-# Check for _XEatDataWords function that may be patched into older Xlib release
-SAVE_LIBS="$LIBS"
-LIBS="$XRES_LIBS"
-AC_CHECK_FUNCS([_XEatDataWords])
-LIBS="$SAVE_LIBS"
+PKG_CHECK_MODULES(XRES, [x11 >= 1.6] xext xextproto [resourceproto >= 1.2.0])
AC_CONFIG_FILES([Makefile
src/Makefile
diff --git a/src/XRes.c b/src/XRes.c
index 89fab82..2bee277 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -15,17 +15,6 @@
#include <assert.h>
#include <limits.h>
-#ifndef HAVE__XEATDATAWORDS
-static inline void _XEatDataWords(Display *dpy, unsigned long n)
-{
-# ifndef LONG64
- if (n >= (ULONG_MAX >> 2))
- _XIOError(dpy);
-# endif
- _XEatData (dpy, n << 2);
-}
-#endif
-
static XExtensionInfo _xres_ext_info_data;
static XExtensionInfo *xres_ext_info = &_xres_ext_info_data;
static const char *xres_extension_name = XRES_NAME;
commit 0f5cfdc3136dd8ef43800bda64f9d39e6b23b2e9
Author: Julien Cristau <jcristau@debian.org>
Date: Sun Jun 30 20:09:49 2013 +0200
Compute number of bytes correctly in XResQueryClientPixmapBytes
64-bit servers send the upper 32-bit in bytes_overflow. We were
multiplying by 2^32 - 1 instead of 2^32 when putting things back
together.
Debian bug#621702
Reported-by: Kevin Ryde <user42@zip.com.au>
Signed-off-by: Julien Cristau <jcristau@debian.org>
Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/src/XRes.c b/src/XRes.c
index 51e905f..89fab82 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -240,7 +240,7 @@ Status XResQueryClientPixmapBytes (
}
#ifdef LONG64
- *bytes = (rep.bytes_overflow * 4294967295) + rep.bytes;
+ *bytes = (rep.bytes_overflow * 4294967296UL) + rep.bytes;
#else
*bytes = rep.bytes_overflow ? 0xffffffff : rep.bytes;
#endif
commit f468184963e53feda848853c4aefd0197b2cc116
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri Apr 12 23:36:13 2013 -0700
integer overflow in XResQueryClientResources() [CVE-2013-1988 2/2]
The CARD32 rep.num_types needs to be bounds checked before multiplying
by sizeof(XResType) to avoid integer overflow leading to underallocation
and writing data from the network past the end of the allocated buffer.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/src/XRes.c b/src/XRes.c
index c989985..51e905f 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -187,7 +187,12 @@ Status XResQueryClientResources (
}
if(rep.num_types) {
- if((typs = Xmalloc(sizeof(XResType) * rep.num_types))) {
+ if (rep.num_types < (INT_MAX / sizeof(XResType)))
+ typs = Xmalloc(sizeof(XResType) * rep.num_types);
+ else
+ typs = NULL;
+
+ if (typs != NULL) {
xXResType scratch;
int i;
commit b053d215b80e721f9afdc5794e4f3f4f2aee0141
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri Apr 12 23:36:13 2013 -0700
integer overflow in XResQueryClients() [CVE-2013-1988 1/2]
The CARD32 rep.num_clients needs to be bounds checked before multiplying
by sizeof(XResClient) to avoid integer overflow leading to underallocation
and writing data from the network past the end of the allocated buffer.
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/src/XRes.c b/src/XRes.c
index 1ab1db8..c989985 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -130,7 +130,12 @@ Status XResQueryClients (
}
if(rep.num_clients) {
- if((clnts = Xmalloc(sizeof(XResClient) * rep.num_clients))) {
+ if (rep.num_clients < (INT_MAX / sizeof(XResClient)))
+ clnts = Xmalloc(sizeof(XResClient) * rep.num_clients);
+ else
+ clnts = NULL;
+
+ if (clnts != NULL) {
xXResClient scratch;
int i;
commit 69457711050ac3a53859ef11790a7ac815cd7d94
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Sat Apr 13 10:34:22 2013 -0700
Use _XEatDataWords to avoid overflow of rep.length shifting
rep.length is a CARD32, so rep.length << 2 could overflow in 32-bit builds
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/configure.ac b/configure.ac
index 90205cc..f68b689 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,6 +50,12 @@ XORG_CHECK_MALLOC_ZERO
# Obtain compiler/linker options for depedencies
PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= 1.2.0])
+# Check for _XEatDataWords function that may be patched into older Xlib release
+SAVE_LIBS="$LIBS"
+LIBS="$XRES_LIBS"
+AC_CHECK_FUNCS([_XEatDataWords])
+LIBS="$SAVE_LIBS"
+
AC_CONFIG_FILES([Makefile
src/Makefile
man/Makefile
diff --git a/src/XRes.c b/src/XRes.c
index 1744196..1ab1db8 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -13,6 +13,18 @@
#include <X11/extensions/XResproto.h>
#include <X11/extensions/XRes.h>
#include <assert.h>
+#include <limits.h>
+
+#ifndef HAVE__XEATDATAWORDS
+static inline void _XEatDataWords(Display *dpy, unsigned long n)
+{
+# ifndef LONG64
+ if (n >= (ULONG_MAX >> 2))
+ _XIOError(dpy);
+# endif
+ _XEatData (dpy, n << 2);
+}
+#endif
static XExtensionInfo _xres_ext_info_data;
static XExtensionInfo *xres_ext_info = &_xres_ext_info_data;
@@ -131,7 +143,7 @@ Status XResQueryClients (
*num_clients = rep.num_clients;
result = 1;
} else {
- _XEatData(dpy, rep.length << 2);
+ _XEatDataWords(dpy, rep.length);
}
}
@@ -183,7 +195,7 @@ Status XResQueryClientResources (
*num_types = rep.num_types;
result = 1;
} else {
- _XEatData(dpy, rep.length << 2);
+ _XEatDataWords(dpy, rep.length);
}
}
commit 83e7693515369d57dcd11c2bb1f03563f51bc500
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Fri Jan 18 23:06:20 2013 -0800
Replace deprecated Automake INCLUDES variable with AM_CPPFLAGS
Excerpt https://lists.gnu.org/archive/html/automake/2012-12/msg00038.html
- Support for the long-deprecated INCLUDES variable will be removed
altogether in Automake 1.14. The AM_CPPFLAGS variable should be
used instead.
This variable was deprecated in Automake releases prior to 1.10, which is
the current minimum level required to build X.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/src/Makefile.am b/src/Makefile.am
index fd508da..bf66d68 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,7 +10,7 @@ AM_CFLAGS = \
$(XRES_CFLAGS) \
$(MALLOC_ZERO_CFLAGS)
-INCLUDES = -I$(top_srcdir)/include
+AM_CPPFLAGS = -I$(top_srcdir)/include
libXRes_la_LDFLAGS = -version-number 1:0:0 -no-undefined
commit d9324b7d07294bb18e4902596a1b8ee387188364
Author: Colin Walters <walters@verbum.org>
Date: Wed Jan 4 17:37:06 2012 -0500
autogen.sh: Implement GNOME Build API
http://people.gnome.org/~walters/docs/build-api.txt
Signed-off-by: Adam Jackson <ajax@redhat.com>
diff --git a/autogen.sh b/autogen.sh
index 904cd67..fc34bd5 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -9,4 +9,6 @@ cd $srcdir
autoreconf -v --install || exit 1
cd $ORIGDIR || exit $?
-$srcdir/configure --enable-maintainer-mode "$@"
+if test -z "$NOCONFIGURE"; then
+ $srcdir/configure "$@"
+fi
commit 6d1f115422cde2bfca4b69caa395345f3ac454e7
Author: Adam Jackson <ajax@redhat.com>
Date: Tue Jan 15 14:28:48 2013 -0500
configure: Remove AM_MAINTAINER_MODE
Signed-off-by: Adam Jackson <ajax@redhat.com>
diff --git a/configure.ac b/configure.ac
index 0079857..90205cc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -36,7 +36,6 @@ AC_CONFIG_HEADERS([config.h])
# Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-bzip2])
-AM_MAINTAINER_MODE
# Initialize libtool
AC_PROG_LIBTOOL
commit f44f4e265ec3ab7ef87d6d7009ec079ba4c49336
Author: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Mon Apr 23 18:57:48 2012 -0700
Bump version to 1.1.99.0 to reflect addition of 1.2 API
As noted in configure.ac comment, we try to keep library version
based on the protocol version number, so since the protocol skipped
to 1.2, we'll do that with the library as well for simplicity's sake.
Sets resourceproto requirement to version 1.2.0 since there were no
intermediate/snapshot versions between 1.1.2 & 1.2.0.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/configure.ac b/configure.ac
index bc4e8a6..0079857 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ AC_PREREQ([2.60])
# digit in the version number to track changes which don't affect the
# protocol, so XRes version l.n.m corresponds to protocol version l.n
#
-AC_INIT([libXres], [1.0.6],
+AC_INIT([libXres], [1.1.99.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXres])
AC_CONFIG_SRCDIR([Makefile.am])
AC_CONFIG_HEADERS([config.h])
@@ -48,12 +48,8 @@ XORG_MACROS_VERSION(1.8)
XORG_DEFAULT_OPTIONS
XORG_CHECK_MALLOC_ZERO
-# Check xres configuration, strip extra digits from package version to
-# find the required protocol version
-RES_VERSION=[`echo $VERSION | sed 's/^\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/'`]
-
# Obtain compiler/linker options for depedencies
-PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= $RES_VERSION])
+PKG_CHECK_MODULES(XRES, x11 xext xextproto [resourceproto >= 1.2.0])
AC_CONFIG_FILES([Makefile
src/Makefile
commit 01fc6f81f0a2935741dd1114aa3fa267d8be9095
Author: Erkki Seppälä <erkki.seppala@vincit.fi>
Date: Wed Dec 15 13:48:09 2010 +0200
Implemented second part of XResource extension v1.2: XResQueryResourceBytes
Signed-off-by: Erkki Seppälä <erkki.seppala@vincit.fi>
Reviewed-by: Rami Ylimäki <rami.ylimaki@vincit.fi>
Reviewed-by: Tiago Vignatti <tiago.vignatti@nokia.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/include/X11/extensions/XRes.h b/include/X11/extensions/XRes.h
index b9759e3..1c81616 100644
--- a/include/X11/extensions/XRes.h
+++ b/include/X11/extensions/XRes.h
@@ -43,6 +43,24 @@ typedef struct {
void *value;
} XResClientIdValue;
+typedef struct {
+ XID resource;
+ Atom type;
+} XResResourceIdSpec;
+
+typedef struct {
+ XResResourceIdSpec spec;
+ long bytes;
+ long ref_count;
+ long use_count;
+} XResResourceSizeSpec;
+
+typedef struct {
+ XResResourceSizeSpec size;
+ long num_cross_references;
+ XResResourceSizeSpec *cross_references;
+} XResResourceSizeValue;
+
_XFUNCPROTOBEGIN
/* v1.0 */
@@ -98,6 +116,20 @@ void XResClientIdsDestroy (
XResClientIdValue *client_ids
);
+Status XResQueryResourceBytes (
+ Display *dpy,
+ XID client,
+ long num_specs,
+ XResResourceIdSpec *resource_specs, /* in */
+ long *num_sizes, /* out */
+ XResResourceSizeValue **sizes /* out */
+);
+
+void XResResourceSizeValuesDestroy (
+ long num_sizes,
+ XResResourceSizeValue *sizes
+);
+
_XFUNCPROTOEND
#endif /* _XRES_H */
diff --git a/src/XRes.c b/src/XRes.c
index 0781666..1744196 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -237,7 +237,7 @@ static Bool ReadClientValues(
int c;
for (c = 0; c < num_ids; ++c) {
XResClientIdValue* client = client_ids + c;
- CARD32 value;
+ long int value;
_XRead32 (dpy, &value, 4);
client->spec.client = value;
_XRead32 (dpy, &value, 4);
@@ -344,3 +344,111 @@ pid_t XResGetClientPid(
return (pid_t) -1;
}
}
+
+static Status ReadResourceSizeSpec(
+ Display *dpy,
+ XResResourceSizeSpec *size
+)
+{
+ long int value;
+ _XRead32(dpy, &value, 4);
+ size->spec.resource = value;
+ _XRead32(dpy, &value, 4);
+ size->spec.type = value;
+ _XRead32(dpy, &value, 4);
+ size->bytes = value;
+ _XRead32(dpy, &value, 4);
+ size->ref_count = value;
+ _XRead32(dpy, &value, 4);
+ size->use_count = value;
+ return 0;
+}
+
+static Status ReadResourceSizeValues(
+ Display *dpy,
+ long num_sizes,
+ XResResourceSizeValue *sizes)
+{
+ int c;
+ int d;
+ for (c = 0; c < num_sizes; ++c) {
+ long int num;
+ ReadResourceSizeSpec(dpy, &sizes[c].size);
+ _XRead32(dpy, &num, 4);
+ sizes[c].num_cross_references = num;
+ sizes[c].cross_references = num ? calloc(num, sizeof(*sizes[c].cross_references)) : NULL;
+ for (d = 0; d < num; ++d) {
+ ReadResourceSizeSpec(dpy, &sizes[c].cross_references[d]);
+ }
+ }
+ return Success;
+}
+
+Status XResQueryResourceBytes (
+ Display *dpy,
+ XID client,
+ long num_specs,
+ XResResourceIdSpec *resource_specs, /* in */
+ long *num_sizes, /* out */
+ XResResourceSizeValue **sizes /* out */
+)
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXResQueryResourceBytesReq *req;
+ xXResQueryResourceBytesReply rep;
+ int c;
+
+ *num_sizes = 0;
+
+ XResCheckExtension (dpy, info, 0);
+
+ LockDisplay (dpy);
+ GetReq (XResQueryResourceBytes, req);
+ req->reqType = info->codes->major_opcode;
+ req->XResReqType = X_XResQueryResourceBytes;
+ req->length += num_specs * 2; /* 2 longs per client id spec */
+ req->client = client;
+ req->numSpecs = num_specs;
+
+ for (c = 0; c < num_specs; ++c) {
+ Data32(dpy, &resource_specs[c].resource, 4);
+ Data32(dpy, &resource_specs[c].type, 4);
+ }
+
+ *num_sizes = 0;
+ *sizes = NULL;
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
+ goto error;
+ }
+
+ *sizes = calloc(rep.numSizes, sizeof(**sizes));
+ *num_sizes = rep.numSizes;
+
+ if (ReadResourceSizeValues(dpy, *num_sizes, *sizes) != Success) {
+ goto error;
+ }
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return Success;
+
+ error:
+ XResResourceSizeValuesDestroy(*num_sizes, *sizes);
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return !Success;
+}
+
+void XResResourceSizeValuesDestroy (
+ long num_sizes,
+ XResResourceSizeValue *sizes
+)
+{
+ int c;
+ for (c = 0; c < num_sizes; ++c) {
+ free(sizes[c].cross_references);
+ }
+ free(sizes);
+}
commit 0f38938a27df1f865dcdda35f4d2ef191092ba42
Author: Erkki Seppälä <erkki.seppala@vincit.fi>
Date: Mon Nov 29 12:43:51 2010 +0200
Implemented first part of XResource extension v1.2: XResQueryClientIds
Signed-off-by: Erkki Seppälä <erkki.seppala@vincit.fi>
Reviewed-by: Rami Ylimäki <rami.ylimaki@vincit.fi>
Reviewed-by: Tiago Vignatti <tiago.vignatti@nokia.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
diff --git a/include/X11/extensions/XRes.h b/include/X11/extensions/XRes.h
index ed4b2b8..b9759e3 100644
--- a/include/X11/extensions/XRes.h
+++ b/include/X11/extensions/XRes.h
@@ -7,6 +7,8 @@
#include <X11/Xfuncproto.h>
+/* v1.0 */
+
typedef struct {
XID resource_base;
XID resource_mask;
@@ -17,8 +19,33 @@ typedef struct {
unsigned int count;
} XResType;
+/* v1.2 */
+
+typedef enum {
+ XRES_CLIENT_ID_XID,
+ XRES_CLIENT_ID_PID,
+ XRES_CLIENT_ID_NR
+} XResClientIdType;
+
+typedef enum {
+ XRES_CLIENT_ID_XID_MASK = 1 << XRES_CLIENT_ID_XID,
+ XRES_CLIENT_ID_PID_MASK = 1 << XRES_CLIENT_ID_PID
+} XResClientIdMask;
+
+typedef struct {
+ XID client;
+ unsigned int mask;
+} XResClientIdSpec;
+
+typedef struct {
+ XResClientIdSpec spec;
+ long length;
+ void *value;
+} XResClientIdValue;
+
_XFUNCPROTOBEGIN
+/* v1.0 */
Bool XResQueryExtension (
Display *dpy,
@@ -51,6 +78,26 @@ Status XResQueryClientPixmapBytes (
unsigned long *bytes
);
+/* v1.2 */
+
+Status XResQueryClientIds (
+ Display *dpy,
+ long num_specs,
+ XResClientIdSpec *client_specs, /* in */
+ long *num_ids, /* out */
+ XResClientIdValue **client_ids /* out */
+);
+
+XResClientIdType XResGetClientIdType(XResClientIdValue* value);
+
+/* return -1 if no pid associated to the value */
+pid_t XResGetClientPid(XResClientIdValue* value);
+
+void XResClientIdsDestroy (
+ long num_ids,
+ XResClientIdValue *client_ids
+);
+
_XFUNCPROTOEND
#endif /* _XRES_H */
diff --git a/src/XRes.c b/src/XRes.c
index 6091c96..0781666 100644
--- a/src/XRes.c
+++ b/src/XRes.c
@@ -12,7 +12,7 @@
#include <X11/extensions/extutil.h>
#include <X11/extensions/XResproto.h>
#include <X11/extensions/XRes.h>
-
+#include <assert.h>
static XExtensionInfo _xres_ext_info_data;
static XExtensionInfo *xres_ext_info = &_xres_ext_info_data;
@@ -228,3 +228,119 @@ Status XResQueryClientPixmapBytes (
return 1;
}
+static Bool ReadClientValues(
+ Display *dpy,
+ long num_ids,
+ XResClientIdValue *client_ids /* out */
+)
+{
+ int c;
+ for (c = 0; c < num_ids; ++c) {
+ XResClientIdValue* client = client_ids + c;
+ CARD32 value;
+ _XRead32 (dpy, &value, 4);
+ client->spec.client = value;
+ _XRead32 (dpy, &value, 4);
+ client->spec.mask = value;
+ _XRead32 (dpy, &value, 4);
+ client->length = value;
+ client->value = malloc(client->length);
+ _XRead32 (dpy, client->value, client->length);
+ }
+ return True;
+}
+
+Status XResQueryClientIds (
+ Display *dpy,
+ long num_specs,
+ XResClientIdSpec *client_specs, /* in */
+ long *num_ids, /* out */
+ XResClientIdValue **client_ids /* out */
+)
+{
+ XExtDisplayInfo *info = find_display (dpy);
+ xXResQueryClientIdsReq *req;
+ xXResQueryClientIdsReply rep;
+ int c;
+
+ *num_ids = 0;
+
+ XResCheckExtension (dpy, info, 0);
+ LockDisplay (dpy);
+ GetReq (XResQueryClientIds, req);
+ req->reqType = info->codes->major_opcode;
+ req->XResReqType = X_XResQueryClientIds;
+ req->length += num_specs * 2; /* 2 longs per client id spec */
+ req->numSpecs = num_specs;
+
+ for (c = 0; c < num_specs; ++c) {
+ Data32(dpy, &client_specs[c].client, 4);
+ Data32(dpy, &client_specs[c].mask, 4);
+ }
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
+ goto error;
+ }
+
+ *client_ids = calloc(rep.numIds, sizeof(**client_ids));
+ *num_ids = rep.numIds;
+
+ if (!ReadClientValues(dpy, *num_ids, *client_ids)) {
+ goto error;
+ }
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return Success;
+
+ error:
+ XResClientIdsDestroy (*num_ids, *client_ids);
+ *client_ids = NULL;
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return !Success;
+}
+
+void XResClientIdsDestroy (
+ long num_ids,
+ XResClientIdValue *client_ids
+)
+{
+ int c;
+ for (c = 0; c < num_ids; ++c) {
+ free(client_ids[c].value);
+ }
+ free(client_ids);
+}
+
+XResClientIdType XResGetClientIdType(
+ XResClientIdValue* value
+)
+{
+ int bit;
+ XResClientIdType idType = 0;
+ Bool found = False;
+ for (bit = 0; bit < XRES_CLIENT_ID_NR; ++bit) {
+ if (value->spec.mask & (1 << bit)) {
+ assert(!found);
+ found = True;
+ idType = bit;
+ }
+ }
+
+ assert(found);
+
+ return idType;
+}
+
+pid_t XResGetClientPid(
+ XResClientIdValue* value
+)
+{
+ if (value->spec.mask & XRES_CLIENT_ID_PID_MASK && value->length >= 4) {
+ return (pid_t) * (CARD32*) value->value;
+ } else {
+ return (pid_t) -1;
+ }
+}
Reply to: