/packages/x11/xserver/xorg-server/patches/xorg-server-1.11.2-10_cache_xkbcomp_output_for_fast_start_up.patch
http://github.com/OpenELEC/OpenELEC.tv · Patch · 343 lines · 325 code · 18 blank · 0 comment · 0 complexity · 177c08d6c0028e0097ab9606ec20524d MD5 · raw file
- Patch from Moblin to cache xkbcomp output for faster booting
- Signed-off-by: Bryce Harrington <bryce@canonical.com>
- ---
- Index: xorg-server/configure.ac
- ===================================================================
- --- xorg-server.orig/configure.ac 2011-01-31 15:12:21.000000000 +1100
- +++ xorg-server/configure.ac 2011-01-31 15:13:26.563659152 +1100
- @@ -537,9 +537,9 @@
- AC_ARG_WITH(xkb-path, AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]),
- [ XKBPATH="$withval" ],
- [ XKBPATH="${datadir}/X11/xkb" ])
- -AC_ARG_WITH(xkb-output, AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]),
- +AC_ARG_WITH(xkb-output, AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${localstatedir}/cache/xkb)]),
- [ XKBOUTPUT="$withval" ],
- - [ XKBOUTPUT="compiled" ])
- + [ XKBOUTPUT="${localstatedir}/cache/xkb" ])
- AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES],
- [Keyboard ruleset (default: base/evdev)]),
- [ XKB_DFLT_RULES="$withval" ],
- @@ -1165,7 +1165,7 @@
- dnl Make sure XKM_OUTPUT_DIR is an absolute path
- XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1`
- if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then
- - XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT"
- + AC_MSG_ERROR([xkb-output must be an absolute path.])
- fi
-
- dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed
- Index: xorg-server/xkb/README.compiled
- ===================================================================
- --- xorg-server.orig/xkb/README.compiled 2011-01-28 12:31:51.000000000 +1100
- +++ xorg-server/xkb/README.compiled 2011-01-31 15:13:26.563659152 +1100
- @@ -4,10 +4,10 @@
- or some other tool might destroy or replace the files in this directory,
- so it is not a safe place to store compiled keymaps for long periods of
- time. The default keymap for any server is usually stored in:
- - X<num>-default.xkm
- -where <num> is the display number of the server in question, which makes
- -it possible for several servers *on the same host* to share the same
- -directory.
- + server-<SHA1>.xkm
- +
- +where <SHA1> is the SHA1 hash of keymap source, so that compiled
- +keymap of different keymap sources are stored in different files.
-
- Unless the X server is modified, sharing this directory between servers on
- different hosts could cause problems.
- Index: xorg-server/xkb/ddxLoad.c
- ===================================================================
- --- xorg-server.orig/xkb/ddxLoad.c 2011-01-31 14:28:22.000000000 +1100
- +++ xorg-server/xkb/ddxLoad.c 2011-01-31 15:17:50.814046721 +1100
- @@ -30,6 +30,12 @@
-
- #include <xkb-config.h>
-
- +#ifdef HAVE_SHA1_IN_LIBGCRYPT /* Use libgcrypt for SHA1 */
- +# include <gcrypt.h>
- +#else /* Use OpenSSL's libcrypto */
- +#warning "xkbcomp caching support disabled"
- +#endif
- +
- #include <stdio.h>
- #include <ctype.h>
- #include <X11/X.h>
- @@ -43,20 +49,9 @@
- #define XKBSRV_NEED_FILE_FUNCS
- #include <xkbsrv.h>
- #include <X11/extensions/XI.h>
- +#include <errno.h>
- #include "xkb.h"
-
- - /*
- - * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
- - * relative to the top-level XKB configuration directory.
- - * Making the server write to a subdirectory of that directory
- - * requires some work in the general case (install procedure
- - * has to create links to /var or somesuch on many machines),
- - * so we just compile into /usr/tmp for now.
- - */
- -#ifndef XKM_OUTPUT_DIR
- -#define XKM_OUTPUT_DIR "compiled/"
- -#endif
- -
- #define PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\""
- #define ERROR_PREFIX "\"> \""
- #define POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\""
- @@ -170,6 +165,47 @@
- }
- }
-
- +#ifndef SHA_DIGEST_LENGTH
- +#define SHA_DIGEST_LENGTH 20
- +#endif
- +
- +static Bool
- +Sha1Asc(char sha1Asc[SHA_DIGEST_LENGTH*2+1], const char * input)
- +{
- + int i;
- + unsigned char sha1[SHA_DIGEST_LENGTH];
- +
- +#ifdef HAVE_SHA1_IN_LIBGCRYPT /* Use libgcrypt for SHA1 */
- + static int init;
- + gcry_md_hd_t h;
- + gcry_error_t err;
- +
- + if (!init) {
- + if (!gcry_check_version(NULL))
- + return BadAlloc;
- + gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
- + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
- + init = 1;
- + }
- +
- + err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
- + if (err)
- + return BadAlloc;
- + gcry_md_write(h, input, strlen(input));
- + memcpy(sha1, gcry_md_read(h, GCRY_MD_SHA1), 20);
- + gcry_md_close(h);
- +#endif
- +
- + /* convert sha1 to sha1_asc */
- + for(i=0; i<SHA_DIGEST_LENGTH; ++i) {
- + sprintf(sha1Asc+i*2, "%02X", sha1[i]);
- + }
- +
- + return Success;
- +}
- +
- +/* call xkbcomp and compile XKB keymap, return xkm file name in
- + nameRtrn */
- static Bool
- XkbDDXCompileKeymapByNames( XkbDescPtr xkb,
- XkbComponentNamesPtr names,
- @@ -179,7 +215,11 @@
- int nameRtrnLen)
- {
- FILE * out;
- - char *buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
- + char * buf = NULL, xkmfile[PATH_MAX], xkm_output_dir[PATH_MAX];
- + char * tmpXkmFile = NULL;
- + char * canonicalXkmFileName = NULL;
- + char sha1Asc[SHA_DIGEST_LENGTH*2+1], xkbKeyMapBuf[100*1024];
- + int ret, result;
-
- const char *emptystring = "";
- char *xkbbasedirflag = NULL;
- @@ -190,14 +230,67 @@
- /* WIN32 has no popen. The input must be stored in a file which is
- used as input for xkbcomp. xkbcomp does not read from stdin. */
- char tmpname[PATH_MAX];
- - const char *xkmfile = tmpname;
- + const char *xkbfile = tmpname;
- #else
- - const char *xkmfile = "-";
- + const char *xkbfile = "-";
- #endif
-
- - snprintf(keymap, sizeof(keymap), "server-%s", display);
- + /* Write keymap source (xkbfile) to memory buffer `xkbKeyMapBuf',
- + of which SHA1 is generated and used as result xkm file name */
- + memset(xkbKeyMapBuf, 0, sizeof(xkbKeyMapBuf));
- + out = fmemopen(xkbKeyMapBuf, sizeof(xkbKeyMapBuf), "w");
- + if (NULL == out) {
- + ErrorF("[xkb] Open xkbKeyMapBuf for writing failed\n");
- + return FALSE;
- + }
- + ret = XkbWriteXKBKeymapForNames(out, names, xkb, want, need);
- + if (fclose(out) !=0)
- + {
- + ErrorF("[xkb] XkbWriteXKBKeymapForNames error, perhaps xkbKeyMapBuf is too small\n");
- + return FALSE;
- + }
- +#ifdef DEBUG
- + if (xkbDebugFlags) {
- + ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
- + fputs(xkbKeyMapBuf, stderr);
- + }
- +#endif
- + if (!ret) {
- + ErrorF("[xkb] Generating XKB Keymap failed, giving up compiling keymap\n");
- + return FALSE;
- + }
- +
- + DebugF("[xkb] computing SHA1 of keymap\n");
- + if (Success == Sha1Asc(sha1Asc, xkbKeyMapBuf)) {
- + snprintf(xkmfile, sizeof(xkmfile), "server-%s", sha1Asc);
- + }
- + else {
- + ErrorF("[xkb] Computing SHA1 of keymap failed, "
- + "using display name instead as xkm file name\n");
- + snprintf(xkmfile, sizeof(xkmfile), "server-%s", display);
- + }
-
- OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
- + /* set nameRtrn, fail if it's too small */
- + if ((strlen(xkmfile)+1 > nameRtrnLen) && nameRtrn) {
- + ErrorF("[xkb] nameRtrn too small to hold xkmfile name\n");
- + return FALSE;
- + }
- + strncpy(nameRtrn, xkmfile, nameRtrnLen);
- +
- + /* if the xkm file already exists, reuse it */
- + canonicalXkmFileName = Xprintf("%s%s.xkm", xkm_output_dir, xkmfile);
- + if (access(canonicalXkmFileName, R_OK) == 0) {
- + /* yes, we can reuse the old xkm file */
- + LogMessage(X_INFO, "XKB: reuse xkmfile %s\n", canonicalXkmFileName);
- + result = TRUE;
- + goto _ret;
- + }
- + LogMessage(X_INFO, "XKB: generating xkmfile %s\n", canonicalXkmFileName);
- +
- + /* continue to call xkbcomp to compile the keymap. to avoid race
- + condition, we compile it to a tmpfile then rename it to
- + xkmfile */
-
- #ifdef WIN32
- strcpy(tmpname, Win32TempDir());
- @@ -222,15 +315,21 @@
- }
- }
-
- + if ( (tmpXkmFile = tempnam(xkm_output_dir, NULL)) == NULL ) {
- + ErrorF("[xkb] Can't generate temp xkm file name");
- + result = FALSE;
- + goto _ret;
- + }
- +
- if (asprintf(&buf,
- "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
- - "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
- + "-em1 %s -emp %s -eml %s \"%s\"",
- xkbbindir, xkbbindirsep,
- ((xkbDebugFlags < 2) ? 1 :
- ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)),
- - xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
- + xkbbasedirflag ? xkbbasedirflag : "", xkbfile,
- PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
- - xkm_output_dir, keymap) == -1)
- + tmpXkmFile) == -1)
- buf = NULL;
-
- free(xkbbasedirflag);
- @@ -240,6 +339,11 @@
- return FALSE;
- }
-
- + /* there's a potential race condition between calling tempnam()
- + and invoking xkbcomp to write the result file (potential temp
- + file name conflicts), but since xkbcomp is a standalone
- + program, we have to live with this */
- +
- #ifndef WIN32
- out= Popen(buf,"w");
- #else
- @@ -247,30 +351,42 @@
- #endif
-
- if (out!=NULL) {
- -#ifdef DEBUG
- - if (xkbDebugFlags) {
- - ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
- - XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
- - }
- -#endif
- - XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
- + /* write XKBKeyMapBuf to xkbcomp */
- + if (EOF==fputs(xkbKeyMapBuf, out))
- + {
- + ErrorF("[xkb] Sending keymap to xkbcomp failed\n");
- + result = FALSE;
- + goto _ret;
- + }
- #ifndef WIN32
- if (Pclose(out)==0)
- #else
- if (fclose(out)==0 && System(buf) >= 0)
- #endif
- {
- + /* xkbcomp success */
- if (xkbDebugFlags)
- - DebugF("[xkb] xkb executes: %s\n",buf);
- - if (nameRtrn) {
- - strncpy(nameRtrn,keymap,nameRtrnLen);
- - nameRtrn[nameRtrnLen-1]= '\0';
- - }
- - free(buf);
- - return TRUE;
- + DebugF("[xkb] xkb executes: %s\n",buf);
- +
- + /* if canonicalXkmFileName already exists now, we simply
- + overwrite it, this is OK */
- + ret = rename(tmpXkmFile, canonicalXkmFileName);
- + if (0 != ret) {
- + ErrorF("[xkb] Can't rename %s to %s, error: %s\n",
- + tmpXkmFile, canonicalXkmFileName,
- + strerror(errno));
- +
- + /* in case of error, don't unlink tmpXkmFile, leave i
- + for debugging */
- +
- + result = FALSE;
- + goto _ret;
- + }
- + result = TRUE;
- + goto _ret;
- }
- else
- - LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
- + LogMessage(X_ERROR, "Error compiling keymap (%s)\n", xkbfile);
- #ifdef WIN32
- /* remove the temporary file */
- unlink(tmpname);
- @@ -285,8 +401,17 @@
- }
- if (nameRtrn)
- nameRtrn[0]= '\0';
- - free(buf);
- - return FALSE;
- + result = FALSE;
- +
- +_ret:
- + if (tmpXkmFile)
- + free(tmpXkmFile);
- + if (canonicalXkmFileName)
- + free(canonicalXkmFileName);
- + if (buf)
- + free(buf);
- +
- + return result;
- }
-
- static FILE *
- @@ -370,7 +495,6 @@
- DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
- }
- fclose(file);
- - (void) unlink (fileName);
- return (need|want)&(~missing);
- }