]>
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.
41 /* VERSION must be at least two characters long. */
50 /* Search path entry delimiter */
56 #define PREFIX "/Efi/StdLib"
60 #define EXEC_PREFIX PREFIX
64 #define LIBPYTHON "lib/python." VERSION
68 //#define PYTHONPATH PREFIX LIBPYTHON sDELIM \
69 // EXEC_PREFIX LIBPYTHON "/lib-dynload"
70 #define PYTHONPATH LIBPYTHON // sDELIM
71 // LIBPYTHON "/lib-dynload"
75 #define LANDMARK "os.py"
78 static char prefix
[MAXPATHLEN
+1];
79 static char exec_prefix
[MAXPATHLEN
+1];
80 static char progpath
[MAXPATHLEN
+1];
81 static char *module_search_path
= NULL
;
82 static char lib_python
[] = LIBPYTHON
;
83 static char volume_name
[32] = { 0 };
85 /** Determine if "ch" is a separator character.
87 @param[in] ch The character to test.
89 @retval TRUE ch is a separator character.
90 @retval FALSE ch is NOT a separator character.
96 return ch
== SEP
|| ch
== ALTSEP
;
102 /** Reduce a path by its last element.
104 The last element (everything to the right of the last separator character)
105 in the path, dir, is removed from the path. Parameter dir is modified in place.
107 @param[in,out] dir Pointer to the path to modify.
112 size_t i
= strlen(dir
);
113 while (i
> 0 && !is_sep(dir
[i
]))
118 /** Does filename point to a file and not directory?
120 @param[in] filename The fully qualified path to the object to test.
122 @retval 0 Filename was not found, or is a directory.
123 @retval 1 Filename refers to a regular file.
126 isfile(char *filename
)
129 if (stat(filename
, &buf
) != 0) {
132 //if (!S_ISREG(buf.st_mode))
133 if (S_ISDIR(buf
.st_mode
)) {
139 /** Determine if filename refers to a Python module.
141 A Python module is indicated if the file exists, or if the file with
142 'o' or 'c' appended exists.
144 @param[in] filename The fully qualified path to the object to test.
149 ismodule(char *filename
)
151 if (isfile(filename
)) {
152 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename);
156 /* Check for the compiled version of prefix. */
157 if (strlen(filename
) < MAXPATHLEN
) {
158 strcat(filename
, Py_OptimizeFlag
? "o" : "c");
159 if (isfile(filename
)) {
166 /** Does filename point to a directory?
168 @param[in] filename The fully qualified path to the object to test.
170 @retval 0 Filename was not found, or is not a regular file.
171 @retval 1 Filename refers to a directory.
174 isdir(char *filename
)
178 if (stat(filename
, &buf
) != 0)
181 if (!S_ISDIR(buf
.st_mode
))
187 /** Determine if a path is absolute, or not.
188 An absolute path consists of a volume name, "VOL:", followed by a rooted path,
189 "/path/elements". If both of these components are present, the path is absolute.
191 Let P be a pointer to the path to test.
192 Let A be a pointer to the first ':' in P.
193 Let B be a pointer to the first '/' or '\\' in P.
195 If A and B are not NULL
196 If (A-P+1) == (B-P) then the path is absolute.
197 Otherwise, the path is NOT absolute.
199 @param[in] path The path to test.
201 @retval -1 Path is absolute but lacking volume name.
202 @retval 0 Path is NOT absolute.
203 @retval 1 Path is absolute.
206 is_absolute(char *path
)
211 A
= strchr(path
, ':');
212 B
= strpbrk(path
, "/\\");
221 if(((A
- path
) + 1) == (B
- path
)) {
230 /** Add a path component, by appending stuff to buffer.
231 buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
232 NUL-terminated string with no more than MAXPATHLEN characters (not counting
233 the trailing NUL). It's a fatal error if it contains a string longer than
234 that (callers must be careful!). If these requirements are met, it's
235 guaranteed that buffer will still be a NUL-terminated string with no more
236 than MAXPATHLEN characters at exit. If stuff is too long, only as much of
237 stuff as fits will be appended.
239 @param[in,out] buffer The path to be extended.
240 @param[in] stuff The stuff to join onto the path.
243 joinpath(char *buffer
, char *stuff
)
248 if (is_absolute(stuff
) == 1) {
254 strncpy(buffer
, volume_name
, MAXPATHLEN
);
257 /* We must not use an else clause here because we want to test n again.
258 volume_name may have been empty.
260 if (n
> 0 && n
< MAXPATHLEN
) {
261 if(!is_sep(buffer
[n
-1])) {
264 if(is_sep(stuff
[0])) ++stuff
;
268 Py_FatalError("buffer overflow in getpath.c's joinpath()");
270 if (n
+ k
> MAXPATHLEN
)
272 strncpy(buffer
+n
, stuff
, k
);
276 /** Is filename an executable file?
280 2) is a file, not a directory
281 3) has a name ending with ".efi"
282 4) Only has a single '.' in the name.
284 If basename(filename) does not contain a '.', append ".efi" to filename
285 If filename ends in ".efi", it is executable, else it isn't.
287 This routine is used to when searching for the file named by argv[0].
288 As such, there is no need to search for extensions other than ".efi".
290 @param[in] filename The name of the file to test. It may, or may not, have an extension.
292 @retval 0 filename already has a path other than ".efi", or it doesn't exist, or is a directory.
293 @retval 1 filename refers to an executable file.
296 isxfile(char *filename
)
303 bn
= basename(filename
); // Separate off the file name component
304 reduce(filename
); // and isolate the path component
306 newbn
= strrchr(bn
, '.'); // Does basename contain a period?
307 if(newbn
== NULL
) { // Does NOT contain a period.
309 strncpyX(newbn
, ".efi", MAXPATHLEN
- bnlen
); // append ".efi" to basename
312 else if(strcmp(newbn
, ".efi") != 0) {
313 return 0; // File can not be executable.
315 joinpath(filename
, bn
); // Stitch path and file name back together
317 if (stat(filename
, &buf
) != 0) { // Now, verify that file exists
320 if(S_ISDIR(buf
.st_mode
)) { // And it is not a directory.
327 /** Copy p into path, ensuring that the result is an absolute path.
329 copy_absolute requires that path be allocated at least
330 MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes.
332 @param[out] path Destination to receive the absolute path.
333 @param[in] p Path to be tested and possibly converted.
336 copy_absolute(char *path
, char *p
)
338 if (is_absolute(p
) == 1)
341 if (!getcwd(path
, MAXPATHLEN
)) {
342 /* unable to get the current directory */
343 if(volume_name
[0] != 0) {
344 strcpy(path
, volume_name
);
351 if (p
[0] == '.' && is_sep(p
[1]))
357 /** Modify path so that the result is an absolute path.
358 absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes.
360 @param[in,out] path The path to be made absolute.
363 absolutize(char *path
)
365 char buffer
[MAXPATHLEN
+ 1];
367 if (is_absolute(path
) == 1)
369 copy_absolute(buffer
, path
);
370 strcpy(path
, buffer
);
373 /** Extract the volume name from a path.
375 @param[out] Dest Pointer to location in which to store the extracted volume name.
376 @param[in] path Pointer to the path to extract the volume name from.
379 set_volume(char *Dest
, char *path
)
383 if(is_absolute(path
)) {
384 VolLen
= strcspn(path
, "/\\:");
385 if((VolLen
!= 0) && (path
[VolLen
] == ':')) {
386 (void) strncpyX(Dest
, path
, VolLen
+ 1);
394 Two directories must be found, the platform independent directory
395 (prefix), containing the common .py and .pyc files, and the platform
396 dependent directory (exec_prefix), containing the shared library
397 modules. Note that prefix and exec_prefix are the same directory
398 for UEFI installations.
400 Separate searches are carried out for prefix and exec_prefix.
401 Each search tries a number of different locations until a ``landmark''
402 file or directory is found. If no prefix or exec_prefix is found, a
403 warning message is issued and the preprocessor defined PREFIX and
404 EXEC_PREFIX are used (even though they may not work); python carries on
405 as best as is possible, but some imports may fail.
407 Before any searches are done, the location of the executable is
408 determined. If argv[0] has one or more slashes in it, it is used
409 unchanged. Otherwise, it must have been invoked from the shell's path,
410 so we search %PATH% for the named executable and use that. If the
411 executable was not found on %PATH% (or there was no %PATH% environment
412 variable), the original argv[0] string is used.
414 Finally, argv0_path is set to the directory containing the executable
415 (i.e. the last component is stripped).
417 With argv0_path in hand, we perform a number of steps. The same steps
418 are performed for prefix and for exec_prefix, but with a different
421 The prefix landmark will always be lib/python.VERSION/os.py and the
422 exec_prefix will always be lib/python.VERSION/dynaload, where VERSION
423 is Python's version number as defined at the beginning of this file.
425 First. See if the %PYTHONHOME% environment variable points to the
426 installed location of the Python libraries. If %PYTHONHOME% is set, then
427 it points to prefix and exec_prefix. %PYTHONHOME% can be a single
428 directory, which is used for both, or the prefix and exec_prefix
429 directories separated by the DELIM character.
431 Next. Search the directories pointed to by the preprocessor variables
432 PREFIX and EXEC_PREFIX. These paths are prefixed with the volume name
433 extracted from argv0_path. The volume names correspond to the UEFI
438 Well, almost. Once we have determined prefix and exec_prefix, the
439 preprocessor variable PYTHONPATH is used to construct a path. Each
440 relative path on PYTHONPATH is prefixed with prefix. Then the directory
441 containing the shared library modules is appended. The environment
442 variable $PYTHONPATH is inserted in front of it all. Finally, the
443 prefix and exec_prefix globals are tweaked so they reflect the values
444 expected by other code, by stripping the "lib/python$VERSION/..." stuff
445 off. This seems to make more sense given that currently the only
446 known use of sys.prefix and sys.exec_prefix is for the ILU installation
447 process to find the installed Python tree.
449 The final, fully resolved, paths should look something like:
450 fs0:/Efi/Tools/python.efi
451 fs0:/Efi/StdLib/lib/python27
452 fs0:/Efi/StdLib/lib/python27/dynaload
458 extern char *Py_GetProgramName(void);
460 static char delimiter
[2] = {DELIM
, '\0'};
461 static char separator
[2] = {SEP
, '\0'};
462 char *pythonpath
= PYTHONPATH
;
463 char *rtpypath
= Py_GETENV("PYTHONPATH");
464 //char *home = Py_GetPythonHome();
465 char *path
= getenv("PATH");
466 char *prog
= Py_GetProgramName();
467 char argv0_path
[MAXPATHLEN
+1];
468 char zip_path
[MAXPATHLEN
+1];
475 /* ###########################################################################
476 Determine path to the Python.efi binary.
477 Produces progpath, argv0_path, and volume_name.
478 ########################################################################### */
480 /* If there is no slash in the argv0 path, then we have to
481 * assume python is on the user's $PATH, since there's no
482 * other way to find a directory to start the search from. If
483 * $PATH isn't exported, you lose.
485 if (strchr(prog
, SEP
))
486 strncpy(progpath
, prog
, MAXPATHLEN
);
489 char *delim
= strchr(path
, DELIM
);
492 size_t len
= delim
- path
;
493 if (len
> MAXPATHLEN
)
495 strncpy(progpath
, path
, len
);
496 *(progpath
+ len
) = '\0';
499 strncpy(progpath
, path
, MAXPATHLEN
);
501 joinpath(progpath
, prog
);
502 if (isxfile(progpath
))
514 if ( (!is_absolute(progpath
)) && (progpath
[0] != '\0') )
515 absolutize(progpath
);
516 strncpy(argv0_path
, progpath
, MAXPATHLEN
);
517 argv0_path
[MAXPATHLEN
] = '\0';
518 set_volume(volume_name
, argv0_path
);
521 /* At this point, argv0_path is guaranteed to be less than
522 MAXPATHLEN bytes long.
525 /* ###########################################################################
526 Build the FULL prefix string, including volume name.
527 This is the full path to the platform independent libraries.
528 ########################################################################### */
530 strncpy(prefix
, volume_name
, MAXPATHLEN
);
531 joinpath(prefix
, PREFIX
);
532 joinpath(prefix
, lib_python
);
534 /* ###########################################################################
535 Build the FULL path to the zipped-up Python library.
536 ########################################################################### */
538 strncpy(zip_path
, prefix
, MAXPATHLEN
);
539 zip_path
[MAXPATHLEN
] = '\0';
541 joinpath(zip_path
, "python00.zip");
542 bufsz
= strlen(zip_path
); /* Replace "00" with version */
543 zip_path
[bufsz
- 6] = VERSION
[0];
544 zip_path
[bufsz
- 5] = VERSION
[1];
546 /* ###########################################################################
547 Build the FULL path to dynamically loadable libraries.
548 ########################################################################### */
550 strncpy(exec_prefix
, volume_name
, MAXPATHLEN
);
551 joinpath(exec_prefix
, EXEC_PREFIX
);
552 joinpath(exec_prefix
, lib_python
);
553 joinpath(exec_prefix
, "lib-dynload");
555 /* ###########################################################################
556 Build the module search path.
557 ########################################################################### */
559 /* Reduce prefix and exec_prefix to their essence,
560 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local.
561 * If we're loading relative to the build directory,
562 * return the compiled-in defaults instead.
566 /* The prefix is the root directory, but reduce() chopped
569 strcpy(prefix
, volume_name
);
571 bufsz
= strlen(prefix
);
572 if(prefix
[bufsz
-1] == ':') {
577 /* Calculate size of return buffer.
579 defpath
= pythonpath
;
583 bufsz
+= strlen(rtpypath
) + 1;
585 prefixsz
= strlen(prefix
) + 1;
588 char *delim
= strchr(defpath
, DELIM
);
590 if (is_absolute(defpath
) == 0)
591 /* Paths are relative to prefix */
595 bufsz
+= delim
- defpath
+ 1;
597 bufsz
+= strlen(defpath
) + 1;
603 bufsz
+= strlen(zip_path
) + 1;
604 bufsz
+= strlen(exec_prefix
) + 1;
606 /* This is the only malloc call in this file */
607 buf
= (char *)PyMem_Malloc(bufsz
);
610 /* We can't exit, so print a warning and limp along */
611 fprintf(stderr
, "Not enough memory for dynamic PYTHONPATH.\n");
612 fprintf(stderr
, "Using default static PYTHONPATH.\n");
613 module_search_path
= PYTHONPATH
;
616 /* Run-time value of $PYTHONPATH goes first */
618 strcpy(buf
, rtpypath
);
619 strcat(buf
, delimiter
);
624 /* Next is the default zip path */
625 strcat(buf
, zip_path
);
626 strcat(buf
, delimiter
);
628 /* Next goes merge of compile-time $PYTHONPATH with
629 * dynamically located prefix.
631 defpath
= pythonpath
;
633 char *delim
= strchr(defpath
, DELIM
);
635 if (is_absolute(defpath
) != 1) {
637 strcat(buf
, separator
);
641 size_t len
= delim
- defpath
+ 1;
642 size_t end
= strlen(buf
) + len
;
643 strncat(buf
, defpath
, len
);
647 strcat(buf
, defpath
);
652 strcat(buf
, delimiter
);
654 /* Finally, on goes the directory for dynamic-load modules */
655 strcat(buf
, exec_prefix
);
657 /* And publish the results */
658 module_search_path
= buf
;
660 /* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib.
661 We want to get back to the root value, so we have to remove the final three
662 segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and
663 EXEC_PREFIX is also indeterminate, we just remove the three final segments.
668 if (!exec_prefix
[0]) {
669 strcpy(exec_prefix
, volume_name
);
671 bufsz
= strlen(exec_prefix
);
672 if(exec_prefix
[bufsz
-1] == ':') {
673 exec_prefix
[bufsz
] = SEP
;
674 exec_prefix
[bufsz
+1] = 0;
676 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__
, __LINE__
, module_search_path
);
677 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__
, __LINE__
, prefix
);
678 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__
, __LINE__
, exec_prefix
);
679 if (Py_VerboseFlag
) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__
, __LINE__
, progpath
);
683 /* External interface */
688 if (!module_search_path
)
690 return module_search_path
;
696 if (!module_search_path
)
702 Py_GetExecPrefix(void)
704 if (!module_search_path
)
710 Py_GetProgramFullPath(void)
712 if (!module_search_path
)