/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

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