loadmod.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  1. /*
  2. * Copyright 1995-1998 by Metro Link, Inc.
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that
  7. * copyright notice and this permission notice appear in supporting
  8. * documentation, and that the name of Metro Link, Inc. not be used in
  9. * advertising or publicity pertaining to distribution of the software without
  10. * specific, written prior permission. Metro Link, Inc. makes no
  11. * representations about the suitability of this software for any purpose.
  12. * It is provided "as is" without express or implied warranty.
  13. *
  14. * METRO LINK, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16. * EVENT SHALL METRO LINK, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20. * PERFORMANCE OF THIS SOFTWARE.
  21. */
  22. /*
  23. * Copyright (c) 1997-2002 by The XFree86 Project, Inc.
  24. *
  25. * Permission is hereby granted, free of charge, to any person obtaining a
  26. * copy of this software and associated documentation files (the "Software"),
  27. * to deal in the Software without restriction, including without limitation
  28. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  29. * and/or sell copies of the Software, and to permit persons to whom the
  30. * Software is furnished to do so, subject to the following conditions:
  31. *
  32. * The above copyright notice and this permission notice shall be included in
  33. * all copies or substantial portions of the Software.
  34. *
  35. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  36. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  37. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  38. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  39. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  40. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  41. * OTHER DEALINGS IN THE SOFTWARE.
  42. *
  43. * Except as contained in this notice, the name of the copyright holder(s)
  44. * and author(s) shall not be used in advertising or otherwise to promote
  45. * the sale, use or other dealings in this Software without prior written
  46. * authorization from the copyright holder(s) and author(s).
  47. */
  48. #ifdef HAVE_XORG_CONFIG_H
  49. #include <xorg-config.h>
  50. #endif
  51. #include "os.h"
  52. /* For stat() and related stuff */
  53. #define NO_OSLIB_PROTOTYPES
  54. #include "xf86_OSlib.h"
  55. #define LOADERDECLARATIONS
  56. #include "loaderProcs.h"
  57. #include "misc.h"
  58. #include "xf86.h"
  59. #include "xf86Priv.h"
  60. #include "xf86Xinput.h"
  61. #include "loader.h"
  62. #include "xf86Optrec.h"
  63. #include <sys/types.h>
  64. #include <regex.h>
  65. #include <dirent.h>
  66. #include <limits.h>
  67. typedef struct _pattern {
  68. const char *pattern;
  69. regex_t rex;
  70. } PatternRec, *PatternPtr;
  71. /* Prototypes for static functions */
  72. static char *FindModule(const char *, const char *, const char **, PatternPtr);
  73. static Bool CheckVersion(const char *, XF86ModuleVersionInfo *,
  74. const XF86ModReqInfo *);
  75. static void UnloadModuleOrDriver(ModuleDescPtr mod);
  76. static char *LoaderGetCanonicalName(const char *, PatternPtr);
  77. static void RemoveChild(ModuleDescPtr);
  78. static ModuleDescPtr doLoadModule(const char *, const char *, const char **,
  79. const char **, void *,
  80. const XF86ModReqInfo *, int *, int *);
  81. const ModuleVersions LoaderVersionInfo = {
  82. XORG_VERSION_CURRENT,
  83. ABI_ANSIC_VERSION,
  84. ABI_VIDEODRV_VERSION,
  85. ABI_XINPUT_VERSION,
  86. ABI_EXTENSION_VERSION,
  87. ABI_FONT_VERSION
  88. };
  89. static int ModuleDuplicated[] = { };
  90. static void
  91. FreeStringList(char **paths)
  92. {
  93. char **p;
  94. if (!paths)
  95. return;
  96. for (p = paths; *p; p++)
  97. free(*p);
  98. free(paths);
  99. }
  100. static char **defaultPathList = NULL;
  101. static Bool
  102. PathIsAbsolute(const char *path)
  103. {
  104. return *path == '/';
  105. }
  106. /*
  107. * Convert a comma-separated path into a NULL-terminated array of path
  108. * elements, rejecting any that are not full absolute paths, and appending
  109. * a '/' when it isn't already present.
  110. */
  111. static char **
  112. InitPathList(const char *path)
  113. {
  114. char *fullpath = NULL;
  115. char *elem = NULL;
  116. char **list = NULL, **save = NULL;
  117. int len;
  118. int addslash;
  119. int n = 0;
  120. if (!path)
  121. return defaultPathList;
  122. fullpath = strdup(path);
  123. if (!fullpath)
  124. return NULL;
  125. elem = strtok(fullpath, ",");
  126. while (elem) {
  127. if (PathIsAbsolute(elem)) {
  128. len = strlen(elem);
  129. addslash = (elem[len - 1] != '/');
  130. if (addslash)
  131. len++;
  132. save = list;
  133. list = realloc(list, (n + 2) * sizeof(char *));
  134. if (!list) {
  135. if (save) {
  136. save[n] = NULL;
  137. FreeStringList(save);
  138. }
  139. free(fullpath);
  140. return NULL;
  141. }
  142. list[n] = malloc(len + 1);
  143. if (!list[n]) {
  144. FreeStringList(list);
  145. free(fullpath);
  146. return NULL;
  147. }
  148. strcpy(list[n], elem);
  149. if (addslash) {
  150. list[n][len - 1] = '/';
  151. list[n][len] = '\0';
  152. }
  153. n++;
  154. }
  155. elem = strtok(NULL, ",");
  156. }
  157. if (list)
  158. list[n] = NULL;
  159. free(fullpath);
  160. return list;
  161. }
  162. static void
  163. FreePathList(char **pathlist)
  164. {
  165. if (pathlist && pathlist != defaultPathList)
  166. FreeStringList(pathlist);
  167. }
  168. void
  169. LoaderSetPath(const char *path)
  170. {
  171. if (!path)
  172. return;
  173. defaultPathList = InitPathList(path);
  174. }
  175. /* Standard set of module subdirectories to search, in order of preference */
  176. static const char *stdSubdirs[] = {
  177. "",
  178. "input/",
  179. "drivers/",
  180. "multimedia/",
  181. "extensions/",
  182. "internal/",
  183. NULL
  184. };
  185. /*
  186. * Standard set of module name patterns to check, in order of preference
  187. * These are regular expressions (suitable for use with POSIX regex(3)).
  188. *
  189. * This list assumes that you're an ELFish platform and therefore your
  190. * shared libraries are named something.so. If we're ever nuts enough
  191. * to port this DDX to, say, Darwin, we'll need to fix this.
  192. */
  193. static PatternRec stdPatterns[] = {
  194. #ifdef __CYGWIN__
  195. {"^cyg(.*)\\.dll$",},
  196. {"(.*)_drv\\.dll$",},
  197. {"(.*)\\.dll$",},
  198. #else
  199. {"^lib(.*)\\.so$",},
  200. {"(.*)_drv\\.so$",},
  201. {"(.*)\\.so$",},
  202. #endif
  203. {NULL,}
  204. };
  205. static PatternPtr
  206. InitPatterns(const char **patternlist)
  207. {
  208. char errmsg[80];
  209. int i, e;
  210. PatternPtr patterns = NULL;
  211. PatternPtr p = NULL;
  212. static int firstTime = 1;
  213. const char **s;
  214. if (firstTime) {
  215. /* precompile stdPatterns */
  216. firstTime = 0;
  217. for (p = stdPatterns; p->pattern; p++)
  218. if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) {
  219. regerror(e, &p->rex, errmsg, sizeof(errmsg));
  220. FatalError("InitPatterns: regcomp error for `%s': %s\n",
  221. p->pattern, errmsg);
  222. }
  223. }
  224. if (patternlist) {
  225. for (i = 0, s = patternlist; *s; i++, s++)
  226. if (*s == DEFAULT_LIST)
  227. i += sizeof(stdPatterns) / sizeof(stdPatterns[0]) - 1 - 1;
  228. patterns = malloc((i + 1) * sizeof(PatternRec));
  229. if (!patterns) {
  230. return NULL;
  231. }
  232. for (i = 0, s = patternlist; *s; i++, s++)
  233. if (*s != DEFAULT_LIST) {
  234. p = patterns + i;
  235. p->pattern = *s;
  236. if ((e = regcomp(&p->rex, p->pattern, REG_EXTENDED)) != 0) {
  237. regerror(e, &p->rex, errmsg, sizeof(errmsg));
  238. ErrorF("InitPatterns: regcomp error for `%s': %s\n",
  239. p->pattern, errmsg);
  240. i--;
  241. }
  242. }
  243. else {
  244. for (p = stdPatterns; p->pattern; p++, i++)
  245. patterns[i] = *p;
  246. if (p != stdPatterns)
  247. i--;
  248. }
  249. patterns[i].pattern = NULL;
  250. }
  251. else
  252. patterns = stdPatterns;
  253. return patterns;
  254. }
  255. static void
  256. FreePatterns(PatternPtr patterns)
  257. {
  258. if (patterns && patterns != stdPatterns)
  259. free(patterns);
  260. }
  261. static const char **
  262. InitSubdirs(const char **subdirlist)
  263. {
  264. int i;
  265. const char **tmp_subdirlist = NULL;
  266. char **subdirs = NULL;
  267. const char **s, **stmp = NULL;
  268. const char *osname;
  269. const char *slash;
  270. int oslen = 0, len;
  271. Bool indefault;
  272. if (subdirlist == NULL) {
  273. subdirlist = tmp_subdirlist = malloc(2 * sizeof(char *));
  274. if (subdirlist == NULL)
  275. return NULL;
  276. subdirlist[0] = DEFAULT_LIST;
  277. subdirlist[1] = NULL;
  278. }
  279. LoaderGetOS(&osname, NULL, NULL, NULL);
  280. oslen = strlen(osname);
  281. {
  282. /* Count number of entries and check for invalid paths */
  283. for (i = 0, s = subdirlist; *s; i++, s++) {
  284. if (*s == DEFAULT_LIST) {
  285. i += sizeof(stdSubdirs) / sizeof(stdSubdirs[0]) - 1 - 1;
  286. }
  287. else {
  288. /*
  289. * Path validity check. Don't allow absolute paths, or
  290. * paths containing "..". To catch absolute paths on
  291. * platforms that use driver letters, don't allow the ':'
  292. * character to appear at all.
  293. */
  294. if (**s == '/' || **s == '\\' || strchr(*s, ':') ||
  295. strstr(*s, "..")) {
  296. xf86Msg(X_ERROR, "InitSubdirs: Bad subdir: \"%s\"\n", *s);
  297. free(tmp_subdirlist);
  298. return NULL;
  299. }
  300. }
  301. }
  302. subdirs = malloc((i * 2 + 1) * sizeof(char *));
  303. if (!subdirs) {
  304. free(tmp_subdirlist);
  305. return NULL;
  306. }
  307. i = 0;
  308. s = subdirlist;
  309. indefault = FALSE;
  310. while (*s) {
  311. if (*s == DEFAULT_LIST) {
  312. /* Divert to the default list */
  313. indefault = TRUE;
  314. stmp = ++s;
  315. s = stdSubdirs;
  316. }
  317. len = strlen(*s);
  318. if (**s && (*s)[len - 1] != '/') {
  319. slash = "/";
  320. len++;
  321. }
  322. else
  323. slash = "";
  324. len += oslen + 2;
  325. if (!(subdirs[i] = malloc(len))) {
  326. while (--i >= 0)
  327. free(subdirs[i]);
  328. free(subdirs);
  329. free(tmp_subdirlist);
  330. return NULL;
  331. }
  332. /* tack on the OS name */
  333. sprintf(subdirs[i], "%s%s%s/", *s, slash, osname);
  334. i++;
  335. /* path as given */
  336. subdirs[i] = strdup(*s);
  337. i++;
  338. s++;
  339. if (indefault && !s) {
  340. /* revert back to the main list */
  341. indefault = FALSE;
  342. s = stmp;
  343. }
  344. }
  345. subdirs[i] = NULL;
  346. }
  347. free(tmp_subdirlist);
  348. return (const char **) subdirs;
  349. }
  350. static void
  351. FreeSubdirs(const char **subdirs)
  352. {
  353. const char **s;
  354. if (subdirs) {
  355. for (s = subdirs; *s; s++)
  356. free((char *) *s);
  357. free(subdirs);
  358. }
  359. }
  360. static char *
  361. FindModuleInSubdir(const char *dirpath, const char *module)
  362. {
  363. struct dirent *direntry = NULL;
  364. DIR *dir = NULL;
  365. char *ret = NULL, tmpBuf[PATH_MAX];
  366. struct stat stat_buf;
  367. dir = opendir(dirpath);
  368. if (!dir)
  369. return NULL;
  370. while ((direntry = readdir(dir))) {
  371. if (direntry->d_name[0] == '.')
  372. continue;
  373. snprintf(tmpBuf, PATH_MAX, "%s%s/", dirpath, direntry->d_name);
  374. /* the stat with the appended / fails for normal files,
  375. and works for sub dirs fine, looks a bit strange in strace
  376. but does seem to work */
  377. if ((stat(tmpBuf, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) {
  378. if ((ret = FindModuleInSubdir(tmpBuf, module)))
  379. break;
  380. continue;
  381. }
  382. #ifdef __CYGWIN__
  383. snprintf(tmpBuf, PATH_MAX, "cyg%s.dll", module);
  384. #else
  385. snprintf(tmpBuf, PATH_MAX, "lib%s.so", module);
  386. #endif
  387. if (strcmp(direntry->d_name, tmpBuf) == 0) {
  388. if (asprintf(&ret, "%s%s", dirpath, tmpBuf) == -1)
  389. ret = NULL;
  390. break;
  391. }
  392. #ifdef __CYGWIN__
  393. snprintf(tmpBuf, PATH_MAX, "%s_drv.dll", module);
  394. #else
  395. snprintf(tmpBuf, PATH_MAX, "%s_drv.so", module);
  396. #endif
  397. if (strcmp(direntry->d_name, tmpBuf) == 0) {
  398. if (asprintf(&ret, "%s%s", dirpath, tmpBuf) == -1)
  399. ret = NULL;
  400. break;
  401. }
  402. #ifdef __CYGWIN__
  403. snprintf(tmpBuf, PATH_MAX, "%s.dll", module);
  404. #else
  405. snprintf(tmpBuf, PATH_MAX, "%s.so", module);
  406. #endif
  407. if (strcmp(direntry->d_name, tmpBuf) == 0) {
  408. if (asprintf(&ret, "%s%s", dirpath, tmpBuf) == -1)
  409. ret = NULL;
  410. break;
  411. }
  412. }
  413. closedir(dir);
  414. return ret;
  415. }
  416. static char *
  417. FindModule(const char *module, const char *dirname, const char **subdirlist,
  418. PatternPtr patterns)
  419. {
  420. char buf[PATH_MAX + 1];
  421. char *name = NULL;
  422. const char **subdirs = NULL;
  423. const char **s;
  424. if (strlen(dirname) > PATH_MAX)
  425. return NULL;
  426. subdirs = InitSubdirs(subdirlist);
  427. if (!subdirs)
  428. return NULL;
  429. for (s = subdirs; *s; s++) {
  430. if ((strlen(dirname) + strlen(*s)) > PATH_MAX)
  431. continue;
  432. strcpy(buf, dirname);
  433. strcat(buf, *s);
  434. if ((name = FindModuleInSubdir(buf, module)))
  435. break;
  436. }
  437. FreeSubdirs(subdirs);
  438. return name;
  439. }
  440. const char **
  441. LoaderListDirs(const char **subdirlist, const char **patternlist)
  442. {
  443. char buf[PATH_MAX + 1];
  444. char **pathlist;
  445. char **elem;
  446. const char **subdirs;
  447. const char **s;
  448. PatternPtr patterns = NULL;
  449. PatternPtr p;
  450. DIR *d;
  451. struct dirent *dp;
  452. regmatch_t match[2];
  453. struct stat stat_buf;
  454. int len, dirlen;
  455. char *fp;
  456. char **listing = NULL;
  457. char **save;
  458. char **ret = NULL;
  459. int n = 0;
  460. if (!(pathlist = InitPathList(NULL)))
  461. return NULL;
  462. if (!(subdirs = InitSubdirs(subdirlist)))
  463. goto bail;
  464. if (!(patterns = InitPatterns(patternlist)))
  465. goto bail;
  466. for (elem = pathlist; *elem; elem++) {
  467. for (s = subdirs; *s; s++) {
  468. if ((dirlen = strlen(*elem) + strlen(*s)) > PATH_MAX)
  469. continue;
  470. strcpy(buf, *elem);
  471. strcat(buf, *s);
  472. fp = buf + dirlen;
  473. if (stat(buf, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode) &&
  474. (d = opendir(buf))) {
  475. if (buf[dirlen - 1] != '/') {
  476. buf[dirlen++] = '/';
  477. fp++;
  478. }
  479. while ((dp = readdir(d))) {
  480. if (dirlen + strlen(dp->d_name) > PATH_MAX)
  481. continue;
  482. strcpy(fp, dp->d_name);
  483. if (!(stat(buf, &stat_buf) == 0 &&
  484. S_ISREG(stat_buf.st_mode)))
  485. continue;
  486. for (p = patterns; p->pattern; p++) {
  487. if (regexec(&p->rex, dp->d_name, 2, match, 0) == 0 &&
  488. match[1].rm_so != -1) {
  489. len = match[1].rm_eo - match[1].rm_so;
  490. save = listing;
  491. listing = realloc(listing,
  492. (n + 2) * sizeof(char *));
  493. if (!listing) {
  494. if (save) {
  495. save[n] = NULL;
  496. FreeStringList(save);
  497. }
  498. closedir(d);
  499. goto bail;
  500. }
  501. listing[n] = malloc(len + 1);
  502. if (!listing[n]) {
  503. FreeStringList(listing);
  504. closedir(d);
  505. goto bail;
  506. }
  507. strncpy(listing[n], dp->d_name + match[1].rm_so,
  508. len);
  509. listing[n][len] = '\0';
  510. n++;
  511. break;
  512. }
  513. }
  514. }
  515. closedir(d);
  516. }
  517. }
  518. }
  519. if (listing)
  520. listing[n] = NULL;
  521. ret = listing;
  522. bail:
  523. FreePatterns(patterns);
  524. FreeSubdirs(subdirs);
  525. FreePathList(pathlist);
  526. return (const char **) ret;
  527. }
  528. void
  529. LoaderFreeDirList(char **list)
  530. {
  531. FreeStringList(list);
  532. }
  533. static Bool
  534. CheckVersion(const char *module, XF86ModuleVersionInfo * data,
  535. const XF86ModReqInfo * req)
  536. {
  537. int vercode[4];
  538. char verstr[4];
  539. long ver = data->xf86version;
  540. MessageType errtype;
  541. xf86Msg(X_INFO, "Module %s: vendor=\"%s\"\n",
  542. data->modname ? data->modname : "UNKNOWN!",
  543. data->vendor ? data->vendor : "UNKNOWN!");
  544. /* Check for the different scheme used in XFree86 4.0.x releases:
  545. * ((((((((major << 7) | minor) << 7) | subminor) << 5) | beta) << 5) | alpha)
  546. * Since it wasn't used in 4.1.0 or later, limit to versions in the 4.0.x
  547. * range, which limits the overlap with the new version scheme to conflicts
  548. * with 6.71.8.764 through 6.72.39.934.
  549. */
  550. if ((ver > (4 << 24)) && (ver < ((4 << 24) + (1 << 17)))) {
  551. /* 4.0.x and earlier */
  552. verstr[1] = verstr[3] = 0;
  553. verstr[2] = (ver & 0x1f) ? (ver & 0x1f) + 'a' - 1 : 0;
  554. ver >>= 5;
  555. verstr[0] = (ver & 0x1f) ? (ver & 0x1f) + 'A' - 1 : 0;
  556. ver >>= 5;
  557. vercode[2] = ver & 0x7f;
  558. ver >>= 7;
  559. vercode[1] = ver & 0x7f;
  560. ver >>= 7;
  561. vercode[0] = ver;
  562. xf86ErrorF("\tcompiled for %d.%d", vercode[0], vercode[1]);
  563. if (vercode[2] != 0)
  564. xf86ErrorF(".%d", vercode[2]);
  565. xf86ErrorF("%s%s, module version = %d.%d.%d\n", verstr, verstr + 2,
  566. data->majorversion, data->minorversion, data->patchlevel);
  567. }
  568. else {
  569. vercode[0] = ver / 10000000;
  570. vercode[1] = (ver / 100000) % 100;
  571. vercode[2] = (ver / 1000) % 100;
  572. vercode[3] = ver % 1000;
  573. xf86ErrorF("\tcompiled for %d.%d.%d", vercode[0], vercode[1],
  574. vercode[2]);
  575. if (vercode[3] != 0)
  576. xf86ErrorF(".%d", vercode[3]);
  577. xf86ErrorF(", module version = %d.%d.%d\n", data->majorversion,
  578. data->minorversion, data->patchlevel);
  579. }
  580. if (data->moduleclass)
  581. xf86ErrorFVerb(2, "\tModule class: %s\n", data->moduleclass);
  582. ver = -1;
  583. if (data->abiclass) {
  584. int abimaj, abimin;
  585. int vermaj, vermin;
  586. if (!strcmp(data->abiclass, ABI_CLASS_ANSIC))
  587. ver = LoaderVersionInfo.ansicVersion;
  588. else if (!strcmp(data->abiclass, ABI_CLASS_VIDEODRV))
  589. ver = LoaderVersionInfo.videodrvVersion;
  590. else if (!strcmp(data->abiclass, ABI_CLASS_XINPUT))
  591. ver = LoaderVersionInfo.xinputVersion;
  592. else if (!strcmp(data->abiclass, ABI_CLASS_EXTENSION))
  593. ver = LoaderVersionInfo.extensionVersion;
  594. else if (!strcmp(data->abiclass, ABI_CLASS_FONT))
  595. ver = LoaderVersionInfo.fontVersion;
  596. abimaj = GET_ABI_MAJOR(data->abiversion);
  597. abimin = GET_ABI_MINOR(data->abiversion);
  598. xf86ErrorFVerb(2, "\tABI class: %s, version %d.%d\n",
  599. data->abiclass, abimaj, abimin);
  600. if (ver != -1) {
  601. vermaj = GET_ABI_MAJOR(ver);
  602. vermin = GET_ABI_MINOR(ver);
  603. if (abimaj != vermaj) {
  604. if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)
  605. errtype = X_WARNING;
  606. else
  607. errtype = X_ERROR;
  608. xf86MsgVerb(errtype, 0,
  609. "module ABI major version (%d) doesn't"
  610. " match the server's version (%d)\n",
  611. abimaj, vermaj);
  612. if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL))
  613. return FALSE;
  614. }
  615. else if (abimin > vermin) {
  616. if (LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL)
  617. errtype = X_WARNING;
  618. else
  619. errtype = X_ERROR;
  620. xf86MsgVerb(errtype, 0,
  621. "module ABI minor version (%d) is "
  622. "newer than the server's version "
  623. "(%d)\n", abimin, vermin);
  624. if (!(LoaderOptions & LDR_OPT_ABI_MISMATCH_NONFATAL))
  625. return FALSE;
  626. }
  627. }
  628. }
  629. /* Check against requirements that the caller has specified */
  630. if (req) {
  631. if (req->majorversion != MAJOR_UNSPEC) {
  632. if (data->majorversion != req->majorversion) {
  633. xf86MsgVerb(X_WARNING, 2, "module major version (%d) "
  634. "doesn't match required major version (%d)\n",
  635. data->majorversion, req->majorversion);
  636. return FALSE;
  637. }
  638. else if (req->minorversion != MINOR_UNSPEC) {
  639. if (data->minorversion < req->minorversion) {
  640. xf86MsgVerb(X_WARNING, 2, "module minor version (%d) "
  641. "is less than the required minor version (%d)\n",
  642. data->minorversion, req->minorversion);
  643. return FALSE;
  644. }
  645. else if (data->minorversion == req->minorversion &&
  646. req->patchlevel != PATCH_UNSPEC) {
  647. if (data->patchlevel < req->patchlevel) {
  648. xf86MsgVerb(X_WARNING, 2, "module patch level (%d) "
  649. "is less than the required patch level (%d)\n",
  650. data->patchlevel, req->patchlevel);
  651. return FALSE;
  652. }
  653. }
  654. }
  655. }
  656. if (req->moduleclass) {
  657. if (!data->moduleclass ||
  658. strcmp(req->moduleclass, data->moduleclass)) {
  659. xf86MsgVerb(X_WARNING, 2, "Module class (%s) doesn't match "
  660. "the required class (%s)\n",
  661. data->moduleclass ? data->moduleclass : "<NONE>",
  662. req->moduleclass);
  663. return FALSE;
  664. }
  665. }
  666. else if (req->abiclass != ABI_CLASS_NONE) {
  667. if (!data->abiclass || strcmp(req->abiclass, data->abiclass)) {
  668. xf86MsgVerb(X_WARNING, 2, "ABI class (%s) doesn't match the "
  669. "required ABI class (%s)\n",
  670. data->abiclass ? data->abiclass : "<NONE>",
  671. req->abiclass);
  672. return FALSE;
  673. }
  674. }
  675. if ((req->abiclass != ABI_CLASS_NONE) &&
  676. req->abiversion != ABI_VERS_UNSPEC) {
  677. int reqmaj, reqmin, maj, min;
  678. reqmaj = GET_ABI_MAJOR(req->abiversion);
  679. reqmin = GET_ABI_MINOR(req->abiversion);
  680. maj = GET_ABI_MAJOR(data->abiversion);
  681. min = GET_ABI_MINOR(data->abiversion);
  682. if (maj != reqmaj) {
  683. xf86MsgVerb(X_WARNING, 2, "ABI major version (%d) doesn't "
  684. "match the required ABI major version (%d)\n",
  685. maj, reqmaj);
  686. return FALSE;
  687. }
  688. /* XXX Maybe this should be the other way around? */
  689. if (min > reqmin) {
  690. xf86MsgVerb(X_WARNING, 2, "module ABI minor version (%d) "
  691. "is newer than that available (%d)\n", min, reqmin);
  692. return FALSE;
  693. }
  694. }
  695. }
  696. return TRUE;
  697. }
  698. static ModuleDescPtr
  699. AddSibling(ModuleDescPtr head, ModuleDescPtr new)
  700. {
  701. new->sib = head;
  702. return new;
  703. }
  704. void *
  705. LoadSubModule(void *_parent, const char *module,
  706. const char **subdirlist, const char **patternlist,
  707. void *options, const XF86ModReqInfo * modreq,
  708. int *errmaj, int *errmin)
  709. {
  710. ModuleDescPtr submod;
  711. ModuleDescPtr parent = (ModuleDescPtr) _parent;
  712. xf86MsgVerb(X_INFO, 3, "Loading sub module \"%s\"\n", module);
  713. if (PathIsAbsolute(module)) {
  714. xf86Msg(X_ERROR,
  715. "LoadSubModule: Absolute module path not permitted: \"%s\"\n",
  716. module);
  717. if (errmaj)
  718. *errmaj = LDR_BADUSAGE;
  719. if (errmin)
  720. *errmin = 0;
  721. return NULL;
  722. }
  723. submod = doLoadModule(module, NULL, subdirlist, patternlist, options,
  724. modreq, errmaj, errmin);
  725. if (submod && submod != (ModuleDescPtr) 1) {
  726. parent->child = AddSibling(parent->child, submod);
  727. submod->parent = parent;
  728. }
  729. return submod;
  730. }
  731. static ModuleDescPtr
  732. NewModuleDesc(const char *name)
  733. {
  734. ModuleDescPtr mdp = calloc(1, sizeof(ModuleDesc));
  735. if (mdp)
  736. mdp->name = xstrdup(name);
  737. return mdp;
  738. }
  739. ModuleDescPtr
  740. DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
  741. {
  742. ModuleDescPtr ret;
  743. if (!mod)
  744. return NULL;
  745. ret = NewModuleDesc(mod->name);
  746. if (ret == NULL)
  747. return NULL;
  748. ret->handle = mod->handle;
  749. ret->SetupProc = mod->SetupProc;
  750. ret->TearDownProc = mod->TearDownProc;
  751. ret->TearDownData = ModuleDuplicated;
  752. ret->child = DuplicateModule(mod->child, ret);
  753. ret->sib = DuplicateModule(mod->sib, parent);
  754. ret->parent = parent;
  755. ret->VersionInfo = mod->VersionInfo;
  756. ret->path = strdup(mod->path);
  757. return ret;
  758. }
  759. static const char *compiled_in_modules[] = {
  760. "ddc",
  761. "i2c",
  762. "ramdac",
  763. "dbe",
  764. "record",
  765. "extmod",
  766. "dri",
  767. "dri2",
  768. #if DRI3
  769. "dri3",
  770. #endif
  771. #if PRESENT
  772. "present",
  773. #endif
  774. NULL
  775. };
  776. static ModuleDescPtr
  777. doLoadModule(const char *module, const char *path, const char **subdirlist,
  778. const char **patternlist, void *options,
  779. const XF86ModReqInfo * modreq, int *errmaj, int *errmin)
  780. {
  781. XF86ModuleData *initdata = NULL;
  782. char **pathlist = NULL;
  783. char *found = NULL;
  784. char *name = NULL;
  785. char **path_elem = NULL;
  786. char *p = NULL;
  787. ModuleDescPtr ret = NULL;
  788. PatternPtr patterns = NULL;
  789. int noncanonical = 0;
  790. char *m = NULL;
  791. const char **cim;
  792. xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module);
  793. patterns = InitPatterns(patternlist);
  794. name = LoaderGetCanonicalName(module, patterns);
  795. noncanonical = (name && strcmp(module, name) != 0);
  796. if (noncanonical) {
  797. xf86ErrorFVerb(3, " (%s)\n", name);
  798. xf86MsgVerb(X_WARNING, 1,
  799. "LoadModule: given non-canonical module name \"%s\"\n",
  800. module);
  801. m = name;
  802. }
  803. else {
  804. xf86ErrorFVerb(3, "\n");
  805. m = (char *) module;
  806. }
  807. for (cim = compiled_in_modules; *cim; cim++)
  808. if (!strcmp(m, *cim)) {
  809. xf86MsgVerb(X_INFO, 3, "Module \"%s\" already built-in\n", m);
  810. ret = (ModuleDescPtr) 1;
  811. goto LoadModule_exit;
  812. }
  813. if (!name) {
  814. if (errmaj)
  815. *errmaj = LDR_BADUSAGE;
  816. if (errmin)
  817. *errmin = 0;
  818. goto LoadModule_fail;
  819. }
  820. ret = NewModuleDesc(name);
  821. if (!ret) {
  822. if (errmaj)
  823. *errmaj = LDR_NOMEM;
  824. if (errmin)
  825. *errmin = 0;
  826. goto LoadModule_fail;
  827. }
  828. pathlist = InitPathList(path);
  829. if (!pathlist) {
  830. /* This could be a malloc failure too */
  831. if (errmaj)
  832. *errmaj = LDR_BADUSAGE;
  833. if (errmin)
  834. *errmin = 1;
  835. goto LoadModule_fail;
  836. }
  837. /*
  838. * if the module name is not a full pathname, we need to
  839. * check the elements in the path
  840. */
  841. if (PathIsAbsolute(module))
  842. found = xstrdup(module);
  843. path_elem = pathlist;
  844. while (!found && *path_elem != NULL) {
  845. found = FindModule(m, *path_elem, subdirlist, patterns);
  846. path_elem++;
  847. /*
  848. * When the module name isn't the canonical name, search for the
  849. * former if no match was found for the latter.
  850. */
  851. if (!*path_elem && m == name) {
  852. path_elem = pathlist;
  853. m = (char *) module;
  854. }
  855. }
  856. /*
  857. * did we find the module?
  858. */
  859. if (!found) {
  860. xf86Msg(X_WARNING, "Warning, couldn't open module %s\n", module);
  861. if (errmaj)
  862. *errmaj = LDR_NOENT;
  863. if (errmin)
  864. *errmin = 0;
  865. goto LoadModule_fail;
  866. }
  867. ret->handle = LoaderOpen(found, errmaj, errmin);
  868. if (ret->handle == NULL)
  869. goto LoadModule_fail;
  870. ret->path = strdup(found);
  871. /* drop any explicit suffix from the module name */
  872. p = strchr(name, '.');
  873. if (p)
  874. *p = '\0';
  875. /*
  876. * now check if the special data object <modulename>ModuleData is
  877. * present.
  878. */
  879. if (asprintf(&p, "%sModuleData", name) == -1) {
  880. p = NULL;
  881. if (errmaj)
  882. *errmaj = LDR_NOMEM;
  883. if (errmin)
  884. *errmin = 0;
  885. goto LoadModule_fail;
  886. }
  887. initdata = LoaderSymbolFromModule(ret->handle, p);
  888. if (initdata) {
  889. ModuleSetupProc setup;
  890. ModuleTearDownProc teardown;
  891. XF86ModuleVersionInfo *vers;
  892. vers = initdata->vers;
  893. setup = initdata->setup;
  894. teardown = initdata->teardown;
  895. if (vers) {
  896. if (!CheckVersion(module, vers, modreq)) {
  897. if (errmaj)
  898. *errmaj = LDR_MISMATCH;
  899. if (errmin)
  900. *errmin = 0;
  901. goto LoadModule_fail;
  902. }
  903. }
  904. else {
  905. xf86Msg(X_ERROR,
  906. "LoadModule: Module %s does not supply"
  907. " version information\n", module);
  908. if (errmaj)
  909. *errmaj = LDR_INVALID;
  910. if (errmin)
  911. *errmin = 0;
  912. goto LoadModule_fail;
  913. }
  914. if (setup)
  915. ret->SetupProc = setup;
  916. if (teardown)
  917. ret->TearDownProc = teardown;
  918. ret->VersionInfo = vers;
  919. }
  920. else {
  921. /* no initdata, fail the load */
  922. xf86Msg(X_ERROR, "LoadModule: Module %s does not have a %s "
  923. "data object.\n", module, p);
  924. if (errmaj)
  925. *errmaj = LDR_INVALID;
  926. if (errmin)
  927. *errmin = 0;
  928. goto LoadModule_fail;
  929. }
  930. if (ret->SetupProc) {
  931. ret->TearDownData = ret->SetupProc(ret, options, errmaj, errmin);
  932. if (!ret->TearDownData) {
  933. goto LoadModule_fail;
  934. }
  935. }
  936. else if (options) {
  937. xf86Msg(X_WARNING, "Module Options present, but no SetupProc "
  938. "available for %s\n", module);
  939. }
  940. goto LoadModule_exit;
  941. LoadModule_fail:
  942. UnloadModule(ret);
  943. ret = NULL;
  944. LoadModule_exit:
  945. FreePathList(pathlist);
  946. FreePatterns(patterns);
  947. free(found);
  948. free(name);
  949. free(p);
  950. return ret;
  951. }
  952. /*
  953. * LoadModule: load a module
  954. *
  955. * module The module name. Normally this is not a filename but the
  956. * module's "canonical name. A full pathname is, however,
  957. * also accepted.
  958. * path A comma separated list of module directories.
  959. * subdirlist A NULL terminated list of subdirectories to search. When
  960. * NULL, the default "stdSubdirs" list is used. The default
  961. * list is also substituted for entries with value DEFAULT_LIST.
  962. * patternlist A NULL terminated list of regular expressions used to find
  963. * module filenames. Each regex should contain exactly one
  964. * subexpression that corresponds to the canonical module name.
  965. * When NULL, the default "stdPatterns" list is used. The
  966. * default list is also substituted for entries with value
  967. * DEFAULT_LIST.
  968. * options A NULL terminated list of Options that are passed to the
  969. * module's SetupProc function.
  970. * modreq An optional XF86ModReqInfo* containing
  971. * version/ABI/vendor-ABI requirements to check for when
  972. * loading the module. The following fields of the
  973. * XF86ModReqInfo struct are checked:
  974. * majorversion - must match the module's majorversion exactly
  975. * minorversion - the module's minorversion must be >= this
  976. * patchlevel - the module's minorversion.patchlevel must be
  977. * >= this. Patchlevel is ignored when
  978. * minorversion is not set.
  979. * abiclass - (string) must match the module's abiclass
  980. * abiversion - must be consistent with the module's
  981. * abiversion (major equal, minor no older)
  982. * moduleclass - string must match the module's moduleclass
  983. * string
  984. * "don't care" values are ~0 for numbers, and NULL for strings
  985. * errmaj Major error return.
  986. * errmin Minor error return.
  987. *
  988. */
  989. ModuleDescPtr
  990. LoadModule(const char *module, const char *path, const char **subdirlist,
  991. const char **patternlist, void *options,
  992. const XF86ModReqInfo * modreq, int *errmaj, int *errmin)
  993. {
  994. return doLoadModule(module, path, subdirlist, patternlist, options,
  995. modreq, errmaj, errmin);
  996. }
  997. void
  998. UnloadModule(void *mod)
  999. {
  1000. UnloadModuleOrDriver((ModuleDescPtr) mod);
  1001. }
  1002. static void
  1003. UnloadModuleOrDriver(ModuleDescPtr mod)
  1004. {
  1005. if (mod == (ModuleDescPtr) 1)
  1006. return;
  1007. if (mod == NULL || mod->name == NULL)
  1008. return;
  1009. if (mod->parent)
  1010. LogMessageVerbSigSafe(X_INFO, 3, "UnloadSubModule: \"%s\"\n",
  1011. mod->name);
  1012. else
  1013. LogMessageVerbSigSafe(X_INFO, 3, "UnloadModule: \"%s\"\n", mod->name);
  1014. if (mod->TearDownData != ModuleDuplicated) {
  1015. if ((mod->TearDownProc) && (mod->TearDownData))
  1016. mod->TearDownProc(mod->TearDownData);
  1017. LoaderUnload(mod->name, mod->handle);
  1018. }
  1019. if (mod->child)
  1020. UnloadModuleOrDriver(mod->child);
  1021. if (mod->sib)
  1022. UnloadModuleOrDriver(mod->sib);
  1023. free(mod->path);
  1024. free(mod->name);
  1025. free(mod);
  1026. }
  1027. void
  1028. UnloadSubModule(void *_mod)
  1029. {
  1030. ModuleDescPtr mod = (ModuleDescPtr) _mod;
  1031. /* Some drivers are calling us on built-in submodules, ignore them */
  1032. if (mod == (ModuleDescPtr) 1)
  1033. return;
  1034. RemoveChild(mod);
  1035. UnloadModuleOrDriver(mod);
  1036. }
  1037. static void
  1038. RemoveChild(ModuleDescPtr child)
  1039. {
  1040. ModuleDescPtr mdp;
  1041. ModuleDescPtr prevsib;
  1042. ModuleDescPtr parent;
  1043. if (!child->parent)
  1044. return;
  1045. parent = child->parent;
  1046. if (parent->child == child) {
  1047. parent->child = child->sib;
  1048. return;
  1049. }
  1050. prevsib = parent->child;
  1051. mdp = prevsib->sib;
  1052. while (mdp && mdp != child) {
  1053. prevsib = mdp;
  1054. mdp = mdp->sib;
  1055. }
  1056. if (mdp == child)
  1057. prevsib->sib = child->sib;
  1058. child->sib = NULL;
  1059. return;
  1060. }
  1061. void
  1062. LoaderErrorMsg(const char *name, const char *modname, int errmaj, int errmin)
  1063. {
  1064. const char *msg;
  1065. MessageType type = X_ERROR;
  1066. switch (errmaj) {
  1067. case LDR_NOERROR:
  1068. msg = "no error";
  1069. break;
  1070. case LDR_NOMEM:
  1071. msg = "out of memory";
  1072. break;
  1073. case LDR_NOENT:
  1074. msg = "module does not exist";
  1075. break;
  1076. case LDR_NOSUBENT:
  1077. msg = "a required submodule could not be loaded";
  1078. break;
  1079. case LDR_NOSPACE:
  1080. msg = "too many modules";
  1081. break;
  1082. case LDR_NOMODOPEN:
  1083. msg = "open failed";
  1084. break;
  1085. case LDR_UNKTYPE:
  1086. msg = "unknown module type";
  1087. break;
  1088. case LDR_NOLOAD:
  1089. msg = "loader failed";
  1090. break;
  1091. case LDR_ONCEONLY:
  1092. msg = "already loaded";
  1093. type = X_INFO;
  1094. break;
  1095. case LDR_NOPORTOPEN:
  1096. msg = "port open failed";
  1097. break;
  1098. case LDR_NOHARDWARE:
  1099. msg = "no hardware found";
  1100. break;
  1101. case LDR_MISMATCH:
  1102. msg = "module requirement mismatch";
  1103. break;
  1104. case LDR_BADUSAGE:
  1105. msg = "invalid argument(s) to LoadModule()";
  1106. break;
  1107. case LDR_INVALID:
  1108. msg = "invalid module";
  1109. break;
  1110. case LDR_BADOS:
  1111. msg = "module doesn't support this OS";
  1112. break;
  1113. case LDR_MODSPECIFIC:
  1114. msg = "module-specific error";
  1115. break;
  1116. default:
  1117. msg = "unknown error";
  1118. }
  1119. if (name)
  1120. xf86Msg(type, "%s: Failed to load module \"%s\" (%s, %d)\n",
  1121. name, modname, msg, errmin);
  1122. else
  1123. xf86Msg(type, "Failed to load module \"%s\" (%s, %d)\n",
  1124. modname, msg, errmin);
  1125. }
  1126. /* Given a module path or file name, return the module's canonical name */
  1127. static char *
  1128. LoaderGetCanonicalName(const char *modname, PatternPtr patterns)
  1129. {
  1130. char *str;
  1131. const char *s;
  1132. int len;
  1133. PatternPtr p;
  1134. regmatch_t match[2];
  1135. /* Strip off any leading path */
  1136. s = strrchr(modname, '/');
  1137. if (s == NULL)
  1138. s = modname;
  1139. else
  1140. s++;
  1141. /* Find the first regex that is matched */
  1142. for (p = patterns; p->pattern; p++)
  1143. if (regexec(&p->rex, s, 2, match, 0) == 0 && match[1].rm_so != -1) {
  1144. len = match[1].rm_eo - match[1].rm_so;
  1145. str = malloc(len + 1);
  1146. if (!str)
  1147. return NULL;
  1148. strncpy(str, s + match[1].rm_so, len);
  1149. str[len] = '\0';
  1150. return str;
  1151. }
  1152. /* If there is no match, return the whole name minus the leading path */
  1153. return strdup(s);
  1154. }
  1155. /*
  1156. * Return the module version information.
  1157. */
  1158. unsigned long
  1159. LoaderGetModuleVersion(ModuleDescPtr mod)
  1160. {
  1161. if (!mod || mod == (ModuleDescPtr) 1 || !mod->VersionInfo)
  1162. return 0;
  1163. return MODULE_VERSION_NUMERIC(mod->VersionInfo->majorversion,
  1164. mod->VersionInfo->minorversion,
  1165. mod->VersionInfo->patchlevel);
  1166. }