~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/loader/loadmod.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

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