diff options
Diffstat (limited to 'dist/libxcb/src/xcb_util.c')
-rw-r--r-- | dist/libxcb/src/xcb_util.c | 153 |
1 files changed, 90 insertions, 63 deletions
diff --git a/dist/libxcb/src/xcb_util.c b/dist/libxcb/src/xcb_util.c index 0296ce0dd..5124d144b 100644 --- a/dist/libxcb/src/xcb_util.c +++ b/dist/libxcb/src/xcb_util.c @@ -60,16 +60,27 @@ # include <sys/stat.h> #endif -#ifdef HAVE_LAUNCHD #include <sys/stat.h> + +#ifndef __has_builtin +# define __has_builtin(x) 0 #endif 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; y = (mask >> 1) & 033333333333; y = mask - y - ((y >> 1) & 033333333333); return ((y + (y >> 3)) & 030707070707) % 077; +#endif } int xcb_sumof(uint8_t *list, int len) @@ -82,7 +93,6 @@ int xcb_sumof(uint8_t *list, int len) return s; } -#ifdef HAVE_LAUNCHD /* Return true and parse if name matches <path to socket>[.<screen>] * Upon success: * host = <path to socket> @@ -95,19 +105,30 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char { struct stat sbuf; char path[PATH_MAX]; - int _screen = 0; + size_t len; + int _screen = 0, res; - strlcpy(path, name, sizeof(path)); - if (0 != stat(path, &sbuf)) { - char *dot = strrchr(path, '.'); - if (!dot) + len = strlen(name); + if (len >= sizeof(path)) + return 0; + 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; *dot = '\0'; - + errno = 0; + lscreen = strtoul(dot + 1, &endptr, 10); + if (lscreen > INT_MAX || !endptr || *endptr || errno) + return 0; if (0 != stat(path, &sbuf)) return 0; - - _screen = atoi(dot + 1); + _screen = (int)lscreen; } if (host) { @@ -133,7 +154,6 @@ static int _xcb_parse_display_path_to_socket(const char *name, char **host, char return 1; } -#endif static int _xcb_parse_display(const char *name, char **host, char **protocol, int *displayp, int *screenp) @@ -146,11 +166,12 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol, if(!name) return 0; -#ifdef HAVE_LAUNCHD /* First check for <path to socket>[.<screen>] */ - if (_xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp)) - return 1; -#endif + if (name[0] == '/') + return _xcb_parse_display_path_to_socket(name, host, protocol, displayp, screenp); + + if (strncmp(name, "unix:", 5) == 0) + return _xcb_parse_display_path_to_socket(name + 5, host, protocol, displayp, screenp); slash = strrchr(name, '/'); @@ -236,41 +257,46 @@ static int _xcb_open(const char *host, char *protocol, const int display) char *file = NULL; int actual_filelen; - /* 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 + if (protocol && strcmp("unix", protocol) == 0 && host && host[0] == '/') { + /* Full path to socket provided, ignore everything else */ + filelen = strlen(host) + 1; + if (filelen > INT_MAX) + return -1; + 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 #if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED) - /* Check special path for Unix sockets under Solaris Trusted Extensions */ - if (is_system_labeled()) - { - struct stat sbuf; - const char *tsol_base = "/var/tsol/doors/.X11-unix/X"; - char tsol_socket[PATH_MAX]; - - snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display); - - if (stat(tsol_socket, &sbuf) == 0) - base = tsol_base; - } + /* Check special path for Unix sockets under Solaris Trusted Extensions */ + if (is_system_labeled()) + { + const char *tsol_base = "/var/tsol/doors/.X11-unix/X"; + char tsol_socket[PATH_MAX]; + struct stat sbuf; + + snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display); + + if (stat(tsol_socket, &sbuf) == 0) + base = tsol_base; + else if (errno != ENOENT) + return 0; + } #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; file = malloc(filelen); if(file == NULL) @@ -278,24 +304,23 @@ static int _xcb_open(const char *host, char *protocol, const int display) /* display specifies Unix socket */ actual_filelen = snprintf(file, filelen, "%s%d", base, display); - } - if(actual_filelen < 0) - { - free(file); - return -1; - } - /* snprintf may truncate the file */ - filelen = MIN(actual_filelen, filelen - 1); + if(actual_filelen < 0) + { + free(file); + return -1; + } + /* snprintf may truncate the file */ + filelen = MIN(actual_filelen, filelen - 1); #ifdef HAVE_ABSTRACT_SOCKETS - fd = _xcb_open_abstract(protocol, file, filelen); - if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED)) - { - free(file); - return fd; - } - + fd = _xcb_open_abstract(protocol, file, filelen); + if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED)) + { + free(file); + return fd; + } #endif + } fd = _xcb_open_unix(protocol, file); free(file); @@ -389,7 +414,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); if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0) break; +#ifdef _WIN32 + closesocket(fd); +#else close(fd); +#endif fd = -1; } freeaddrinfo(results); @@ -528,10 +557,8 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname, if(auth) { c = xcb_connect_to_fd(fd, auth); - goto out; } - - if(_xcb_get_auth_info(fd, &ourauth, display)) + else if(_xcb_get_auth_info(fd, &ourauth, display)) { c = xcb_connect_to_fd(fd, &ourauth); free(ourauth.name); |