2 * Copyright 1995-1998 by Metro Link, Inc.
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.
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.
23 * Copyright (c) 1997-2002 by The XFree86 Project, Inc.
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:
32 * The above copyright notice and this permission notice shall be included in
33 * all copies or substantial portions of the Software.
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.
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).
49 #ifdef HAVE_XORG_CONFIG_H
50 #include <xorg-config.h>
54 /* For stat() and related stuff */
55 #define NO_OSLIB_PROTOTYPES
56 #include "xf86_OSlib.h"
57 #define LOADERDECLARATIONS
58 #include "loaderProcs.h"
62 #include "xf86Xinput.h"
64 #include "xf86Optrec.h"
66 #include <sys/types.h>
71 typedef struct _pattern
{
74 } PatternRec
, *PatternPtr
;
76 /* Prototypes for static functions */
77 static char *FindModule(const char *, const char *, const char **, PatternPtr
);
78 static Bool
CheckVersion(const char *, XF86ModuleVersionInfo
*,
79 const XF86ModReqInfo
*);
80 static void UnloadModuleOrDriver(ModuleDescPtr mod
);
81 static char *LoaderGetCanonicalName(const char *, PatternPtr
);
82 static void RemoveChild(ModuleDescPtr
);
83 static ModuleDescPtr
doLoadModule(const char *, const char *, const char **,
84 const char **, pointer
,
85 const XF86ModReqInfo
*, int *, int *);
87 const ModuleVersions LoaderVersionInfo
= {
92 ABI_EXTENSION_VERSION
,
96 static int ModuleDuplicated
[] = { };
99 FreeStringList(char **paths
)
106 for (p
= paths
; *p
; p
++)
112 static char **defaultPathList
= NULL
;
115 PathIsAbsolute(const char *path
)
121 * Convert a comma-separated path into a NULL-terminated array of path
122 * elements, rejecting any that are not full absolute paths, and appending
123 * a '/' when it isn't already present.
126 InitPathList(const char *path
)
128 char *fullpath
= NULL
;
130 char **list
= NULL
, **save
= NULL
;
136 return defaultPathList
;
138 fullpath
= strdup(path
);
141 elem
= strtok(fullpath
, ",");
143 if (PathIsAbsolute(elem
)) {
145 addslash
= (elem
[len
- 1] != '/');
149 list
= realloc(list
, (n
+ 2) * sizeof(char *));
153 FreeStringList(save
);
158 list
[n
] = malloc(len
+ 1);
160 FreeStringList(list
);
164 strcpy(list
[n
], elem
);
166 list
[n
][len
- 1] = '/';
171 elem
= strtok(NULL
, ",");
180 FreePathList(char **pathlist
)
182 if (pathlist
&& pathlist
!= defaultPathList
)
183 FreeStringList(pathlist
);
187 LoaderSetPath(const char *path
)
192 defaultPathList
= InitPathList(path
);
195 /* Standard set of module subdirectories to search, in order of preference */
196 static const char *stdSubdirs
[] = {
207 * Standard set of module name patterns to check, in order of preference
208 * These are regular expressions (suitable for use with POSIX regex(3)).
210 * This list assumes that you're an ELFish platform and therefore your
211 * shared libraries are named something.so. If we're ever nuts enough
212 * to port this DDX to, say, Darwin, we'll need to fix this.
214 static PatternRec stdPatterns
[] = {
216 {"^cyg(.*)\\.dll$",},
217 {"(.*)_drv\\.dll$",},
228 InitPatterns(const char **patternlist
)
232 PatternPtr patterns
= NULL
;
234 static int firstTime
= 1;
238 /* precompile stdPatterns */
240 for (p
= stdPatterns
; p
->pattern
; p
++)
241 if ((e
= regcomp(&p
->rex
, p
->pattern
, REG_EXTENDED
)) != 0) {
242 regerror(e
, &p
->rex
, errmsg
, sizeof(errmsg
));
243 FatalError("InitPatterns: regcomp error for `%s': %s\n",
249 for (i
= 0, s
= patternlist
; *s
; i
++, s
++)
250 if (*s
== DEFAULT_LIST
)
251 i
+= sizeof(stdPatterns
) / sizeof(stdPatterns
[0]) - 1 - 1;
252 patterns
= malloc((i
+ 1) * sizeof(PatternRec
));
256 for (i
= 0, s
= patternlist
; *s
; i
++, s
++)
257 if (*s
!= DEFAULT_LIST
) {
260 if ((e
= regcomp(&p
->rex
, p
->pattern
, REG_EXTENDED
)) != 0) {
261 regerror(e
, &p
->rex
, errmsg
, sizeof(errmsg
));
262 ErrorF("InitPatterns: regcomp error for `%s': %s\n",
268 for (p
= stdPatterns
; p
->pattern
; p
++, i
++)
270 if (p
!= stdPatterns
)
273 patterns
[i
].pattern
= NULL
;
276 patterns
= stdPatterns
;
281 FreePatterns(PatternPtr patterns
)
283 if (patterns
&& patterns
!= stdPatterns
)
288 InitSubdirs(const char **subdirlist
)
291 const char **tmp_subdirlist
= NULL
;
292 char **subdirs
= NULL
;
293 const char **s
, **stmp
= NULL
;
299 if (subdirlist
== NULL
) {
300 subdirlist
= tmp_subdirlist
= malloc(2 * sizeof(char *));
301 if (subdirlist
== NULL
)
303 subdirlist
[0] = DEFAULT_LIST
;
304 subdirlist
[1] = NULL
;
307 LoaderGetOS(&osname
, NULL
, NULL
, NULL
);
308 oslen
= strlen(osname
);
311 /* Count number of entries and check for invalid paths */
312 for (i
= 0, s
= subdirlist
; *s
; i
++, s
++) {
313 if (*s
== DEFAULT_LIST
) {
314 i
+= sizeof(stdSubdirs
) / sizeof(stdSubdirs
[0]) - 1 - 1;
318 * Path validity check. Don't allow absolute paths, or
319 * paths containing "..". To catch absolute paths on
320 * platforms that use driver letters, don't allow the ':'
321 * character to appear at all.
323 if (**s
== '/' || **s
== '\\' || strchr(*s
, ':') ||
325 xf86Msg(X_ERROR
, "InitSubdirs: Bad subdir: \"%s\"\n", *s
);
326 free(tmp_subdirlist
);
331 subdirs
= malloc((i
* 2 + 1) * sizeof(char *));
333 free(tmp_subdirlist
);
340 if (*s
== DEFAULT_LIST
) {
341 /* Divert to the default list */
347 if (**s
&& (*s
)[len
- 1] != '/') {
354 if (!(subdirs
[i
] = malloc(len
))) {
358 free(tmp_subdirlist
);
361 /* tack on the OS name */
362 sprintf(subdirs
[i
], "%s%s%s/", *s
, slash
, osname
);
365 subdirs
[i
] = strdup(*s
);
368 if (indefault
&& !s
) {
369 /* revert back to the main list */
376 free(tmp_subdirlist
);
377 return (const char **) subdirs
;
381 FreeSubdirs(const char **subdirs
)
386 for (s
= subdirs
; *s
; s
++)
393 FindModuleInSubdir(const char *dirpath
, const char *module
)
395 struct dirent
*direntry
= NULL
;
397 char *ret
= NULL
, tmpBuf
[PATH_MAX
];
398 struct stat stat_buf
;
400 dir
= opendir(dirpath
);
404 while ((direntry
= readdir(dir
))) {
405 if (direntry
->d_name
[0] == '.')
407 snprintf(tmpBuf
, PATH_MAX
, "%s%s/", dirpath
, direntry
->d_name
);
408 /* the stat with the appended / fails for normal files,
409 and works for sub dirs fine, looks a bit strange in strace
410 but does seem to work */
411 if ((stat(tmpBuf
, &stat_buf
) == 0) && S_ISDIR(stat_buf
.st_mode
)) {
412 if ((ret
= FindModuleInSubdir(tmpBuf
, module
)))
418 snprintf(tmpBuf
, PATH_MAX
, "cyg%s.dll", module
);
420 snprintf(tmpBuf
, PATH_MAX
, "lib%s.so", module
);
422 if (strcmp(direntry
->d_name
, tmpBuf
) == 0) {
423 if (asprintf(&ret
, "%s%s", dirpath
, tmpBuf
) == -1)
429 snprintf(tmpBuf
, PATH_MAX
, "%s_drv.dll", module
);
431 snprintf(tmpBuf
, PATH_MAX
, "%s_drv.so", module
);
433 if (strcmp(direntry
->d_name
, tmpBuf
) == 0) {
434 if (asprintf(&ret
, "%s%s", dirpath
, tmpBuf
) == -1)
440 snprintf(tmpBuf
, PATH_MAX
, "%s.dll", module
);
442 snprintf(tmpBuf
, PATH_MAX
, "%s.so", module
);
444 if (strcmp(direntry
->d_name
, tmpBuf
) == 0) {
445 if (asprintf(&ret
, "%s%s", dirpath
, tmpBuf
) == -1)
456 FindModule(const char *module
, const char *dirname
, const char **subdirlist
,
459 char buf
[PATH_MAX
+ 1];
461 const char **subdirs
= NULL
;
464 if (strlen(dirname
) > PATH_MAX
)
467 subdirs
= InitSubdirs(subdirlist
);
471 for (s
= subdirs
; *s
; s
++) {
472 if ((strlen(dirname
) + strlen(*s
)) > PATH_MAX
)
474 strcpy(buf
, dirname
);
476 if ((name
= FindModuleInSubdir(buf
, module
)))
480 FreeSubdirs(subdirs
);
486 LoaderListDirs(const char **subdirlist
, const char **patternlist
)
488 char buf
[PATH_MAX
+ 1];
491 const char **subdirs
;
498 struct stat stat_buf
;
501 char **listing
= NULL
;
506 if (!(pathlist
= InitPathList(NULL
)))
508 if (!(subdirs
= InitSubdirs(subdirlist
)))
510 if (!(patterns
= InitPatterns(patternlist
)))
513 for (elem
= pathlist
; *elem
; elem
++) {
514 for (s
= subdirs
; *s
; s
++) {
515 if ((dirlen
= strlen(*elem
) + strlen(*s
)) > PATH_MAX
)
520 if (stat(buf
, &stat_buf
) == 0 && S_ISDIR(stat_buf
.st_mode
) &&
521 (d
= opendir(buf
))) {
522 if (buf
[dirlen
- 1] != '/') {
526 while ((dp
= readdir(d
))) {
527 if (dirlen
+ strlen(dp
->d_name
) > PATH_MAX
)
529 strcpy(fp
, dp
->d_name
);
530 if (!(stat(buf
, &stat_buf
) == 0 &&
531 S_ISREG(stat_buf
.st_mode
)))
533 for (p
= patterns
; p
->pattern
; p
++) {
534 if (regexec(&p
->rex
, dp
->d_name
, 2, match
, 0) == 0 &&
535 match
[1].rm_so
!= -1) {
536 len
= match
[1].rm_eo
- match
[1].rm_so
;
538 listing
= realloc(listing
,
539 (n
+ 2) * sizeof(char *));
543 FreeStringList(save
);
548 listing
[n
] = malloc(len
+ 1);
550 FreeStringList(listing
);
554 strncpy(listing
[n
], dp
->d_name
+ match
[1].rm_so
,
556 listing
[n
][len
] = '\0';
571 FreePatterns(patterns
);
572 FreeSubdirs(subdirs
);
573 FreePathList(pathlist
);
578 LoaderFreeDirList(char **list
)
580 FreeStringList(list
);
584 CheckVersion(const char *module
, XF86ModuleVersionInfo
* data
,
585 const XF86ModReqInfo
* req
)
589 long ver
= data
->xf86version
;
592 xf86Msg(X_INFO
, "Module %s: vendor=\"%s\"\n",
593 data
->modname
? data
->modname
: "UNKNOWN!",
594 data
->vendor
? data
->vendor
: "UNKNOWN!");
596 /* Check for the different scheme used in XFree86 4.0.x releases:
597 * ((((((((major << 7) | minor) << 7) | subminor) << 5) | beta) << 5) | alpha)
598 * Since it wasn't used in 4.1.0 or later, limit to versions in the 4.0.x
599 * range, which limits the overlap with the new version scheme to conflicts
600 * with 6.71.8.764 through 6.72.39.934.
602 if ((ver
> (4 << 24)) && (ver
< ((4 << 24) + (1 << 17)))) {
603 /* 4.0.x and earlier */
604 verstr
[1] = verstr
[3] = 0;
605 verstr
[2] = (ver
& 0x1f) ? (ver
& 0x1f) + 'a' - 1 : 0;
607 verstr
[0] = (ver
& 0x1f) ? (ver
& 0x1f) + 'A' - 1 : 0;
609 vercode
[2] = ver
& 0x7f;
611 vercode
[1] = ver
& 0x7f;
614 xf86ErrorF("\tcompiled for %d.%d", vercode
[0], vercode
[1]);
616 xf86ErrorF(".%d", vercode
[2]);
617 xf86ErrorF("%s%s, module version = %d.%d.%d\n", verstr
, verstr
+ 2,
618 data
->majorversion
, data
->minorversion
, data
->patchlevel
);
621 vercode
[0] = ver
/ 10000000;
622 vercode
[1] = (ver
/ 100000) % 100;
623 vercode
[2] = (ver
/ 1000) % 100;
624 vercode
[3] = ver
% 1000;
625 xf86ErrorF("\tcompiled for %d.%d.%d", vercode
[0], vercode
[1],
628 xf86ErrorF(".%d", vercode
[3]);
629 xf86ErrorF(", module version = %d.%d.%d\n", data
->majorversion
,
630 data
->minorversion
, data
->patchlevel
);
633 if (data
->moduleclass
)
634 xf86ErrorFVerb(2, "\tModule class: %s\n", data
->moduleclass
);
637 if (data
->abiclass
) {
641 if (!strcmp(data
->abiclass
, ABI_CLASS_ANSIC
))
642 ver
= LoaderVersionInfo
.ansicVersion
;
643 else if (!strcmp(data
->abiclass
, ABI_CLASS_VIDEODRV
))
644 ver
= LoaderVersionInfo
.videodrvVersion
;
645 else if (!strcmp(data
->abiclass
, ABI_CLASS_XINPUT
))
646 ver
= LoaderVersionInfo
.xinputVersion
;
647 else if (!strcmp(data
->abiclass
, ABI_CLASS_EXTENSION
))
648 ver
= LoaderVersionInfo
.extensionVersion
;
649 else if (!strcmp(data
->abiclass
, ABI_CLASS_FONT
))
650 ver
= LoaderVersionInfo
.fontVersion
;
652 abimaj
= GET_ABI_MAJOR(data
->abiversion
);
653 abimin
= GET_ABI_MINOR(data
->abiversion
);
654 xf86ErrorFVerb(2, "\tABI class: %s, version %d.%d\n",
655 data
->abiclass
, abimaj
, abimin
);
657 vermaj
= GET_ABI_MAJOR(ver
);
658 vermin
= GET_ABI_MINOR(ver
);
659 if (abimaj
!= vermaj
) {
660 if (LoaderOptions
& LDR_OPT_ABI_MISMATCH_NONFATAL
)
664 xf86MsgVerb(errtype
, 0,
665 "module ABI major version (%d) doesn't"
666 " match the server's version (%d)\n",
668 if (!(LoaderOptions
& LDR_OPT_ABI_MISMATCH_NONFATAL
))
671 else if (abimin
> vermin
) {
672 if (LoaderOptions
& LDR_OPT_ABI_MISMATCH_NONFATAL
)
676 xf86MsgVerb(errtype
, 0,
677 "module ABI minor version (%d) is "
678 "newer than the server's version "
679 "(%d)\n", abimin
, vermin
);
680 if (!(LoaderOptions
& LDR_OPT_ABI_MISMATCH_NONFATAL
))
686 /* Check against requirements that the caller has specified */
688 if (req
->majorversion
!= MAJOR_UNSPEC
) {
689 if (data
->majorversion
!= req
->majorversion
) {
690 xf86MsgVerb(X_WARNING
, 2, "module major version (%d) "
691 "doesn't match required major version (%d)\n",
692 data
->majorversion
, req
->majorversion
);
695 else if (req
->minorversion
!= MINOR_UNSPEC
) {
696 if (data
->minorversion
< req
->minorversion
) {
697 xf86MsgVerb(X_WARNING
, 2, "module minor version (%d) "
698 "is less than the required minor version (%d)\n",
699 data
->minorversion
, req
->minorversion
);
702 else if (data
->minorversion
== req
->minorversion
&&
703 req
->patchlevel
!= PATCH_UNSPEC
) {
704 if (data
->patchlevel
< req
->patchlevel
) {
705 xf86MsgVerb(X_WARNING
, 2, "module patch level (%d) "
706 "is less than the required patch level (%d)\n",
707 data
->patchlevel
, req
->patchlevel
);
713 if (req
->moduleclass
) {
714 if (!data
->moduleclass
||
715 strcmp(req
->moduleclass
, data
->moduleclass
)) {
716 xf86MsgVerb(X_WARNING
, 2, "Module class (%s) doesn't match "
717 "the required class (%s)\n",
718 data
->moduleclass
? data
->moduleclass
: "<NONE>",
723 else if (req
->abiclass
!= ABI_CLASS_NONE
) {
724 if (!data
->abiclass
|| strcmp(req
->abiclass
, data
->abiclass
)) {
725 xf86MsgVerb(X_WARNING
, 2, "ABI class (%s) doesn't match the "
726 "required ABI class (%s)\n",
727 data
->abiclass
? data
->abiclass
: "<NONE>",
732 if ((req
->abiclass
!= ABI_CLASS_NONE
) &&
733 req
->abiversion
!= ABI_VERS_UNSPEC
) {
734 int reqmaj
, reqmin
, maj
, min
;
736 reqmaj
= GET_ABI_MAJOR(req
->abiversion
);
737 reqmin
= GET_ABI_MINOR(req
->abiversion
);
738 maj
= GET_ABI_MAJOR(data
->abiversion
);
739 min
= GET_ABI_MINOR(data
->abiversion
);
741 xf86MsgVerb(X_WARNING
, 2, "ABI major version (%d) doesn't "
742 "match the required ABI major version (%d)\n",
746 /* XXX Maybe this should be the other way around? */
748 xf86MsgVerb(X_WARNING
, 2, "module ABI minor version (%d) "
749 "is newer than that available (%d)\n", min
, reqmin
);
758 AddSibling(ModuleDescPtr head
, ModuleDescPtr
new)
765 LoadSubModule(pointer _parent
, const char *module
,
766 const char **subdirlist
, const char **patternlist
,
767 pointer options
, const XF86ModReqInfo
* modreq
,
768 int *errmaj
, int *errmin
)
770 ModuleDescPtr submod
;
771 ModuleDescPtr parent
= (ModuleDescPtr
) _parent
;
773 xf86MsgVerb(X_INFO
, 3, "Loading sub module \"%s\"\n", module
);
775 if (PathIsAbsolute(module
)) {
777 "LoadSubModule: Absolute module path not permitted: \"%s\"\n",
780 *errmaj
= LDR_BADUSAGE
;
786 submod
= doLoadModule(module
, NULL
, subdirlist
, patternlist
, options
,
787 modreq
, errmaj
, errmin
);
788 if (submod
&& submod
!= (ModuleDescPtr
) 1) {
789 parent
->child
= AddSibling(parent
->child
, submod
);
790 submod
->parent
= parent
;
796 NewModuleDesc(const char *name
)
798 ModuleDescPtr mdp
= calloc(1, sizeof(ModuleDesc
));
801 mdp
->name
= xstrdup(name
);
807 DuplicateModule(ModuleDescPtr mod
, ModuleDescPtr parent
)
814 ret
= NewModuleDesc(mod
->name
);
818 ret
->handle
= mod
->handle
;
820 ret
->SetupProc
= mod
->SetupProc
;
821 ret
->TearDownProc
= mod
->TearDownProc
;
822 ret
->TearDownData
= ModuleDuplicated
;
823 ret
->child
= DuplicateModule(mod
->child
, ret
);
824 ret
->sib
= DuplicateModule(mod
->sib
, parent
);
825 ret
->parent
= parent
;
826 ret
->VersionInfo
= mod
->VersionInfo
;
827 ret
->path
= strdup(mod
->path
);
832 static const char *compiled_in_modules
[] = {
845 doLoadModule(const char *module
, const char *path
, const char **subdirlist
,
846 const char **patternlist
, pointer options
,
847 const XF86ModReqInfo
* modreq
, int *errmaj
, int *errmin
)
849 XF86ModuleData
*initdata
= NULL
;
850 char **pathlist
= NULL
;
853 char **path_elem
= NULL
;
855 ModuleDescPtr ret
= NULL
;
856 PatternPtr patterns
= NULL
;
857 int noncanonical
= 0;
861 xf86MsgVerb(X_INFO
, 3, "LoadModule: \"%s\"", module
);
863 patterns
= InitPatterns(patternlist
);
864 name
= LoaderGetCanonicalName(module
, patterns
);
865 noncanonical
= (name
&& strcmp(module
, name
) != 0);
867 xf86ErrorFVerb(3, " (%s)\n", name
);
868 xf86MsgVerb(X_WARNING
, 1,
869 "LoadModule: given non-canonical module name \"%s\"\n",
874 xf86ErrorFVerb(3, "\n");
878 for (cim
= compiled_in_modules
; *cim
; cim
++)
879 if (!strcmp(m
, *cim
)) {
880 xf86MsgVerb(X_INFO
, 3, "Module \"%s\" already built-in\n", m
);
881 ret
= (ModuleDescPtr
) 1;
882 goto LoadModule_exit
;
887 *errmaj
= LDR_BADUSAGE
;
890 goto LoadModule_fail
;
892 ret
= NewModuleDesc(name
);
898 goto LoadModule_fail
;
901 pathlist
= InitPathList(path
);
903 /* This could be a malloc failure too */
905 *errmaj
= LDR_BADUSAGE
;
908 goto LoadModule_fail
;
912 * if the module name is not a full pathname, we need to
913 * check the elements in the path
915 if (PathIsAbsolute(module
))
916 found
= xstrdup(module
);
917 path_elem
= pathlist
;
918 while (!found
&& *path_elem
!= NULL
) {
919 found
= FindModule(m
, *path_elem
, subdirlist
, patterns
);
922 * When the module name isn't the canonical name, search for the
923 * former if no match was found for the latter.
925 if (!*path_elem
&& m
== name
) {
926 path_elem
= pathlist
;
932 * did we find the module?
935 xf86Msg(X_WARNING
, "Warning, couldn't open module %s\n", module
);
940 goto LoadModule_fail
;
942 ret
->handle
= LoaderOpen(found
, errmaj
, errmin
);
943 if (ret
->handle
== NULL
)
944 goto LoadModule_fail
;
945 ret
->path
= strdup(found
);
947 /* drop any explicit suffix from the module name */
948 p
= strchr(name
, '.');
953 * now check if the special data object <modulename>ModuleData is
956 if (asprintf(&p
, "%sModuleData", name
) == -1) {
962 goto LoadModule_fail
;
964 initdata
= LoaderSymbolFromModule(ret
->handle
, p
);
966 ModuleSetupProc setup
;
967 ModuleTearDownProc teardown
;
968 XF86ModuleVersionInfo
*vers
;
970 vers
= initdata
->vers
;
971 setup
= initdata
->setup
;
972 teardown
= initdata
->teardown
;
975 if (!CheckVersion(module
, vers
, modreq
)) {
977 *errmaj
= LDR_MISMATCH
;
980 goto LoadModule_fail
;
985 "LoadModule: Module %s does not supply"
986 " version information\n", module
);
988 *errmaj
= LDR_INVALID
;
991 goto LoadModule_fail
;
994 ret
->SetupProc
= setup
;
996 ret
->TearDownProc
= teardown
;
997 ret
->VersionInfo
= vers
;
1000 /* no initdata, fail the load */
1001 xf86Msg(X_ERROR
, "LoadModule: Module %s does not have a %s "
1002 "data object.\n", module
, p
);
1004 *errmaj
= LDR_INVALID
;
1007 goto LoadModule_fail
;
1009 if (ret
->SetupProc
) {
1010 ret
->TearDownData
= ret
->SetupProc(ret
, options
, errmaj
, errmin
);
1011 if (!ret
->TearDownData
) {
1012 goto LoadModule_fail
;
1016 xf86Msg(X_WARNING
, "Module Options present, but no SetupProc "
1017 "available for %s\n", module
);
1019 goto LoadModule_exit
;
1026 FreePathList(pathlist
);
1027 FreePatterns(patterns
);
1036 * LoadModule: load a module
1038 * module The module name. Normally this is not a filename but the
1039 * module's "canonical name. A full pathname is, however,
1041 * path A comma separated list of module directories.
1042 * subdirlist A NULL terminated list of subdirectories to search. When
1043 * NULL, the default "stdSubdirs" list is used. The default
1044 * list is also substituted for entries with value DEFAULT_LIST.
1045 * patternlist A NULL terminated list of regular expressions used to find
1046 * module filenames. Each regex should contain exactly one
1047 * subexpression that corresponds to the canonical module name.
1048 * When NULL, the default "stdPatterns" list is used. The
1049 * default list is also substituted for entries with value
1051 * options A NULL terminated list of Options that are passed to the
1052 * module's SetupProc function.
1053 * modreq An optional XF86ModReqInfo* containing
1054 * version/ABI/vendor-ABI requirements to check for when
1055 * loading the module. The following fields of the
1056 * XF86ModReqInfo struct are checked:
1057 * majorversion - must match the module's majorversion exactly
1058 * minorversion - the module's minorversion must be >= this
1059 * patchlevel - the module's minorversion.patchlevel must be
1060 * >= this. Patchlevel is ignored when
1061 * minorversion is not set.
1062 * abiclass - (string) must match the module's abiclass
1063 * abiversion - must be consistent with the module's
1064 * abiversion (major equal, minor no older)
1065 * moduleclass - string must match the module's moduleclass
1067 * "don't care" values are ~0 for numbers, and NULL for strings
1068 * errmaj Major error return.
1069 * errmin Minor error return.
1073 LoadModule(const char *module
, const char *path
, const char **subdirlist
,
1074 const char **patternlist
, pointer options
,
1075 const XF86ModReqInfo
* modreq
, int *errmaj
, int *errmin
)
1077 return doLoadModule(module
, path
, subdirlist
, patternlist
, options
,
1078 modreq
, errmaj
, errmin
);
1082 UnloadModule(pointer mod
)
1084 UnloadModuleOrDriver((ModuleDescPtr
) mod
);
1088 UnloadModuleOrDriver(ModuleDescPtr mod
)
1090 if (mod
== (ModuleDescPtr
) 1)
1093 if (mod
== NULL
|| mod
->name
== NULL
)
1097 LogMessageVerbSigSafe(X_INFO
, 3, "UnloadSubModule: \"%s\"\n",
1100 LogMessageVerbSigSafe(X_INFO
, 3, "UnloadModule: \"%s\"\n", mod
->name
);
1102 if (mod
->TearDownData
!= ModuleDuplicated
) {
1103 if ((mod
->TearDownProc
) && (mod
->TearDownData
))
1104 mod
->TearDownProc(mod
->TearDownData
);
1105 LoaderUnload(mod
->name
, mod
->handle
);
1109 UnloadModuleOrDriver(mod
->child
);
1111 UnloadModuleOrDriver(mod
->sib
);
1118 UnloadSubModule(pointer _mod
)
1120 ModuleDescPtr mod
= (ModuleDescPtr
) _mod
;
1122 /* Some drivers are calling us on built-in submodules, ignore them */
1123 if (mod
== (ModuleDescPtr
) 1)
1126 UnloadModuleOrDriver(mod
);
1130 RemoveChild(ModuleDescPtr child
)
1133 ModuleDescPtr prevsib
;
1134 ModuleDescPtr parent
;
1139 parent
= child
->parent
;
1140 if (parent
->child
== child
) {
1141 parent
->child
= child
->sib
;
1145 prevsib
= parent
->child
;
1147 while (mdp
&& mdp
!= child
) {
1152 prevsib
->sib
= child
->sib
;
1158 LoaderErrorMsg(const char *name
, const char *modname
, int errmaj
, int errmin
)
1161 MessageType type
= X_ERROR
;
1168 msg
= "out of memory";
1171 msg
= "module does not exist";
1174 msg
= "a required submodule could not be loaded";
1177 msg
= "too many modules";
1180 msg
= "open failed";
1183 msg
= "unknown module type";
1186 msg
= "loader failed";
1189 msg
= "already loaded";
1192 case LDR_NOPORTOPEN
:
1193 msg
= "port open failed";
1195 case LDR_NOHARDWARE
:
1196 msg
= "no hardware found";
1199 msg
= "module requirement mismatch";
1202 msg
= "invalid argument(s) to LoadModule()";
1205 msg
= "invalid module";
1208 msg
= "module doesn't support this OS";
1210 case LDR_MODSPECIFIC
:
1211 msg
= "module-specific error";
1214 msg
= "unknown error";
1217 xf86Msg(type
, "%s: Failed to load module \"%s\" (%s, %d)\n",
1218 name
, modname
, msg
, errmin
);
1220 xf86Msg(type
, "Failed to load module \"%s\" (%s, %d)\n",
1221 modname
, msg
, errmin
);
1224 /* Given a module path or file name, return the module's canonical name */
1226 LoaderGetCanonicalName(const char *modname
, PatternPtr patterns
)
1232 regmatch_t match
[2];
1234 /* Strip off any leading path */
1235 s
= strrchr(modname
, '/');
1241 /* Find the first regex that is matched */
1242 for (p
= patterns
; p
->pattern
; p
++)
1243 if (regexec(&p
->rex
, s
, 2, match
, 0) == 0 && match
[1].rm_so
!= -1) {
1244 len
= match
[1].rm_eo
- match
[1].rm_so
;
1245 str
= malloc(len
+ 1);
1248 strncpy(str
, s
+ match
[1].rm_so
, len
);
1253 /* If there is no match, return the whole name minus the leading path */
1258 * Return the module version information.
1261 LoaderGetModuleVersion(ModuleDescPtr mod
)
1263 if (!mod
|| mod
== (ModuleDescPtr
) 1 || !mod
->VersionInfo
)
1266 return MODULE_VERSION_NUMERIC(mod
->VersionInfo
->majorversion
,
1267 mod
->VersionInfo
->minorversion
,
1268 mod
->VersionInfo
->patchlevel
);