source: trunk/kLdr/kLdrDyldFind.c@ 2868

Last change on this file since 2868 was 2868, checked in by bird, 19 years ago

Did the remaining search bit (I hope).

  • Property svn:keywords set to Id
File size: 32.4 KB
RevLine 
[2834]1/* $Id: kLdrDyldFind.c 2868 2006-11-11 12:48:54Z bird $ */
[2833]2/** @file
3 *
4 * kLdr - The Dynamic Loader, File Searching Methods.
5 *
6 * Copyright (c) 2006 knut st. osmundsen <bird-kbuild-src@anduin.net>
7 *
8 *
9 * This file is part of kLdr.
10 *
11 * kLdr is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * kLdr is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kLdr; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27
28
29/*******************************************************************************
30* Header Files *
31*******************************************************************************/
[2867]32#ifdef __OS2__
33# define INCL_BASE
34# define INCL_ERRORS
35# include <os2.h>
36# ifndef LIBPATHSTRICT
37# define LIBPATHSTRICT 3
38# endif
39 extern APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
40# define QHINF_EXEINFO 1 /* NE exeinfo. */
41# define QHINF_READRSRCTBL 2 /* Reads from the resource table. */
42# define QHINF_READFILE 3 /* Reads from the executable file. */
43# define QHINF_LIBPATHLENGTH 4 /* Gets the libpath length. */
44# define QHINF_LIBPATH 5 /* Gets the entire libpath. */
45# define QHINF_FIXENTRY 6 /* NE only */
46# define QHINF_STE 7 /* NE only */
47# define QHINF_MAPSEL 8 /* NE only */
48
49#elif defined(__WIN__)
50# include <Windows.h>
51#endif
52
[2833]53#include <kLdr.h>
54#include "kLdrHlp.h"
55#include "kLdrInternal.h"
56
[2867]57/*******************************************************************************
58* Defined Constants And Macros *
59*******************************************************************************/
60/** @def KLDRDYLDFIND_STRICT
61 * Define KLDRDYLDFIND_STRICT to enabled strict checks in kLdrDyldFind. */
62#define KLDRDYLDFIND_STRICT 1
[2833]63
[2867]64/** @def KLDRDYLDFIND_ASSERT
65 * Assert that an expression is true when KLDRDYLDFIND_STRICT is defined.
66 */
67#ifdef KLDRDYLDFIND_STRICT
68# define KLDRDYLDFIND_ASSERT(expr) kldrHlpAssert(expr)
69#else
70# define KLDRDYLDFIND_ASSERT(expr) do {} while (0)
71#endif
72
73
74/*******************************************************************************
[2868]75* Structures and Typedefs *
76*******************************************************************************/
77/**
78 * Search arguments.
79 * This avoids a bunch of unnecessary string lengths and calculations.
80 */
81typedef struct KLDRDYLDFINDARGS
82{
83 const char *pszName;
84 size_t cchName;
85
86 const char *pszPrefix;
87 size_t cchPrefix;
88
89 const char *pszSuffix;
90 size_t cchSuffix;
91
92 size_t cchMaxLength;
93
94 KLDRDYLDSEARCH enmSearch;
95 uint32_t fFlags;
96 PPKLDRRDR ppRdr;
97} KLDRDYLDFINDARGS, *PKLDRDYLDFINDARGS;
98
99typedef const KLDRDYLDFINDARGS *PCKLDRDYLDFINDARGS;
100
101
102/*******************************************************************************
[2867]103* Global Variables *
104*******************************************************************************/
105/** @name The kLdr search method parameters.
106 * @{ */
107/** The kLdr DLL search path.
108 * During initialization the KLDR_LIBRARY_PATH env.var. and the path in the
109 * executable stub is appended. Both ';' and ':' can be used as separators.
110 */
111char kLdrDyldPath[8192];
112/** The kLdr application directory.
113 * This is initialized when the executable is 'loaded' or by a kLdr user.
114 */
115char kLdrDyldAppDir[260];
116/** The default kLdr DLL prefix.
117 * This is initialized with the KLDR_DEF_PREFIX env.var. + the prefix in the executable stub.
118 */
119char kLdrDyldDefPrefix[16];
120/** The default kLdr DLL suffix.
121 * This is initialized with the KLDR_DEF_SUFFIX env.var. + the prefix in the executable stub.
122 */
123char kLdrDyldDefSuffix[16];
124/** @} */
125
126
127/** @name The OS/2 search method parameters.
128 * @{
129 */
130/** The OS/2 LIBPATH.
131 * This is queried from the os2krnl on OS/2, while on other systems initialized using
132 * the KLDR_OS2_LIBPATH env.var.
133 */
134char kLdrDyldOS2Libpath[2048];
135/** The OS/2 LIBPATHSTRICT ("T" or '\0').
136 * This is queried from the os2krnl on OS/2, while on other systems initialized using
137 * the KLDR_OS2_LIBPATHSTRICT env.var.
138 */
139char kLdrDyldOS2LibpathStrict[8];
140/** The OS/2 BEGINLIBPATH.
141 * This is queried from the os2krnl on OS/2, while on other systems initialized using
142 * the KLDR_OS2_BEGINLIBPATH env.var.
143 */
144char kLdrDyldOS2BeginLibpath[2048];
145/** The OS/2 ENDLIBPATH.
146 * This is queried from the os2krnl on OS/2, while on other systems initialized using
147 * the KLDR_OS2_ENDLIBPATH env.var.
148 */
149char kLdrDyldOS2EndLibpath[2048];
150/** @} */
151
152
153/** @name The Windows search method parameters.
154 * @{ */
155/** The Windows application directory.
156 * This is initialized when the executable is 'loaded' or by a kLdr user.
157 */
158char kLdrDyldWindowsAppDir[260];
159/** The Windows system directory.
160 * This is queried from the Win32/64 subsystem on Windows, while on other systems
161 * initialized using the KLDR_WINDOWS_SYSTEM_DIR env.var.
162 */
163char kLdrDyldWindowsSystemDir[260];
164/** The Windows directory.
165 * This is queried from the Win32/64 subsystem on Windows, while on other systems
166 * initialized using the KLDR_WINDOWS_DIR env.var.
167 */
168char kLdrDyldWindowsDir[260];
169/** The Windows path.
170 * This is queried from the PATH env.var. on Windows, while on other systems
171 * initialized using the KLDR_WINDOWS_PATH env.var. and falling back on
172 * the PATH env.var. if it wasn't found.
173 */
174char kLdrDyldWindowsPath[8192];
175/** @} */
176
177
178/** @name The Common Unix search method parameters.
179 * @{
180 */
181/** The Common Unix library path.
182 * Initialized from the env.var. KLDR_UNIX_LIBRARY_PATH or LD_LIBRARY_PATH or the
183 * former wasn't found.
184 */
185char kLdrDyldUnixLibraryPath[8192];
186/** The Common Unix system library path. */
187char kLdrDyldUnixSystemLibraryPath[1024] = "/lib;/usr/lib";
188/** @} */
189
190/** @todo Deal with DT_RUNPATH and DT_RPATH. */
191/** @todo ld.so.cache? */
192
193
194/*******************************************************************************
195* Internal Functions *
196*******************************************************************************/
197static int kldrDyldFindDoSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
198 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr);
199static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr);
[2868]200static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, PCKLDRDYLDFINDARGS pArgs);
201static int kldrDyldFindEnumeratePath(const char *pszSearchPath, PCKLDRDYLDFINDARGS pArgs);
202static int kldrDyldFindGetDefaults(KLDRDYLDSEARCH *penmSearch, const char **pszPrefix, const char **pszSuffix, const char *pszName);
[2867]203
204
[2835]205/**
[2867]206 * Initializes the find paths.
207 *
208 * @returns 0 on success, non-zero on failure.
209 */
210int kldrDyldFindInit(void)
211{
212 size_t cch;
213 int rc;
214 char szTmp[sizeof(kLdrDyldDefSuffix)];
215
216 /*
217 * The kLdr search parameters.
218 */
219 rc = kldrHlpGetEnv("KLDR_LIBRARY_PATH", kLdrDyldPath, sizeof(kLdrDyldPath));
220 if (rc)
221 kLdrDyldPath[0] = '\0';
222
223 rc = kldrHlpGetEnv("KLDR_DEF_PREFIX", szTmp, sizeof(szTmp));
224 if (!rc)
225 kLdrHlpMemCopy(kLdrDyldDefPrefix, szTmp, sizeof(szTmp));
226
227 rc = kldrHlpGetEnv("KLDR_DEF_SUFFIX", szTmp, sizeof(szTmp));
228 if (!rc)
229 kLdrHlpMemCopy(kLdrDyldDefSuffix, szTmp, sizeof(szTmp));
230
231 /*
232 * The OS/2 search parameters.
233 */
234#ifdef __OS2__
235 rc = DosQueryHeaderInfo(NULLHANDLE, 0, kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath), QHINF_LIBPATH);
236 if (rc)
237 return rc;
238 rc = DosQueryExtLIBPATH(kLdrDyldOS2LibpathStrict, LIBPATHSTRICT);
239 if (rc)
240 kLdrDyldOS2LibpathStrict[0] = '\0';
241 rc = DosQueryExtLIBPATH(kLdrDyldOS2BeginLibpath, BEGIN_LIBPATH);
242 if (rc)
243 kLdrDyldOS2BeginLibpath[0] = '\0';
244 rc = DosQueryExtLIBPATH(kLdrDyldOS2EndLibpath, END_LIBPATH);
245 if (rc)
246 kLdrDyldOS2EndLibpath[0] = '\0';
247
248#else
249 kldrHlpGetEnv("KLDR_OS2_LIBPATH", kLdrDyldOS2Libpath, sizeof(kLdrDyldOS2Libpath));
250 kldrHlpGetEnv("KLDR_OS2_LIBPATHSTRICT", kLdrDyldOS2LibpathStrict, sizeof(kLdrDyldOS2LibpathStrict));
251 kldrHlpGetEnv("KLDR_OS2_BEGINLIBPATH", kLdrDyldOS2BeginLibpath, sizeof(kLdrDyldOS2BeginLibpath));
252 kldrHlpGetEnv("KLDR_OS2_ENDLIBPATH", kLdrDyldOS2EndLibpath, sizeof(kLdrDyldOS2EndLibpath));
253#endif
254
255 /*
256 * The windows search parameters.
257 */
258#if defined(__WIN__)
259 cch = GetSystemDirectory(kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
260 if (cch >= sizeof(kLdrDyldWindowsSystemDir))
261 return (rc = GetLastError()) ? rc : -1;
262 cch = GetWindowsDirectory(kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
263 if (cch >= sizeof(kLdrDyldWindowsDir))
264 return (rc = GetLastError()) ? rc : -1;
265 kldrHlpGetEnv("PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
266#else
267 kldrHlpGetEnv("KLDR_WINDOWS_SYSTEM_DIR", kLdrDyldWindowsSystemDir, sizeof(kLdrDyldWindowsSystemDir));
268 kldrHlpGetEnv("KLDR_WINDOWS_DIR", kLdrDyldWindowsDir, sizeof(kLdrDyldWindowsDir));
269 kldrHlpGetEnv("KLDR_WINDOWS_PATH", kLdrDyldWindowsPath, sizeof(kLdrDyldWindowsPath));
270#endif
271
272 /*
273 * The Unix search parameters.
274 */
275 rc = kldrHlpGetEnv("KLDR_UNIX_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
276 if (rc)
277 kldrHlpGetEnv("LD_LIBRARY_PATH", kLdrDyldUnixLibraryPath, sizeof(kLdrDyldUnixLibraryPath));
278
279 (void)cch;
280 return 0;
281}
282
283
284/**
[2835]285 * Locates and opens a module using the specified search method.
286 *
[2867]287 * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
[2835]288 *
289 * @param pszName Partial or complete name, it's specific to the search method to determin which.
[2843]290 * @param pszPrefix Prefix than can be used when searching.
291 * @param pszSuffix Suffix than can be used when searching.
[2835]292 * @param enmSearch The file search method to apply.
293 * @param fFlags Search flags.
294 * @param ppMod Where to store the file provider instance on success.
295 */
296int kldrDyldFindNewModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
297 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
298{
[2867]299 int rc;
300 PKLDRRDR pRdr = NULL;
301
[2835]302 *ppMod = NULL;
[2867]303
304 /*
305 * If this isn't just a filename, we the caller has specified a file
306 * that should be opened directly and not a module name to be searched for.
307 */
308 if (!kldrHlpIsFilenameOnly(pszName))
309 rc = kldrDyldFindTryOpen(pszName, &pRdr);
310 else
311 rc = kldrDyldFindDoSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
312 if (!rc)
313 {
314#ifdef KLDRDYLDFIND_STRICT
315 /* Sanity check of kldrDyldFindExistingModule. */
316 if (fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE)
317 {
318 const char *pszFilename = kLdrRdrName(pRdr);
319 const size_t cchFilename = kLdrHlpStrLen(pszFilename);
320 PKLDRDYLDMOD pCur;
321 for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
322 KLDRDYLDFIND_ASSERT( pCur->pMod->cchFilename != cchFilename
323 || kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
324 }
325#endif
326
327 /*
328 * Check for matching non-global modules that should be promoted.
329 */
330 if (!(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
331 {
332 const char *pszFilename = kLdrRdrName(pRdr);
333 const size_t cchFilename = kLdrHlpStrLen(pszFilename);
334 PKLDRDYLDMOD pCur;
335 for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
336 {
337 if ( !pCur->fGlobalOrSpecific
338 && pCur->pMod->cchFilename == cchFilename
339 && !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
340 {
341 kLdrRdrClose(pRdr);
342 kldrDyldModMarkGlobal(pCur);
343 *ppMod = pCur;
344 return 0;
345 }
346 KLDRDYLDFIND_ASSERT( pCur->pMod->cchFilename != cchFilename
347 || kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename));
348 }
349 }
350
351 /*
352 * Create a new module.
353 */
[2868]354 rc = kldrDyldModCreate(pRdr, fFlags, ppMod);
[2867]355 if (rc)
356 kLdrRdrClose(pRdr);
357 }
358 return rc;
[2835]359}
360
361
362/**
[2867]363 * Searches for a file using the specified method.
364 *
365 * @returns 0 on success and *ppMod pointing to the new module.
366 * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
367 * @returns non-zero kLdr or OS specific status code on other failures.
368 * @param pszName The name.
369 * @param pszPrefix The prefix, optional.
370 * @param pszSuffix The suffix, optional.
371 * @param enmSearch The search method.
372 * @param fFlags The load/search flags.
373 * @param ppRdr Where to store the pointer to the file provider instance on success.
374 */
375static int kldrDyldFindDoSearch(const char *pszName, const char *pszPrefix, const char *pszSuffix,
376 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRRDR ppRdr)
377{
378 int rc;
[2868]379 KLDRDYLDFINDARGS Args;
[2867]380
381 /*
[2868]382 * Initialize the argument structure and resolve defaults.
[2867]383 */
[2868]384 Args.enmSearch = enmSearch;
385 Args.pszPrefix = pszPrefix;
386 Args.pszSuffix = pszSuffix;
387 rc = kldrDyldFindGetDefaults(&Args.enmSearch, &Args.pszPrefix, &Args.pszSuffix, pszName);
388 if (rc)
389 return rc;
390 Args.pszName = pszName;
391 Args.cchName = kLdrHlpStrLen(pszName);
392 Args.cchPrefix = Args.pszPrefix ? kLdrHlpStrLen(pszPrefix) : 0;
393 Args.cchSuffix = Args.pszSuffix ? kLdrHlpStrLen(pszSuffix) : 0;
394 Args.cchMaxLength = Args.cchName + Args.cchSuffix + Args.cchPrefix;
395 Args.fFlags = fFlags;
396 Args.ppRdr = ppRdr;
[2867]397
398 /*
399 * Apply the specified search method.
400 */
[2868]401/** @todo get rid of the strlen() on the various paths here! */
[2867]402 switch (enmSearch)
403 {
404 case KLDRDYLD_SEARCH_KLDR:
405 {
406 if (kLdrDyldAppDir[0] != '\0')
407 {
[2868]408 rc = kldrDyldFindTryOpenPath(kLdrDyldAppDir, kLdrHlpStrLen(kLdrDyldAppDir), &Args);
[2867]409 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
410 break;
411 }
[2868]412 rc = kldrDyldFindTryOpenPath(".", 1, &Args);
[2867]413 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
414 break;
[2868]415 rc = kldrDyldFindEnumeratePath(kLdrDyldPath, &Args);
[2867]416 break;
417 }
418
419 case KLDRDYLD_SEARCH_OS2:
420 {
[2868]421 rc = kldrDyldFindEnumeratePath(kLdrDyldOS2BeginLibpath, &Args);
[2867]422 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
423 break;
[2868]424 rc = kldrDyldFindEnumeratePath(kLdrDyldOS2Libpath, &Args);
[2867]425 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
426 break;
[2868]427 rc = kldrDyldFindEnumeratePath(kLdrDyldOS2EndLibpath, &Args);
[2867]428 break;
429 }
430
431 case KLDRDYLD_SEARCH_WINDOWS:
432 case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
433 {
[2868]434 rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsAppDir, kLdrHlpStrLen(kLdrDyldWindowsAppDir), &Args);
[2867]435 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
436 break;
437 if (enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
438 {
[2868]439 rc = kldrDyldFindTryOpenPath(".", 1, &Args);
[2867]440 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
441 break;
442 }
[2868]443 rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsSystemDir, kLdrHlpStrLen(kLdrDyldWindowsSystemDir), &Args);
[2867]444 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
445 break;
[2868]446 rc = kldrDyldFindTryOpenPath(kLdrDyldWindowsDir, kLdrHlpStrLen(kLdrDyldWindowsDir), &Args);
[2867]447 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
448 break;
449 if (enmSearch == KLDRDYLD_SEARCH_WINDOWS)
450 {
[2868]451 rc = kldrDyldFindTryOpenPath(".", 1, &Args);
[2867]452 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
453 break;
454 }
[2868]455 rc = kldrDyldFindEnumeratePath(kLdrDyldWindowsPath, &Args);
[2867]456 break;
457 }
458
459 case KLDRDYLD_SEARCH_UNIX_COMMON:
460 {
[2868]461 rc = kldrDyldFindEnumeratePath(kLdrDyldUnixLibraryPath, &Args);
[2867]462 if (rc == KLDR_ERR_MODULE_NOT_FOUND)
463 break;
[2868]464 rc = kldrDyldFindEnumeratePath(kLdrDyldUnixSystemLibraryPath, &Args);
[2867]465 break;
466 }
467
[2868]468 default: kldrHlpAssert(!"internal error"); return -1;
[2867]469 }
470 return rc;
471}
472
473
474/**
475 * Try open the specfied file.
476 *
477 * @returns 0 on success and *ppMod pointing to the new module.
478 * @returns KLDR_ERR_MODULE_NOT_FOUND if the specified file couldn't be opened.
479 * @returns non-zero kLdr or OS specific status code on other failures.
480 * @param pszFilename The filename.
481 * @param ppRdr Where to store the pointer to the new module.
482 */
483static int kldrDyldFindTryOpen(const char *pszFilename, PPKLDRRDR ppRdr)
484{
[2868]485 int rc;
486
487 /*
488 * Try open the file.
489 */
490 rc = kLdrRdrOpen(ppRdr, pszFilename);
491 if (!rc)
492 return 0;
493 /** @todo deal with return codes properly. */
494 if (rc >= KLDR_ERR_BASE && rc <= KLDR_ERR_END)
495 return rc;
496
[2867]497 return KLDR_ERR_MODULE_NOT_FOUND;
498}
499
500
501/**
502 * Composes a filename from the specified directory path,
503 * prefix (optional), name and suffix (optional, will try with and without).
504 *
505 * @param pchPath The directory path - this doesn't have to be null terminated.
506 * @param cchPath The length of the path.
[2868]507 * @param pArgs The search argument structure.
[2867]508 *
509 * @returns See kldrDyldFindTryOpen
510 */
[2868]511static int kldrDyldFindTryOpenPath(const char *pchPath, size_t cchPath, PCKLDRDYLDFINDARGS pArgs)
[2867]512{
[2868]513 static char s_szFilename[1024];
514 char *psz;
515
516 /*
517 * Limit check first.
518 */
519 if (cchPath + 1 + pArgs->cchMaxLength >= sizeof(s_szFilename))
520 {
521 KLDRDYLDFIND_ASSERT(!"too long");
522 return KLDR_ERR_MODULE_NOT_FOUND; /* ignore */
523 }
524
525 /*
526 * The directory path.
527 */
528 kLdrHlpMemCopy(s_szFilename, pchPath, cchPath);
529 psz = &s_szFilename[cchPath];
530 if (psz[-1] != '/'
531#if defined(__OS2__) || defined(__WIN__)
532 && psz[-1] != '\\'
533 && psz[-1] != ':'
534#endif
535 )
536 *psz++ = '/';
537
538 /*
539 * The name.
540 */
541 if (pArgs->cchPrefix)
542 {
543 kLdrHlpMemCopy(psz, pArgs->pszPrefix, pArgs->cchPrefix);
544 psz += pArgs->cchPrefix;
545 }
546 kLdrHlpMemCopy(psz, pArgs->pszName, pArgs->cchName);
547 psz += pArgs->cchName;
548 if (pArgs->cchSuffix)
549 {
550 kLdrHlpMemCopy(psz, pArgs->pszSuffix, pArgs->cchSuffix);
551 psz += pArgs->cchSuffix;
552 }
553 *psz = '\0';
554
555 /*
556 * Try open it.
557 */
558 return kldrDyldFindTryOpen(s_szFilename, pArgs->ppRdr);
[2867]559}
560
561
562/**
563 * Enumerates the specfied path.
564 *
565 * @returns Any return code from the kldrDyldFindTryOpenPath() which isn't KLDR_ERR_MODULE_NOT_FOUND.
566 * @returns KLDR_ERR_MODULE_NOT_FOUND if the end of the search path was reached.
567 * @param pszSearchPath The search path to enumeare.
[2868]568 * @param pArgs The search argument structure.
[2867]569 */
[2868]570static int kldrDyldFindEnumeratePath(const char *pszSearchPath, PCKLDRDYLDFINDARGS pArgs)
[2867]571{
[2868]572 const char *psz = pszSearchPath;
573 for (;;)
574 {
575 const char *pszEnd;
576 size_t cchPath;
577
578 /*
579 * Trim.
580 */
581 while (*psz == ';' || *psz == ':')
582 psz++;
583 if (*psz == '\0')
584 return KLDR_ERR_MODULE_NOT_FOUND;
585
586 /*
587 * Find the end.
588 */
589 pszEnd = psz + 1;
590 while ( *pszEnd != '\0'
591 && *pszEnd != ';'
592#if defined(__OS2__) || defined(__WIN__)
593 && ( *pszEnd != ':'
594 || ( pszEnd - psz == 1
595 && ( (*psz >= 'A' && *psz <= 'Z')
596 || (*psz >= 'a' && *psz <= 'z')
597 )
598 )
599 )
600#else
601 && *pszEnd != ':'
602#endif
603 )
604 pszEnd++;
605
606 /*
607 * If not empty path, try open the module using it.
608 */
609 cchPath = pszEnd - psz - 1;
610 if (cchPath > 0)
611 {
612 int rc;
613 rc = kldrDyldFindTryOpenPath(psz, cchPath, pArgs);
614 if (rc != KLDR_ERR_MODULE_NOT_FOUND)
615 return rc;
616 }
617
618 /* next */
619 psz = pszEnd;
620 }
[2867]621}
622
623
[2868]624/**
625 * Resolve default search method, prefix and suffix.
626 *
627 * @returns 0 on success, KLDR_ERR_INVALID_PARAMETER on failure.
628 * @param penmSearch The search method. In/Out.
629 * @param ppszPrefix The prefix. In/Out.
630 * @param ppszSuffix The suffix. In/Out.
631 * @param pszName The name. In.
632 */
633static int kldrDyldFindGetDefaults(KLDRDYLDSEARCH *penmSearch, const char **ppszPrefix, const char **ppszSuffix,
634 const char *pszName)
635{
636 unsigned fCaseSensitive;
[2867]637
[2868]638 /*
639 * Fixup search method alias.
640 */
641 if (*penmSearch == KLDRDYLD_SEARCH_HOST)
642#if defined(__OS2__)
643 *penmSearch = KLDRDYLD_SEARCH_OS2;
644#elif defined(__WIN__)
645 *penmSearch = KLDRDYLD_SEARCH_WINDOWS;
646#else
647# error "Port me"
648#endif
649
650 /*
651 * Apply search method specific prefix/suffix.
652 */
653 switch (*penmSearch)
654 {
655 case KLDRDYLD_SEARCH_KLDR:
656 if (!*ppszPrefix && kLdrDyldDefPrefix[0])
657 *ppszPrefix = kLdrDyldDefPrefix;
658 if (!*ppszSuffix && kLdrDyldDefSuffix[0])
659 *ppszSuffix = kLdrDyldDefSuffix;
660 fCaseSensitive = 1;
661 break;
662
663 case KLDRDYLD_SEARCH_OS2:
664 if (!*ppszSuffix)
665 *ppszSuffix = ".dll";
666 fCaseSensitive = 0;
667 break;
668
669 case KLDRDYLD_SEARCH_WINDOWS:
670 case KLDRDYLD_SEARCH_WINDOWS_ALTERED:
671 if (!*ppszSuffix)
672 *ppszSuffix = ".dll";
673 fCaseSensitive = 0;
674 break;
675
676 case KLDRDYLD_SEARCH_UNIX_COMMON:
677 fCaseSensitive = 1;
678 break;
679
680 default:
681 KLDRDYLDFIND_ASSERT(!"invalid search method");
682 return KLDR_ERR_INVALID_PARAMETER;
683 }
684
685 /*
686 * Drop the suffix if it's already included in the name.
687 */
688 if (*ppszSuffix)
689 {
690 const size_t cchName = kLdrHlpStrLen(pszName);
691 const size_t cchSuffix = kLdrHlpStrLen(*ppszSuffix);
692 if ( cchName > cchSuffix
693 && ( fCaseSensitive
694 ? kLdrHlpMemComp(pszName + cchName - cchSuffix, *ppszSuffix, cchSuffix)
695 : kLdrHlpMemIComp(pszName + cchName - cchSuffix, *ppszSuffix, cchSuffix))
696 )
697 *ppszSuffix = NULL;
698 }
699
700 return 0;
701}
702
703
[2867]704/**
[2835]705 * Locates an already open module using the specified search method.
706 *
707 * @returns 0 and *ppMod on success, non-zero OS specific error on failure.
708 *
709 * @param pszName Partial or complete name, it's specific to the search method to determin which.
[2843]710 * @param pszPrefix Prefix than can be used when searching.
711 * @param pszSuffix Suffix than can be used when searching.
[2835]712 * @param enmSearch The file search method to apply.
713 * @param fFlags Search flags.
714 * @param ppMod Where to store the file provider instance on success.
715 */
716int kldrDyldFindExistingModule(const char *pszName, const char *pszPrefix, const char *pszSuffix,
717 KLDRDYLDSEARCH enmSearch, unsigned fFlags, PPKLDRDYLDMOD ppMod)
718{
[2867]719
720 int rc;
721 unsigned fOS2LibpathStrict;
[2835]722 *ppMod = NULL;
[2867]723
724 /*
725 * Don't bother if no modules are loaded yet.
726 */
727 if (!kLdrDyldHead)
728 return KLDR_ERR_MODULE_NOT_FOUND;
729
730 /*
[2868]731 * Defaults.
[2867]732 */
[2868]733 rc = kldrDyldFindGetDefaults(&enmSearch, &pszPrefix, &pszSuffix, pszName);
734 if (rc)
735 return rc;
[2867]736
737 /*
738 * If this isn't just a filename, the caller has specified a file
739 * that should be opened directly and not a module name to be searched for.
740 *
741 * In order to do the right thing we'll have to open the file and get the
742 * correct filename for it.
743 *
744 * The OS/2 libpath strict method require us to find the correct DLL first.
745 */
746 fOS2LibpathStrict = 0;
747 if ( !kldrHlpIsFilenameOnly(pszName)
748 || (fOS2LibpathStrict = ( enmSearch == KLDRDYLD_SEARCH_OS2
749 && kLdrDyldOS2LibpathStrict[0] == 'T')
750 )
751 )
752 {
753 PKLDRRDR pRdr;
754 if (fOS2LibpathStrict)
755 rc = kldrDyldFindDoSearch(pszName, pszPrefix, pszSuffix, enmSearch, fFlags, &pRdr);
756 else
757 rc = kldrDyldFindTryOpen(pszName, &pRdr);
758 if (!rc)
759 {
760 /* do a filename based search. */
761 const char *pszFilename = kLdrRdrName(pRdr);
762 const size_t cchFilename = kLdrHlpStrLen(pszFilename);
763 PKLDRDYLDMOD pCur;
764 rc = KLDR_ERR_MODULE_NOT_FOUND;
765 for (pCur = kLdrDyldHead; pCur; pCur = pCur->Load.pNext)
766 {
767 if ( pCur->pMod->cchFilename == cchFilename
768 && !kLdrHlpMemComp(pCur->pMod->pszFilename, pszFilename, cchFilename))
769 {
770 *ppMod = pCur;
771 rc = 0;
772 break;
773 }
774 }
775 kLdrRdrClose(pRdr);
776 }
777 }
778 else
779 {
[2868]780 const size_t cchName = kLdrHlpStrLen(pszName);
781 const size_t cchPrefix = pszPrefix ? kLdrHlpStrLen(pszPrefix) : 0;
782 const size_t cchSuffix = pszSuffix ? kLdrHlpStrLen(pszSuffix) : 0;
783 const char *pszNameSuffix = kldrHlpGetSuff(pszName);
784 PKLDRDYLDMOD pCur = kLdrDyldHead;
785
[2867]786 /*
[2868]787 * Some of the methods are case insensitive (ASCII), others are case sensitive.
788 * To avoid having todo indirect calls to the compare functions here, we split
789 * ways even if it means a lot of duplicate code.
[2867]790 */
[2868]791 if ( enmSearch == KLDRDYLD_SEARCH_OS2
792 || enmSearch == KLDRDYLD_SEARCH_WINDOWS
793 || enmSearch == KLDRDYLD_SEARCH_WINDOWS_ALTERED)
[2867]794 {
[2868]795 const unsigned fNameHasSuffix = pszNameSuffix
796 && kLdrHlpStrLen(pszNameSuffix) == cchSuffix
797 && kLdrHlpMemIComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
798 for (; pCur; pCur = pCur->Load.pNext)
799 {
800 /* match global / specific */
801 if ( !pCur->fGlobalOrSpecific
802 && !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
803 continue;
[2867]804
[2868]805 /* match name */
806 if ( pCur->pMod->cchName == cchName
807 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName))
808 break;
809 if (cchPrefix)
[2867]810 {
[2868]811 if ( pCur->pMod->cchName == cchName + cchPrefix
812 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
813 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
814 break;
815 }
816 if (cchSuffix)
817 {
818 if ( pCur->pMod->cchName == cchName + cchSuffix
819 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
[2867]820 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName))
[2868]821 break;
822 if ( fNameHasSuffix
823 && pCur->pMod->cchName == cchName - cchSuffix
824 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
825 break;
[2867]826 if (cchPrefix)
827 {
[2868]828 if ( pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
[2867]829 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
[2868]830 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
831 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
[2867]832 break;
833 if ( fNameHasSuffix
[2868]834 && pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
835 && !kLdrHlpMemIComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
836 && !kLdrHlpMemIComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
[2867]837 break;
838 }
839 }
840 }
[2868]841 }
842 else
843 {
844 const unsigned fNameHasSuffix = pszNameSuffix
845 && kLdrHlpStrLen(pszNameSuffix) == cchSuffix
846 && kLdrHlpMemComp(pszNameSuffix, pszName + cchName - cchSuffix, cchSuffix);
847 for (; pCur; pCur = pCur->Load.pNext)
[2867]848 {
[2868]849 /* match global / specific */
850 if ( !pCur->fGlobalOrSpecific
851 && !(fFlags & KLDRYDLD_LOAD_FLAGS_SPECIFIC_MODULE))
852 continue;
853
854 /* match name */
855 if ( pCur->pMod->cchName == cchName
856 && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName))
857 break;
858 if (cchPrefix)
[2867]859 {
[2868]860 if ( pCur->pMod->cchName == cchName + cchPrefix
861 && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
862 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName))
863 break;
864 }
865 if (cchSuffix)
866 {
867 if ( pCur->pMod->cchName == cchName + cchSuffix
868 && !kLdrHlpMemComp(pCur->pMod->pszName + cchName, pszSuffix, cchSuffix)
[2867]869 && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName))
[2868]870 break;
871 if ( fNameHasSuffix
872 && pCur->pMod->cchName == cchName - cchSuffix
873 && !kLdrHlpMemComp(pCur->pMod->pszName, pszName, cchName - cchSuffix))
874 break;
[2867]875 if (cchPrefix)
876 {
[2868]877 if ( pCur->pMod->cchName == cchName + cchPrefix + cchSuffix
[2867]878 && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
[2868]879 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName)
880 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix + cchName, pszSuffix, cchSuffix))
[2867]881 break;
[2868]882 if ( pCur->pMod->cchName == cchName + cchPrefix - cchSuffix
883 && !kLdrHlpMemComp(pCur->pMod->pszName, pszPrefix, cchPrefix)
884 && !kLdrHlpMemComp(pCur->pMod->pszName + cchPrefix, pszName, cchName - cchSuffix))
[2867]885 break;
886 }
887 }
888 }
889 }
[2868]890
891 /* search result. */
892 if (pCur)
893 {
894 *ppMod = pCur;
895 rc = 0;
896 }
897 else
898 rc = KLDR_ERR_MODULE_NOT_FOUND;
[2867]899 }
900
901 return rc;
[2835]902}
903
Note: See TracBrowser for help on using the repository browser.