]>
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 - 2012, Intel Corporation. All rights reserved.<BR>
25 SPDX-License-Identifier: BSD-2-Clause-Patent
35 /* VERSION must be at least two characters long. */
44 /* Search path entry delimiter */
50 #define PREFIX "/Efi/StdLib"
54 #define EXEC_PREFIX PREFIX
58 #define LIBPYTHON "lib/python." VERSION
62 #ifdef HAVE_ENVIRONMENT_OPS
63 #define PYTHONPATH PREFIX LIBPYTHON sDELIM \
64 EXEC_PREFIX LIBPYTHON "/lib-dynload"
66 #define PYTHONPATH LIBPYTHON
71 #define LANDMARK "os.py"
74 static char prefix
[MAXPATHLEN
+1];
75 static char exec_prefix
[MAXPATHLEN
+1];
76 static char progpath
[MAXPATHLEN
+1];
77 static char *module_search_path
= NULL
;
78 static char lib_python
[] = LIBPYTHON
;
79 static char volume_name
[32] = { 0 };
81 /** Determine if "ch" is a separator character.
83 @param[in] ch The character to test.
85 @retval TRUE ch is a separator character.
86 @retval FALSE ch is NOT a separator character.
92 return ch
== SEP
|| ch
== ALTSEP
;
98 /** Reduce a path by its last element.
100 The last element (everything to the right of the last separator character)
101 in the path, dir, is removed from the path. Parameter dir is modified in place.
103 @param[in,out] dir Pointer to the path to modify.
108 size_t i
= strlen(dir
);
109 while (i
> 0 && !is_sep(dir
[i
]))
114 #ifndef UEFI_C_SOURCE
115 /** Does filename point to a file and not directory?
117 @param[in] filename The fully qualified path to the object to test.
119 @retval 0 Filename was not found, or is a directory.
120 @retval 1 Filename refers to a regular file.
123 isfile(char *filename
)
126 if (stat(filename
, &buf
) != 0) {
129 //if (!S_ISREG(buf.st_mode))
130 if (S_ISDIR(buf
.st_mode
)) {
136 /** Determine if filename refers to a Python module.
138 A Python module is indicated if the file exists, or if the file with
139 'o' or 'c' appended exists.
141 @param[in] filename The fully qualified path to the object to test.
146 ismodule(char *filename
)
148 if (isfile(filename
)) {
149 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
153 /* Check for the compiled version of prefix. */
154 if (strlen(filename
) < MAXPATHLEN
) {
155 strcat(filename
, Py_OptimizeFlag
? "o" : "c");
156 if (isfile(filename
)) {
163 /** Does filename point to a directory?
165 @param[in] filename The fully qualified path to the object to test.
167 @retval 0 Filename was not found, or is not a regular file.
168 @retval 1 Filename refers to a directory.
171 isdir(char *filename
)
175 if (stat(filename
, &buf
) != 0)
178 if (!S_ISDIR(buf
.st_mode
))
183 #endif /* UEFI_C_SOURCE */
185 /** Determine if a path is absolute, or not.
186 An absolute path consists of a volume name, "VOL:", followed by a rooted path,
187 "/path/elements". If both of these components are present, the path is absolute.
189 Let P be a pointer to the path to test.
190 Let A be a pointer to the first ':' in P.
191 Let B be a pointer to the first '/' or '\\' in P.
193 If A and B are not NULL
194 If (A-P+1) == (B-P) then the path is absolute.
195 Otherwise, the path is NOT absolute.
197 @param[in] path The path to test.
199 @retval -1 Path is absolute but lacking volume name.
200 @retval 0 Path is NOT absolute.
201 @retval 1 Path is absolute.
204 is_absolute(char *path
)
209 A
= strchr(path
, ':');
210 B
= strpbrk(path
, "/\\");
219 if(((A
- path
) + 1) == (B
- path
)) {
228 /** Add a path component, by appending stuff to buffer.
229 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
230 NUL-terminated string with no more than MAXPATHLEN characters (not counting
231 the trailing NUL). It's a fatal error if it contains a string longer than
232 that (callers must be careful!). If these requirements are met, it's
233 guaranteed that buffer will still be a NUL-terminated string with no more
234 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
235 stuff as fits will be appended.
237 @param[in,out] buffer The path to be extended.
238 @param[in] stuff The stuff to join onto the path.
241 joinpath(char *buffer
, char *stuff
)
246 if (is_absolute(stuff
) == 1) {
252 strncpy(buffer
, volume_name
, MAXPATHLEN
);
255 /* We must not use an else clause here because we want to test n again.
256 volume_name may have been empty.
258 if (n
> 0 && n
< MAXPATHLEN
) {
259 if(!is_sep(buffer
[n
-1])) {
262 if(is_sep(stuff
[0])) ++stuff
;
266 Py_FatalError("buffer overflow in getpath.c's joinpath()");
268 if (n
+ k
> MAXPATHLEN
)
270 strncpy(buffer
+n
, stuff
, k
);
274 /** Is filename an executable file?
278 2) is a file, not a directory
279 3) has a name ending with ".efi"
280 4) Only has a single '.' in the name.
282 If basename(filename) does not contain a '.', append ".efi" to filename
283 If filename ends in ".efi", it is executable, else it isn't.
285 This routine is used to when searching for the file named by argv[0].
286 As such, there is no need to search for extensions other than ".efi".
288 @param[in] filename The name of the file to test. It may, or may not, have an extension.
290 @retval 0 filename already has a path other than ".efi", or it doesn't exist, or is a directory.
291 @retval 1 filename refers to an executable file.
294 isxfile(char *filename
)
301 bn
= basename(filename
); // Separate off the file name component
302 reduce(filename
); // and isolate the path component
304 newbn
= strrchr(bn
, '.'); // Does basename contain a period?
305 if(newbn
== NULL
) { // Does NOT contain a period.
307 strncpyX(newbn
, ".efi", MAXPATHLEN
- bnlen
); // append ".efi" to basename
310 else if(strcmp(newbn
, ".efi") != 0) {
311 return 0; // File can not be executable.
313 joinpath(filename
, bn
); // Stitch path and file name back together
315 if (stat(filename
, &buf
) != 0) { // Now, verify that file exists
318 if(S_ISDIR(buf
.st_mode
)) { // And it is not a directory.
325 /** Copy p into path, ensuring that the result is an absolute path.
327 copy_absolute requires that path be allocated at least
328 MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
330 @param[out] path Destination to receive the absolute path.
331 @param[in] p Path to be tested and possibly converted.
334 copy_absolute(char *path
, char *p
)
336 if (is_absolute(p
) == 1)
339 if (!getcwd(path
, MAXPATHLEN
)) {
340 /* unable to get the current directory */
341 if(volume_name
[0] != 0) {
342 strcpy(path
, volume_name
);
349 if (p
[0] == '.' && is_sep(p
[1]))
355 /** Modify path so that the result is an absolute path.
356 absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
358 @param[in,out] path The path to be made absolute.
361 absolutize(char *path
)
363 char buffer
[MAXPATHLEN
+ 1];
365 if (is_absolute(path
) == 1)
367 copy_absolute(buffer
, path
);
368 strcpy(path
, buffer
);
371 /** Extract the volume name from a path.
373 @param[out] Dest Pointer to location in which to store the extracted volume name.
374 @param[in] path Pointer to the path to extract the volume name from.
377 set_volume(char *Dest
, char *path
)
381 if(is_absolute(path
)) {
382 VolLen
= strcspn(path
, "/\\:");
383 if((VolLen
!= 0) && (path
[VolLen
] == ':')) {
384 (void) strncpyX(Dest
, path
, VolLen
+ 1);
392 Two directories must be found, the platform independent directory
393 (prefix), containing the common .py and .pyc files, and the platform
394 dependent directory (exec_prefix), containing the shared library
395 modules. Note that prefix and exec_prefix are the same directory
396 for UEFI installations.
398 Separate searches are carried out for prefix and exec_prefix.
399 Each search tries a number of different locations until a ``landmark''
400 file or directory is found. If no prefix or exec_prefix is found, a
401 warning message is issued and the preprocessor defined PREFIX and
402 EXEC_PREFIX are used (even though they may not work); python carries on
403 as best as is possible, but some imports may fail.
405 Before any searches are done, the location of the executable is
406 determined. If argv[0] has one or more slashes in it, it is used
407 unchanged. Otherwise, it must have been invoked from the shell's path,
408 so we search %PATH% for the named executable and use that. If the
409 executable was not found on %PATH% (or there was no %PATH% environment
410 variable), the original argv[0] string is used.
412 Finally, argv0_path is set to the directory containing the executable
413 (i.e. the last component is stripped).
415 With argv0_path in hand, we perform a number of steps. The same steps
416 are performed for prefix and for exec_prefix, but with a different
419 The prefix landmark will always be lib/python.VERSION/os.py and the
420 exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
421 is Python's version number as defined at the beginning of this file.
423 First. See if the %PYTHONHOME% environment variable points to the
424 installed location of the Python libraries. If %PYTHONHOME% is set, then
425 it points to prefix and exec_prefix. %PYTHONHOME% can be a single
426 directory, which is used for both, or the prefix and exec_prefix
427 directories separated by the DELIM character.
429 Next. Search the directories pointed to by the preprocessor variables
430 PREFIX and EXEC_PREFIX. These paths are prefixed with the volume name
431 extracted from argv0_path. The volume names correspond to the UEFI
436 Well, almost. Once we have determined prefix and exec_prefix, the
437 preprocessor variable PYTHONPATH is used to construct a path. Each
438 relative path on PYTHONPATH is prefixed with prefix. Then the directory
439 containing the shared library modules is appended. The environment
440 variable $PYTHONPATH is inserted in front of it all. Finally, the
441 prefix and exec_prefix globals are tweaked so they reflect the values
442 expected by other code, by stripping the "lib/python$VERSION/..." stuff
443 off. This seems to make more sense given that currently the only
444 known use of sys.prefix and sys.exec_prefix is for the ILU installation
445 process to find the installed Python tree.
447 The final, fully resolved, paths should look something like:
448 fs0:/Efi/Tools/python.efi
449 fs0:/Efi/StdLib/lib/python27
450 fs0:/Efi/StdLib/lib/python27/dynaload
456 extern char *Py_GetProgramName(void);
458 static char delimiter
[2] = {DELIM
, '\0'};
459 static char separator
[2] = {SEP
, '\0'};
460 char *pythonpath
= PYTHONPATH
;
461 char *rtpypath
= Py_GETENV("PYTHONPATH");
462 //char *home = Py_GetPythonHome();
463 char *path
= getenv("PATH");
464 char *prog
= Py_GetProgramName();
465 char argv0_path
[MAXPATHLEN
+1];
466 char zip_path
[MAXPATHLEN
+1];
473 /* ###########################################################################
474 Determine path to the Python.efi binary.
475 Produces progpath, argv0_path, and volume_name.
476 ########################################################################### */
478 /* If there is no slash in the argv0 path, then we have to
479 * assume python is on the user's $PATH, since there's no
480 * other way to find a directory to start the search from. If
481 * $PATH isn't exported, you lose.
483 if (strchr(prog
, SEP
))
484 strncpy(progpath
, prog
, MAXPATHLEN
);
487 char *delim
= strchr(path
, DELIM
);
490 size_t len
= delim
- path
;
491 if (len
> MAXPATHLEN
)
493 strncpy(progpath
, path
, len
);
494 *(progpath
+ len
) = '\0';
497 strncpy(progpath
, path
, MAXPATHLEN
);
499 joinpath(progpath
, prog
);
500 if (isxfile(progpath
))
512 if ( (!is_absolute(progpath
)) && (progpath
[0] != '\0') )
513 absolutize(progpath
);
514 strncpy(argv0_path
, progpath
, MAXPATHLEN
);
515 argv0_path
[MAXPATHLEN
] = '\0';
516 set_volume(volume_name
, argv0_path
);
519 /* At this point, argv0_path is guaranteed to be less than
520 MAXPATHLEN bytes long.
523 /* ###########################################################################
524 Build the FULL prefix string, including volume name.
525 This is the full path to the platform independent libraries.
526 ########################################################################### */
528 strncpy(prefix
, volume_name
, MAXPATHLEN
);
529 joinpath(prefix
, PREFIX
);
530 joinpath(prefix
, lib_python
);
532 /* ###########################################################################
533 Build the FULL path to the zipped-up Python library.
534 ########################################################################### */
536 strncpy(zip_path
, prefix
, MAXPATHLEN
);
537 zip_path
[MAXPATHLEN
] = '\0';
539 joinpath(zip_path
, "python00.zip");
540 bufsz
= strlen(zip_path
); /* Replace "00" with version */
541 zip_path
[bufsz
- 6] = VERSION
[0];
542 zip_path
[bufsz
- 5] = VERSION
[1];
544 /* ###########################################################################
545 Build the FULL path to dynamically loadable libraries.
546 ########################################################################### */
548 strncpy(exec_prefix
, volume_name
, MAXPATHLEN
);
549 joinpath(exec_prefix
, EXEC_PREFIX
);
550 joinpath(exec_prefix
, lib_python
);
551 joinpath(exec_prefix
, "lib-dynload");
553 /* ###########################################################################
554 Build the module search path.
555 ########################################################################### */
557 /* Reduce prefix and exec_prefix to their essence,
558 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
559 * If we're loading relative to the build directory,
560 * return the compiled-in defaults instead.
564 /* The prefix is the root directory, but reduce() chopped
567 strcpy(prefix
, volume_name
);
569 bufsz
= strlen(prefix
);
570 if(prefix
[bufsz
-1] == ':') {
575 /* Calculate size of return buffer.
577 defpath
= pythonpath
;
581 bufsz
+= strlen(rtpypath
) + 1;
583 prefixsz
= strlen(prefix
) + 1;
586 char *delim
= strchr(defpath
, DELIM
);
588 if (is_absolute(defpath
) == 0)
589 /* Paths are relative to prefix */
593 bufsz
+= delim
- defpath
+ 1;
595 bufsz
+= strlen(defpath
) + 1;
601 bufsz
+= strlen(zip_path
) + 1;
602 bufsz
+= strlen(exec_prefix
) + 1;
604 /* This is the only malloc call in this file */
605 buf
= (char *)PyMem_Malloc(bufsz
);
608 /* We can't exit, so print a warning and limp along */
609 fprintf(stderr
, "Not enough memory for dynamic PYTHONPATH.\n");
610 fprintf(stderr
, "Using default static PYTHONPATH.\n");
611 module_search_path
= PYTHONPATH
;
614 /* Run-time value of $PYTHONPATH goes first */
616 strcpy(buf
, rtpypath
);
617 strcat(buf
, delimiter
);
622 /* Next is the default zip path */
623 strcat(buf
, zip_path
);
624 strcat(buf
, delimiter
);
626 /* Next goes merge of compile-time $PYTHONPATH with
627 * dynamically located prefix.
629 defpath
= pythonpath
;
631 char *delim
= strchr(defpath
, DELIM
);
633 if (is_absolute(defpath
) != 1) {
635 strcat(buf
, separator
);
639 size_t len
= delim
- defpath
+ 1;
640 size_t end
= strlen(buf
) + len
;
641 strncat(buf
, defpath
, len
);
645 strcat(buf
, defpath
);
650 strcat(buf
, delimiter
);
652 /* Finally, on goes the directory for dynamic-load modules */
653 strcat(buf
, exec_prefix
);
655 /* And publish the results */
656 module_search_path
= buf
;
658 /* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
659 We want to get back to the root value, so we have to remove the final three
660 segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and
661 EXEC_PREFIX is also indeterminate, we just remove the three final segments.
666 if (!exec_prefix
[0]) {
667 strcpy(exec_prefix
, volume_name
);
669 bufsz
= strlen(exec_prefix
);
670 if(exec_prefix
[bufsz
-1] == ':') {
671 exec_prefix
[bufsz
] = SEP
;
672 exec_prefix
[bufsz
+1] = 0;
674 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__
, __LINE__
, module_search_path
);
675 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__
, __LINE__
, prefix
);
676 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__
, __LINE__
, exec_prefix
);
677 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__
, __LINE__
, progpath
);
681 /* External interface */
686 if (!module_search_path
)
688 return module_search_path
;
694 if (!module_search_path
)
700 Py_GetExecPrefix(void)
702 if (!module_search_path
)
708 Py_GetProgramFullPath(void)
710 if (!module_search_path
)