PageRenderTime 27ms CodeModel.GetById 10ms app.highlight 6ms RepoModel.GetById 2ms app.codeStats 0ms

/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
  1Patch from Moblin to cache xkbcomp output for faster booting
  2
  3Signed-off-by: Bryce Harrington <bryce@canonical.com>
  4---
  5
  6Index: xorg-server/configure.ac
  7===================================================================
  8--- xorg-server.orig/configure.ac	2011-01-31 15:12:21.000000000 +1100
  9+++ xorg-server/configure.ac	2011-01-31 15:13:26.563659152 +1100
 10@@ -537,9 +537,9 @@
 11 AC_ARG_WITH(xkb-path,         AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]),
 12 				[ XKBPATH="$withval" ],
 13 				[ XKBPATH="${datadir}/X11/xkb" ])
 14-AC_ARG_WITH(xkb-output,       AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]),
 15+AC_ARG_WITH(xkb-output,       AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${localstatedir}/cache/xkb)]),
 16 				[ XKBOUTPUT="$withval" ],
 17-				[ XKBOUTPUT="compiled" ])
 18+				[ XKBOUTPUT="${localstatedir}/cache/xkb" ])
 19 AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES],
 20                                    [Keyboard ruleset (default: base/evdev)]),
 21                                 [ XKB_DFLT_RULES="$withval" ],
 22@@ -1165,7 +1165,7 @@
 23 dnl Make sure XKM_OUTPUT_DIR is an absolute path
 24 XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1`
 25 if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then
 26-   XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT"
 27+   AC_MSG_ERROR([xkb-output must be an absolute path.])
 28 fi
 29 
 30 dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed
 31Index: xorg-server/xkb/README.compiled
 32===================================================================
 33--- xorg-server.orig/xkb/README.compiled	2011-01-28 12:31:51.000000000 +1100
 34+++ xorg-server/xkb/README.compiled	2011-01-31 15:13:26.563659152 +1100
 35@@ -4,10 +4,10 @@
 36 or some other tool might destroy or replace the files in this directory,
 37 so it is not a safe place to store compiled keymaps for long periods of
 38 time.  The default keymap for any server is usually stored in:
 39-     X<num>-default.xkm
 40-where <num> is the display number of the server in question, which makes
 41-it possible for several servers *on the same host* to share the same 
 42-directory.
 43+     server-<SHA1>.xkm
 44+
 45+where <SHA1> is the SHA1 hash of keymap source, so that compiled
 46+keymap of different keymap sources are stored in different files.
 47 
 48 Unless the X server is modified, sharing this directory between servers on
 49 different hosts could cause problems.
 50Index: xorg-server/xkb/ddxLoad.c
 51===================================================================
 52--- xorg-server.orig/xkb/ddxLoad.c	2011-01-31 14:28:22.000000000 +1100
 53+++ xorg-server/xkb/ddxLoad.c	2011-01-31 15:17:50.814046721 +1100
 54@@ -30,6 +30,12 @@
 55 
 56 #include <xkb-config.h>
 57 
 58+#ifdef HAVE_SHA1_IN_LIBGCRYPT /* Use libgcrypt for SHA1 */
 59+# include <gcrypt.h>
 60+#else /* Use OpenSSL's libcrypto */
 61+#warning "xkbcomp caching support disabled"
 62+#endif
 63+
 64 #include <stdio.h>
 65 #include <ctype.h>
 66 #include <X11/X.h>
 67@@ -43,20 +49,9 @@
 68 #define	XKBSRV_NEED_FILE_FUNCS
 69 #include <xkbsrv.h>
 70 #include <X11/extensions/XI.h>
 71+#include <errno.h>
 72 #include "xkb.h"
 73 
 74-	/*
 75-	 * If XKM_OUTPUT_DIR specifies a path without a leading slash, it is
 76-	 * relative to the top-level XKB configuration directory.
 77-	 * Making the server write to a subdirectory of that directory
 78-	 * requires some work in the general case (install procedure
 79-	 * has to create links to /var or somesuch on many machines),
 80-	 * so we just compile into /usr/tmp for now.
 81-	 */
 82-#ifndef XKM_OUTPUT_DIR
 83-#define	XKM_OUTPUT_DIR	"compiled/"
 84-#endif
 85-
 86 #define	PRE_ERROR_MSG "\"The XKEYBOARD keymap compiler (xkbcomp) reports:\""
 87 #define	ERROR_PREFIX	"\"> \""
 88 #define	POST_ERROR_MSG1 "\"Errors from xkbcomp are not fatal to the X server\""
 89@@ -170,6 +165,47 @@
 90     }
 91 }
 92 
 93+#ifndef SHA_DIGEST_LENGTH
 94+#define SHA_DIGEST_LENGTH 20
 95+#endif
 96+
 97+static Bool
 98+Sha1Asc(char sha1Asc[SHA_DIGEST_LENGTH*2+1], const char * input)
 99+{
100+    int i;
101+    unsigned char sha1[SHA_DIGEST_LENGTH];
102+
103+#ifdef HAVE_SHA1_IN_LIBGCRYPT /* Use libgcrypt for SHA1 */
104+    static int init;
105+    gcry_md_hd_t h;
106+    gcry_error_t err;
107+
108+    if (!init) {
109+	if (!gcry_check_version(NULL))
110+	    return BadAlloc;
111+	gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
112+	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
113+	init = 1;
114+    }
115+
116+    err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
117+    if (err)
118+	return BadAlloc;
119+    gcry_md_write(h, input, strlen(input));
120+    memcpy(sha1, gcry_md_read(h, GCRY_MD_SHA1), 20);
121+    gcry_md_close(h);
122+#endif
123+
124+    /* convert sha1 to sha1_asc */
125+    for(i=0; i<SHA_DIGEST_LENGTH; ++i) {
126+        sprintf(sha1Asc+i*2, "%02X", sha1[i]);
127+    }
128+
129+    return Success;
130+}
131+
132+/* call xkbcomp and compile XKB keymap, return xkm file name in
133+   nameRtrn */
134 static Bool
135 XkbDDXCompileKeymapByNames(	XkbDescPtr		xkb,
136 				XkbComponentNamesPtr	names,
137@@ -179,7 +215,11 @@
138 				int			nameRtrnLen)
139 {
140     FILE *	out;
141-    char	*buf = NULL, keymap[PATH_MAX], xkm_output_dir[PATH_MAX];
142+    char *	buf = NULL, xkmfile[PATH_MAX], xkm_output_dir[PATH_MAX];
143+    char *	tmpXkmFile = NULL;
144+    char *	canonicalXkmFileName = NULL;
145+    char	sha1Asc[SHA_DIGEST_LENGTH*2+1], xkbKeyMapBuf[100*1024];
146+    int	ret, result;
147 
148     const char	*emptystring = "";
149     char *xkbbasedirflag = NULL;
150@@ -190,14 +230,67 @@
151     /* WIN32 has no popen. The input must be stored in a file which is
152        used as input for xkbcomp. xkbcomp does not read from stdin. */
153     char tmpname[PATH_MAX];
154-    const char *xkmfile = tmpname;
155+    const char *xkbfile = tmpname;
156 #else
157-    const char *xkmfile = "-";
158+    const char *xkbfile = "-";
159 #endif
160 
161-    snprintf(keymap, sizeof(keymap), "server-%s", display);
162+    /* Write keymap source (xkbfile) to memory buffer `xkbKeyMapBuf',
163+       of which SHA1 is generated and used as result xkm file name  */
164+    memset(xkbKeyMapBuf, 0, sizeof(xkbKeyMapBuf));
165+    out = fmemopen(xkbKeyMapBuf, sizeof(xkbKeyMapBuf), "w");
166+    if (NULL == out) {
167+        ErrorF("[xkb] Open xkbKeyMapBuf for writing failed\n");
168+        return FALSE;
169+    }
170+    ret = XkbWriteXKBKeymapForNames(out, names, xkb, want, need);
171+    if (fclose(out) !=0)
172+    {
173+        ErrorF("[xkb] XkbWriteXKBKeymapForNames error, perhaps xkbKeyMapBuf is too small\n");
174+        return FALSE;
175+    }
176+#ifdef DEBUG
177+    if (xkbDebugFlags) {
178+       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
179+       fputs(xkbKeyMapBuf, stderr);
180+    }
181+#endif
182+    if (!ret) {
183+        ErrorF("[xkb] Generating XKB Keymap failed, giving up compiling keymap\n");
184+        return FALSE;
185+    }
186+
187+    DebugF("[xkb] computing SHA1 of keymap\n");
188+    if (Success == Sha1Asc(sha1Asc, xkbKeyMapBuf)) {
189+        snprintf(xkmfile, sizeof(xkmfile), "server-%s", sha1Asc);
190+    }
191+    else {
192+        ErrorF("[xkb] Computing SHA1 of keymap failed, "
193+               "using display name instead as xkm file name\n");
194+        snprintf(xkmfile, sizeof(xkmfile), "server-%s", display);
195+    }
196 
197     OutputDirectory(xkm_output_dir, sizeof(xkm_output_dir));
198+    /* set nameRtrn, fail if it's too small */
199+    if ((strlen(xkmfile)+1 > nameRtrnLen) && nameRtrn) {
200+        ErrorF("[xkb] nameRtrn too small to hold xkmfile name\n");
201+        return FALSE;
202+    }
203+    strncpy(nameRtrn, xkmfile, nameRtrnLen);
204+
205+    /* if the xkm file already exists, reuse it */
206+    canonicalXkmFileName = Xprintf("%s%s.xkm", xkm_output_dir, xkmfile);
207+    if (access(canonicalXkmFileName, R_OK) == 0) {
208+        /* yes, we can reuse the old xkm file */
209+        LogMessage(X_INFO, "XKB: reuse xkmfile %s\n", canonicalXkmFileName);
210+        result = TRUE;
211+        goto _ret;
212+    }
213+    LogMessage(X_INFO, "XKB: generating xkmfile %s\n", canonicalXkmFileName);
214+
215+    /* continue to call xkbcomp to compile the keymap. to avoid race
216+       condition, we compile it to a tmpfile then rename it to
217+       xkmfile */
218 
219 #ifdef WIN32
220     strcpy(tmpname, Win32TempDir());
221@@ -222,15 +315,21 @@
222 	}
223     }
224 
225+    if ( (tmpXkmFile = tempnam(xkm_output_dir, NULL)) == NULL ) {
226+	ErrorF("[xkb] Can't generate temp xkm file name");
227+	result = FALSE;
228+	goto _ret;
229+    }
230+
231     if (asprintf(&buf,
232 		 "\"%s%sxkbcomp\" -w %d %s -xkm \"%s\" "
233-		  "-em1 %s -emp %s -eml %s \"%s%s.xkm\"",
234+		  "-em1 %s -emp %s -eml %s \"%s\"",
235 		 xkbbindir, xkbbindirsep,
236 		 ((xkbDebugFlags < 2) ? 1 :
237 		  ((xkbDebugFlags > 10) ? 10 : (int) xkbDebugFlags)),
238-		 xkbbasedirflag ? xkbbasedirflag : "", xkmfile,
239+		 xkbbasedirflag ? xkbbasedirflag : "", xkbfile,
240 		 PRE_ERROR_MSG, ERROR_PREFIX, POST_ERROR_MSG1,
241-		 xkm_output_dir, keymap) == -1)
242+		 tmpXkmFile) == -1)
243 	buf = NULL;
244 
245     free(xkbbasedirflag);
246@@ -240,6 +339,11 @@
247         return FALSE;
248     }
249     
250+    /* there's a potential race condition between calling tempnam()
251+       and invoking xkbcomp to write the result file (potential temp
252+       file name conflicts), but since xkbcomp is a standalone
253+       program, we have to live with this */
254+
255 #ifndef WIN32
256     out= Popen(buf,"w");
257 #else
258@@ -247,30 +351,42 @@
259 #endif
260     
261     if (out!=NULL) {
262-#ifdef DEBUG
263-    if (xkbDebugFlags) {
264-       ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n");
265-       XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need);
266-    }
267-#endif
268-	XkbWriteXKBKeymapForNames(out,names,xkb,want,need);
269+	/* write XKBKeyMapBuf to xkbcomp */
270+	if (EOF==fputs(xkbKeyMapBuf, out))
271+	{
272+	    ErrorF("[xkb] Sending keymap to xkbcomp failed\n");
273+	    result = FALSE;
274+	    goto _ret;
275+	}
276 #ifndef WIN32
277 	if (Pclose(out)==0)
278 #else
279 	if (fclose(out)==0 && System(buf) >= 0)
280 #endif
281 	{
282+	    /* xkbcomp success */
283             if (xkbDebugFlags)
284-                DebugF("[xkb] xkb executes: %s\n",buf);
285-	    if (nameRtrn) {
286-		strncpy(nameRtrn,keymap,nameRtrnLen);
287-		nameRtrn[nameRtrnLen-1]= '\0';
288-	    }
289-            free(buf);
290-	    return TRUE;
291+		 DebugF("[xkb] xkb executes: %s\n",buf);
292+
293+	    /* if canonicalXkmFileName already exists now, we simply
294+	       overwrite it, this is OK */
295+	    ret = rename(tmpXkmFile, canonicalXkmFileName);
296+	    if (0 != ret) {
297+		ErrorF("[xkb] Can't rename %s to %s, error: %s\n",
298+		       tmpXkmFile, canonicalXkmFileName,
299+		       strerror(errno));
300+
301+		/* in case of error, don't unlink tmpXkmFile, leave i
302+		   for debugging */
303+
304+		result = FALSE;
305+		goto _ret;
306+ 	    }
307+	    result = TRUE;
308+	    goto _ret;
309 	}
310 	else
311-	    LogMessage(X_ERROR, "Error compiling keymap (%s)\n", keymap);
312+	    LogMessage(X_ERROR, "Error compiling keymap (%s)\n", xkbfile);
313 #ifdef WIN32
314         /* remove the temporary file */
315         unlink(tmpname);
316@@ -285,8 +401,17 @@
317     }
318     if (nameRtrn)
319 	nameRtrn[0]= '\0';
320-    free(buf);
321-    return FALSE;
322+    result = FALSE;
323+
324+_ret:
325+    if (tmpXkmFile)
326+	free(tmpXkmFile);
327+    if (canonicalXkmFileName)
328+	free(canonicalXkmFileName);
329+    if (buf)
330+	free(buf);
331+    
332+   return result;
333 }
334 
335 static FILE *
336@@ -370,7 +495,6 @@
337 	DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined);
338     }
339     fclose(file);
340-    (void) unlink (fileName);
341     return (need|want)&(~missing);
342 }
343