]>
git.proxmox.com Git - mirror_edk2.git/blob - AppPkg/Applications/Python/Efi/getpath.c
2 Return the initial module search path.
4 Search in specified locations for the associated Python libraries.
6 Py_GetPath returns module_search_path.
7 Py_GetPrefix returns PREFIX
8 Py_GetExec_Prefix returns PREFIX
9 Py_GetProgramFullPath returns the full path to the python executable.
11 These are built dynamically so that the proper volume name can be prefixed
14 For the EDK II, UEFI, implementation of Python, PREFIX and EXEC_PREFIX
19 The following final paths are assumed:
20 /Efi/Tools/Python.efi The Python executable.
21 /Efi/StdLib/lib/python.VERSION The platform independent Python modules.
22 /Efi/StdLib/lib/python.VERSION/dynalib Dynamically loadable Python extension modules.
24 Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
25 This program and the accompanying materials are licensed and made available under
26 the terms and conditions of the BSD License that accompanies this distribution.
27 The full text of the license may be found at
28 http://opensource.org/licenses/bsd-license.
30 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
31 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
40 /* VERSION must be at least two characters long. */
49 /* Search path entry delimiter */
55 #define PREFIX "/Efi/StdLib"
59 #define EXEC_PREFIX PREFIX
63 #define LIBPYTHON "lib/python." VERSION
67 //#define PYTHONPATH PREFIX LIBPYTHON sDELIM \
68 // EXEC_PREFIX LIBPYTHON "/lib-dynload"
69 #define PYTHONPATH LIBPYTHON // sDELIM
70 // LIBPYTHON "/lib-dynload"
74 #define LANDMARK "os.py"
77 static char prefix
[MAXPATHLEN
+1];
78 static char exec_prefix
[MAXPATHLEN
+1];
79 static char progpath
[MAXPATHLEN
+1];
80 static char *module_search_path
= NULL
;
81 static char lib_python
[] = LIBPYTHON
;
82 static char volume_name
[32] = { 0 };
84 /** Determine if "ch" is a separator character.
86 @param[in] ch The character to test.
88 @retval TRUE ch is a separator character.
89 @retval FALSE ch is NOT a separator character.
95 return ch
== SEP
|| ch
== ALTSEP
;
101 /** Reduce a path by its last element.
103 The last element (everything to the right of the last separator character)
104 in the path, dir, is removed from the path. Parameter dir is modified in place.
106 @param[in,out] dir Pointer to the path to modify.
111 size_t i
= strlen(dir
);
112 while (i
> 0 && !is_sep(dir
[i
]))
117 /** Does filename point to a file and not directory?
119 @param[in] filename The fully qualified path to the object to test.
121 @retval 0 Filename was not found, or is a directory.
122 @retval 1 Filename refers to a regular file.
125 isfile(char *filename
)
128 if (stat(filename
, &buf
) != 0) {
129 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] Not Found: file = \"%s\"\n", __func__, __LINE__, filename);
132 //if (!S_ISREG(buf.st_mode))
133 if (S_ISDIR(buf
.st_mode
)) {
134 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] Is DIR: file = \"%s\"\n", __func__, __LINE__, filename);
137 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] SUCCESS: file = \"%s\"\n", __func__, __LINE__, filename);
141 /** Determine if filename refers to a Python module.
143 A Python module is indicated if the file exists, or if the file with
144 'o' or 'c' appended exists.
146 @param[in] filename The fully qualified path to the object to test.
151 ismodule(char *filename
)
153 if (isfile(filename
)) {
154 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
158 /* Check for the compiled version of prefix. */
159 if (strlen(filename
) < MAXPATHLEN
) {
160 strcat(filename
, Py_OptimizeFlag
? "o" : "c");
161 if (isfile(filename
)) {
162 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
166 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] FAIL: file = \"%s\"\n", __func__, __LINE__, filename);
170 /** Does filename point to a directory?
172 @param[in] filename The fully qualified path to the object to test.
174 @retval 0 Filename was not found, or is not a regular file.
175 @retval 1 Filename refers to a directory.
178 isdir(char *filename
)
182 if (stat(filename
, &buf
) != 0)
185 if (!S_ISDIR(buf
.st_mode
))
191 /** Determine if a path is absolute, or not.
192 An absolute path consists of a volume name, "VOL:", followed by a rooted path,
193 "/path/elements". If both of these components are present, the path is absolute.
195 Let P be a pointer to the path to test.
196 Let A be a pointer to the first ':' in P.
197 Let B be a pointer to the first '/' or '\\' in P.
199 If A and B are not NULL
200 If (A-P+1) == (B-P) then the path is absolute.
201 Otherwise, the path is NOT absolute.
203 @param[in] path The path to test.
205 @retval -1 Path is absolute but lacking volume name.
206 @retval 0 Path is NOT absolute.
207 @retval 1 Path is absolute.
210 is_absolute(char *path
)
215 A
= strchr(path
, ':');
216 B
= strpbrk(path
, "/\\");
225 if(((A
- path
) + 1) == (B
- path
)) {
234 /** Add a path component, by appending stuff to buffer.
235 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
236 NUL-terminated string with no more than MAXPATHLEN characters (not counting
237 the trailing NUL). It's a fatal error if it contains a string longer than
238 that (callers must be careful!). If these requirements are met, it's
239 guaranteed that buffer will still be a NUL-terminated string with no more
240 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
241 stuff as fits will be appended.
243 @param[in,out] buffer The path to be extended.
244 @param[in] stuff The stuff to join onto the path.
247 joinpath(char *buffer
, char *stuff
)
252 if (is_absolute(stuff
) == 1) {
258 strncpy(buffer
, volume_name
, MAXPATHLEN
);
261 /* We must not use an else clause here because we want to test n again.
262 volume_name may have been empty.
264 if (n
> 0 && n
< MAXPATHLEN
) {
265 if(!is_sep(buffer
[n
-1])) {
268 if(is_sep(stuff
[0])) ++stuff
;
272 Py_FatalError("buffer overflow in getpath.c's joinpath()");
274 if (n
+ k
> MAXPATHLEN
)
276 strncpy(buffer
+n
, stuff
, k
);
280 /** Is filename an executable file?
284 2) is a file, not a directory
285 3) has a name ending with ".efi"
286 4) Only has a single '.' in the name.
288 If basename(filename) does not contain a '.', append ".efi" to filename
289 If filename ends in ".efi", it is executable, else it isn't.
291 This routine is used to when searching for the file named by argv[0].
292 As such, there is no need to search for extensions other than ".efi".
294 @param[in] filename The name of the file to test. It may, or may not, have an extension.
296 @retval 0 filename already has a path other than ".efi", or it doesn't exist, or is a directory.
297 @retval 1 filename refers to an executable file.
300 isxfile(char *filename
)
307 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] ENTER: file = \"%s\"\n", __func__, __LINE__, filename);
308 bn
= basename(filename
); // Separate off the file name component
309 reduce(filename
); // and isolate the path component
311 newbn
= strrchr(bn
, '.'); // Does basename contain a period?
312 if(newbn
== NULL
) { // Does NOT contain a period.
314 strncpyX(newbn
, ".efi", MAXPATHLEN
- bnlen
); // append ".efi" to basename
317 else if(strcmp(newbn
, ".efi") != 0) {
318 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Bad extension\n", __func__, __LINE__);
319 return 0; // File can not be executable.
321 joinpath(filename
, bn
); // Stitch path and file name back together
322 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
324 if (stat(filename
, &buf
) != 0) { // Now, verify that file exists
325 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Does not exist\n", __func__, __LINE__);
328 if(S_ISDIR(buf
.st_mode
)) { // And it is not a directory.
329 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Is a directory\n", __func__, __LINE__);
333 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] EXIT: file = \"%s\"\n", __func__, __LINE__, filename);
337 /** Copy p into path, ensuring that the result is an absolute path.
339 copy_absolute requires that path be allocated at least
340 MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
342 @param[out] path Destination to receive the absolute path.
343 @param[in] p Path to be tested and possibly converted.
346 copy_absolute(char *path
, char *p
)
348 if (is_absolute(p
) == 1)
351 if (!getcwd(path
, MAXPATHLEN
)) {
352 /* unable to get the current directory */
353 if(volume_name
[0] != 0) {
354 strcpy(path
, volume_name
);
361 if (p
[0] == '.' && is_sep(p
[1]))
367 /** Modify path so that the result is an absolute path.
368 absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
370 @param[in,out] path The path to be made absolute.
373 absolutize(char *path
)
375 char buffer
[MAXPATHLEN
+ 1];
377 if (is_absolute(path
) == 1)
379 copy_absolute(buffer
, path
);
380 strcpy(path
, buffer
);
383 /** Extract the volume name from a path.
385 @param[out] Dest Pointer to location in which to store the extracted volume name.
386 @param[in] path Pointer to the path to extract the volume name from.
389 set_volume(char *Dest
, char *path
)
393 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] ENTER: path = \"%s\"\n", __func__, __LINE__, path);
394 if(is_absolute(path
)) {
395 VolLen
= strcspn(path
, "/\\:");
396 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: VolLen = %d\n", __func__, __LINE__, VolLen);
397 if((VolLen
!= 0) && (path
[VolLen
] == ':')) {
398 (void) strncpyX(Dest
, path
, VolLen
+ 1);
399 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: VolLen = %d, Dest = \"%s\" path = \"%s\"\n",
400 // __func__, __LINE__, VolLen, Dest, path);
403 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d] EXIT: Dest = \"%s\"\n", __func__, __LINE__, Dest);
409 Two directories must be found, the platform independent directory
410 (prefix), containing the common .py and .pyc files, and the platform
411 dependent directory (exec_prefix), containing the shared library
412 modules. Note that prefix and exec_prefix are the same directory
413 for UEFI installations.
415 Separate searches are carried out for prefix and exec_prefix.
416 Each search tries a number of different locations until a ``landmark''
417 file or directory is found. If no prefix or exec_prefix is found, a
418 warning message is issued and the preprocessor defined PREFIX and
419 EXEC_PREFIX are used (even though they may not work); python carries on
420 as best as is possible, but some imports may fail.
422 Before any searches are done, the location of the executable is
423 determined. If argv[0] has one or more slashes in it, it is used
424 unchanged. Otherwise, it must have been invoked from the shell's path,
425 so we search %PATH% for the named executable and use that. If the
426 executable was not found on %PATH% (or there was no %PATH% environment
427 variable), the original argv[0] string is used.
429 Finally, argv0_path is set to the directory containing the executable
430 (i.e. the last component is stripped).
432 With argv0_path in hand, we perform a number of steps. The same steps
433 are performed for prefix and for exec_prefix, but with a different
436 The prefix landmark will always be lib/python.VERSION/os.py and the
437 exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
438 is Python's version number as defined at the beginning of this file.
440 First. See if the %PYTHONHOME% environment variable points to the
441 installed location of the Python libraries. If %PYTHONHOME% is set, then
442 it points to prefix and exec_prefix. %PYTHONHOME% can be a single
443 directory, which is used for both, or the prefix and exec_prefix
444 directories separated by the DELIM character.
446 Next. Search the directories pointed to by the preprocessor variables
447 PREFIX and EXEC_PREFIX. These paths are prefixed with the volume name
448 extracted from argv0_path. The volume names correspond to the UEFI
453 Well, almost. Once we have determined prefix and exec_prefix, the
454 preprocessor variable PYTHONPATH is used to construct a path. Each
455 relative path on PYTHONPATH is prefixed with prefix. Then the directory
456 containing the shared library modules is appended. The environment
457 variable $PYTHONPATH is inserted in front of it all. Finally, the
458 prefix and exec_prefix globals are tweaked so they reflect the values
459 expected by other code, by stripping the "lib/python$VERSION/..." stuff
460 off. This seems to make more sense given that currently the only
461 known use of sys.prefix and sys.exec_prefix is for the ILU installation
462 process to find the installed Python tree.
464 The final, fully resolved, paths should look something like:
465 fs0:/Efi/Tools/python.efi
466 fs0:/Efi/StdLib/lib/python27
467 fs0:/Efi/StdLib/lib/python27/dynaload
473 extern char *Py_GetProgramName(void);
475 static char delimiter
[2] = {DELIM
, '\0'};
476 static char separator
[2] = {SEP
, '\0'};
477 char *pythonpath
= PYTHONPATH
;
478 char *rtpypath
= Py_GETENV("PYTHONPATH");
479 //char *home = Py_GetPythonHome();
480 char *path
= getenv("PATH");
481 char *prog
= Py_GetProgramName();
482 char argv0_path
[MAXPATHLEN
+1];
483 char zip_path
[MAXPATHLEN
+1];
484 //int pfound, efound; /* 1 if found; -1 if found build directory */
489 //uint32_t nsexeclength = MAXPATHLEN;
493 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]:\nENTER prog=\"%s\"\n path=\"%s\"\n", __func__, __LINE__, prog, path);
496 /* ###########################################################################
497 Determine path to the Python.efi binary.
498 Produces progpath, argv0_path, and volume_name.
499 ########################################################################### */
501 /* If there is no slash in the argv0 path, then we have to
502 * assume python is on the user's $PATH, since there's no
503 * other way to find a directory to start the search from. If
504 * $PATH isn't exported, you lose.
506 if (strchr(prog
, SEP
))
507 strncpy(progpath
, prog
, MAXPATHLEN
);
510 char *delim
= strchr(path
, DELIM
);
513 size_t len
= delim
- path
;
514 if (len
> MAXPATHLEN
)
516 strncpy(progpath
, path
, len
);
517 *(progpath
+ len
) = '\0';
520 strncpy(progpath
, path
, MAXPATHLEN
);
522 joinpath(progpath
, prog
);
523 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath);
524 if (isxfile(progpath
))
536 if ( (!is_absolute(progpath
)) && (progpath
[0] != '\0') )
537 absolutize(progpath
);
538 strncpy(argv0_path
, progpath
, MAXPATHLEN
);
539 argv0_path
[MAXPATHLEN
] = '\0';
540 set_volume(volume_name
, argv0_path
);
542 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: volume_name = \"%s\"\n", __func__, __LINE__, volume_name);
544 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath);
545 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: argv0_path = \"%s\"\n", __func__, __LINE__, argv0_path);
546 /* At this point, argv0_path is guaranteed to be less than
547 MAXPATHLEN bytes long.
550 /* ###########################################################################
551 Build the FULL prefix string, including volume name.
552 This is the full path to the platform independent libraries.
553 ########################################################################### */
555 //if (!(pfound = search_for_prefix(argv0_path, home))) {
556 // if (!Py_FrozenFlag)
558 // "Could not find platform independent libraries <prefix>\n");
559 strncpy(prefix
, volume_name
, MAXPATHLEN
);
560 joinpath(prefix
, PREFIX
);
561 joinpath(prefix
, lib_python
);
565 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: V = \"%s\", Prefix = \"%s\"\n", __func__, __LINE__, volume_name, prefix);
567 /* ###########################################################################
568 Build the FULL path to the zipped-up Python library.
569 ########################################################################### */
571 strncpy(zip_path
, prefix
, MAXPATHLEN
);
572 zip_path
[MAXPATHLEN
] = '\0';
573 //if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
578 // strncpy(zip_path, PREFIX, MAXPATHLEN);
579 joinpath(zip_path
, "python00.zip");
580 bufsz
= strlen(zip_path
); /* Replace "00" with version */
581 zip_path
[bufsz
- 6] = VERSION
[0];
582 zip_path
[bufsz
- 5] = VERSION
[1];
583 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Zip_path = \"%s\"\n", __func__, __LINE__, zip_path);
585 /* ###########################################################################
586 Build the FULL path to dynamically loadable libraries.
587 ########################################################################### */
589 //if (!(efound = search_for_exec_prefix(argv0_path, home))) {
590 // if (!Py_FrozenFlag)
592 // "Could not find platform dependent libraries <exec_prefix>\n");
593 strncpy(exec_prefix
, volume_name
, MAXPATHLEN
);
594 joinpath(exec_prefix
, EXEC_PREFIX
);
595 joinpath(exec_prefix
, lib_python
);
596 joinpath(exec_prefix
, "dynaload");
598 /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */
599 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: Exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix);
601 //if ((!pfound || !efound) && !Py_FrozenFlag)
603 // "Consider setting $PYTHONHOME to <prefix>[%c<exec_prefix>]\n", DELIM);
605 /* ###########################################################################
606 Build the module search path.
607 ########################################################################### */
609 /* Reduce prefix and exec_prefix to their essence,
610 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
611 * If we're loading relative to the build directory,
612 * return the compiled-in defaults instead.
617 /* The prefix is the root directory, but reduce() chopped
620 strcpy(prefix
, volume_name
);
622 bufsz
= strlen(prefix
);
623 if(prefix
[bufsz
-1] == ':') {
629 // strncpy(prefix, PREFIX, MAXPATHLEN);
631 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix);
633 /* Calculate size of return buffer.
635 defpath
= pythonpath
;
639 bufsz
+= strlen(rtpypath
) + 1;
641 prefixsz
= strlen(prefix
) + 1;
644 char *delim
= strchr(defpath
, DELIM
);
646 if (is_absolute(defpath
) == 0)
647 /* Paths are relative to prefix */
651 bufsz
+= delim
- defpath
+ 1;
653 bufsz
+= strlen(defpath
) + 1;
658 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: defpath = \"%s\"\n", __func__, __LINE__, defpath);
660 bufsz
+= strlen(zip_path
) + 1;
661 bufsz
+= strlen(exec_prefix
) + 1;
663 /* This is the only malloc call in this file */
664 buf
= (char *)PyMem_Malloc(bufsz
);
667 /* We can't exit, so print a warning and limp along */
668 fprintf(stderr
, "Not enough memory for dynamic PYTHONPATH.\n");
669 fprintf(stderr
, "Using default static PYTHONPATH.\n");
670 module_search_path
= PYTHONPATH
;
673 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]:\n", __func__, __LINE__);
674 /* Run-time value of $PYTHONPATH goes first */
676 strcpy(buf
, rtpypath
);
677 strcat(buf
, delimiter
);
681 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: RTpath = \"%s\"\n", __func__, __LINE__, buf);
683 /* Next is the default zip path */
684 strcat(buf
, zip_path
);
685 strcat(buf
, delimiter
);
686 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: +Zip = \"%s\"\n", __func__, __LINE__, buf);
688 /* Next goes merge of compile-time $PYTHONPATH with
689 * dynamically located prefix.
691 defpath
= pythonpath
;
693 char *delim
= strchr(defpath
, DELIM
);
695 if (is_absolute(defpath
) != 1) {
697 strcat(buf
, separator
);
701 size_t len
= delim
- defpath
+ 1;
702 size_t end
= strlen(buf
) + len
;
703 strncat(buf
, defpath
, len
);
707 strcat(buf
, defpath
);
712 strcat(buf
, delimiter
);
713 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: +Merge = \"%s\"\n", __func__, __LINE__, buf);
715 /* Finally, on goes the directory for dynamic-load modules */
716 strcat(buf
, exec_prefix
);
718 /* And publish the results */
719 module_search_path
= buf
;
720 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path);
724 /* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
725 We want to get back to the root value, so we have to remove the final three
726 segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and
727 EXEC_PREFIX is also indeterminate, we just remove the three final segments.
732 if (!exec_prefix
[0]) {
733 strcpy(exec_prefix
, volume_name
);
735 bufsz
= strlen(exec_prefix
);
736 if(exec_prefix
[bufsz
-1] == ':') {
737 exec_prefix
[bufsz
] = SEP
;
738 exec_prefix
[bufsz
+1] = 0;
742 // strncpy(exec_prefix, EXEC_PREFIX, MAXPATHLEN);
743 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__
, __LINE__
, module_search_path
);
744 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__
, __LINE__
, prefix
);
745 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__
, __LINE__
, exec_prefix
);
746 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__
, __LINE__
, progpath
);
750 /* External interface */
755 if (!module_search_path
)
757 return module_search_path
;
763 if (!module_search_path
)
769 Py_GetExecPrefix(void)
771 if (!module_search_path
)
777 Py_GetProgramFullPath(void)
779 if (!module_search_path
)