1 /** @file 2 Return the initial module search path. 3 4 Search in specified locations for the associated Python libraries. 5 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. 10 11 These are built dynamically so that the proper volume name can be prefixed 12 to the paths. 13 14 For the EDK II, UEFI, implementation of Python, PREFIX and EXEC_PREFIX 15 are set as follows: 16 PREFIX = /Efi/StdLib 17 EXEC_PREFIX = PREFIX 18 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. 23 24 Copyright (c) 2011 - 2012, 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. 29 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. 32 **/ 33 #include <Python.h> 34 #include <osdefs.h> 35 #include <ctype.h> 36 37 #ifdef __cplusplus 38 extern "C" { 39 #endif 40 41 /* VERSION must be at least two characters long. */ 42 #ifndef VERSION 43 #define VERSION "27" 44 #endif 45 46 #ifndef VPATH 47 #define VPATH "." 48 #endif 49 50 /* Search path entry delimiter */ 51 #ifdef DELIM 52 #define sDELIM ";" 53 #endif 54 55 #ifndef PREFIX 56 #define PREFIX "/Efi/StdLib" 57 #endif 58 59 #ifndef EXEC_PREFIX 60 #define EXEC_PREFIX PREFIX 61 #endif 62 63 #ifndef LIBPYTHON 64 #define LIBPYTHON "lib/python." VERSION 65 #endif 66 67 #ifndef PYTHONPATH 68 #ifdef HAVE_ENVIRONMENT_OPS 69 #define PYTHONPATH PREFIX LIBPYTHON sDELIM \ 70 EXEC_PREFIX LIBPYTHON "/lib-dynload" 71 #else 72 #define PYTHONPATH LIBPYTHON 73 #endif 74 #endif 75 76 #ifndef LANDMARK 77 #define LANDMARK "os.py" 78 #endif 79 80 static char prefix[MAXPATHLEN+1]; 81 static char exec_prefix[MAXPATHLEN+1]; 82 static char progpath[MAXPATHLEN+1]; 83 static char *module_search_path = NULL; 84 static char lib_python[] = LIBPYTHON; 85 static char volume_name[32] = { 0 }; 86 87 /** Determine if "ch" is a separator character. 88 89 @param[in] ch The character to test. 90 91 @retval TRUE ch is a separator character. 92 @retval FALSE ch is NOT a separator character. 93 **/ 94 static int 95 is_sep(char ch) 96 { 97 #ifdef ALTSEP 98 return ch == SEP || ch == ALTSEP; 99 #else 100 return ch == SEP; 101 #endif 102 } 103 104 /** Reduce a path by its last element. 105 106 The last element (everything to the right of the last separator character) 107 in the path, dir, is removed from the path. Parameter dir is modified in place. 108 109 @param[in,out] dir Pointer to the path to modify. 110 **/ 111 static void 112 reduce(char *dir) 113 { 114 size_t i = strlen(dir); 115 while (i > 0 && !is_sep(dir[i])) 116 --i; 117 dir[i] = '\0'; 118 } 119 120 #ifndef UEFI_C_SOURCE 121 /** Does filename point to a file and not directory? 122 123 @param[in] filename The fully qualified path to the object to test. 124 125 @retval 0 Filename was not found, or is a directory. 126 @retval 1 Filename refers to a regular file. 127 **/ 128 static int 129 isfile(char *filename) 130 { 131 struct stat buf; 132 if (stat(filename, &buf) != 0) { 133 return 0; 134 } 135 //if (!S_ISREG(buf.st_mode)) 136 if (S_ISDIR(buf.st_mode)) { 137 return 0; 138 } 139 return 1; 140 } 141 142 /** Determine if filename refers to a Python module. 143 144 A Python module is indicated if the file exists, or if the file with 145 'o' or 'c' appended exists. 146 147 @param[in] filename The fully qualified path to the object to test. 148 149 @retval 0 150 **/ 151 static int 152 ismodule(char *filename) 153 { 154 if (isfile(filename)) { 155 //if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: file = \"%s\"\n", __func__, __LINE__, filename); 156 return 1; 157 } 158 159 /* Check for the compiled version of prefix. */ 160 if (strlen(filename) < MAXPATHLEN) { 161 strcat(filename, Py_OptimizeFlag ? "o" : "c"); 162 if (isfile(filename)) { 163 return 1; 164 } 165 } 166 return 0; 167 } 168 169 /** Does filename point to a directory? 170 171 @param[in] filename The fully qualified path to the object to test. 172 173 @retval 0 Filename was not found, or is not a regular file. 174 @retval 1 Filename refers to a directory. 175 **/ 176 static int 177 isdir(char *filename) 178 { 179 struct stat buf; 180 181 if (stat(filename, &buf) != 0) 182 return 0; 183 184 if (!S_ISDIR(buf.st_mode)) 185 return 0; 186 187 return 1; 188 } 189 #endif /* UEFI_C_SOURCE */ 190 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. 194 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. 198 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. 202 203 @param[in] path The path to test. 204 205 @retval -1 Path is absolute but lacking volume name. 206 @retval 0 Path is NOT absolute. 207 @retval 1 Path is absolute. 208 */ 209 static int 210 is_absolute(char *path) 211 { 212 char *A; 213 char *B; 214 215 A = strchr(path, ':'); 216 B = strpbrk(path, "/\\"); 217 218 if(B != NULL) { 219 if(A == NULL) { 220 if(B == path) { 221 return -1; 222 } 223 } 224 else { 225 if(((A - path) + 1) == (B - path)) { 226 return 1; 227 } 228 } 229 } 230 return 0; 231 } 232 233 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. 242 243 @param[in,out] buffer The path to be extended. 244 @param[in] stuff The stuff to join onto the path. 245 */ 246 static void 247 joinpath(char *buffer, char *stuff) 248 { 249 size_t n, k; 250 251 k = 0; 252 if (is_absolute(stuff) == 1) { 253 n = 0; 254 } 255 else { 256 n = strlen(buffer); 257 if(n == 0) { 258 strncpy(buffer, volume_name, MAXPATHLEN); 259 n = strlen(buffer); 260 } 261 /* We must not use an else clause here because we want to test n again. 262 volume_name may have been empty. 263 */ 264 if (n > 0 && n < MAXPATHLEN) { 265 if(!is_sep(buffer[n-1])) { 266 buffer[n++] = SEP; 267 } 268 if(is_sep(stuff[0])) ++stuff; 269 } 270 } 271 if (n > MAXPATHLEN) 272 Py_FatalError("buffer overflow in getpath.c's joinpath()"); 273 k = strlen(stuff); 274 if (n + k > MAXPATHLEN) 275 k = MAXPATHLEN - n; 276 strncpy(buffer+n, stuff, k); 277 buffer[n+k] = '\0'; 278 } 279 280 /** Is filename an executable file? 281 282 An executable file: 283 1) exists 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. 287 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. 290 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". 293 294 @param[in] filename The name of the file to test. It may, or may not, have an extension. 295 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. 298 **/ 299 static int 300 isxfile(char *filename) 301 { 302 struct stat buf; 303 char *bn; 304 char *newbn; 305 int bnlen; 306 307 bn = basename(filename); // Separate off the file name component 308 reduce(filename); // and isolate the path component 309 bnlen = strlen(bn); 310 newbn = strrchr(bn, '.'); // Does basename contain a period? 311 if(newbn == NULL) { // Does NOT contain a period. 312 newbn = &bn[bnlen]; 313 strncpyX(newbn, ".efi", MAXPATHLEN - bnlen); // append ".efi" to basename 314 bnlen += 4; 315 } 316 else if(strcmp(newbn, ".efi") != 0) { 317 return 0; // File can not be executable. 318 } 319 joinpath(filename, bn); // Stitch path and file name back together 320 321 if (stat(filename, &buf) != 0) { // Now, verify that file exists 322 return 0; 323 } 324 if(S_ISDIR(buf.st_mode)) { // And it is not a directory. 325 return 0; 326 } 327 328 return 1; 329 } 330 331 /** Copy p into path, ensuring that the result is an absolute path. 332 333 copy_absolute requires that path be allocated at least 334 MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. 335 336 @param[out] path Destination to receive the absolute path. 337 @param[in] p Path to be tested and possibly converted. 338 **/ 339 static void 340 copy_absolute(char *path, char *p) 341 { 342 if (is_absolute(p) == 1) 343 strcpy(path, p); 344 else { 345 if (!getcwd(path, MAXPATHLEN)) { 346 /* unable to get the current directory */ 347 if(volume_name[0] != 0) { 348 strcpy(path, volume_name); 349 joinpath(path, p); 350 } 351 else 352 strcpy(path, p); 353 return; 354 } 355 if (p[0] == '.' && is_sep(p[1])) 356 p += 2; 357 joinpath(path, p); 358 } 359 } 360 361 /** Modify path so that the result is an absolute path. 362 absolutize() requires that path be allocated at least MAXPATHLEN+1 bytes. 363 364 @param[in,out] path The path to be made absolute. 365 */ 366 static void 367 absolutize(char *path) 368 { 369 char buffer[MAXPATHLEN + 1]; 370 371 if (is_absolute(path) == 1) 372 return; 373 copy_absolute(buffer, path); 374 strcpy(path, buffer); 375 } 376 377 /** Extract the volume name from a path. 378 379 @param[out] Dest Pointer to location in which to store the extracted volume name. 380 @param[in] path Pointer to the path to extract the volume name from. 381 **/ 382 static void 383 set_volume(char *Dest, char *path) 384 { 385 size_t VolLen; 386 387 if(is_absolute(path)) { 388 VolLen = strcspn(path, "/\\:"); 389 if((VolLen != 0) && (path[VolLen] == ':')) { 390 (void) strncpyX(Dest, path, VolLen + 1); 391 } 392 } 393 } 394 395 396 /** Determine paths. 397 398 Two directories must be found, the platform independent directory 399 (prefix), containing the common .py and .pyc files, and the platform 400 dependent directory (exec_prefix), containing the shared library 401 modules. Note that prefix and exec_prefix are the same directory 402 for UEFI installations. 403 404 Separate searches are carried out for prefix and exec_prefix. 405 Each search tries a number of different locations until a ``landmark'' 406 file or directory is found. If no prefix or exec_prefix is found, a 407 warning message is issued and the preprocessor defined PREFIX and 408 EXEC_PREFIX are used (even though they may not work); python carries on 409 as best as is possible, but some imports may fail. 410 411 Before any searches are done, the location of the executable is 412 determined. If argv[0] has one or more slashes in it, it is used 413 unchanged. Otherwise, it must have been invoked from the shell's path, 414 so we search %PATH% for the named executable and use that. If the 415 executable was not found on %PATH% (or there was no %PATH% environment 416 variable), the original argv[0] string is used. 417 418 Finally, argv0_path is set to the directory containing the executable 419 (i.e. the last component is stripped). 420 421 With argv0_path in hand, we perform a number of steps. The same steps 422 are performed for prefix and for exec_prefix, but with a different 423 landmark. 424 425 The prefix landmark will always be lib/python.VERSION/os.py and the 426 exec_prefix will always be lib/python.VERSION/dynaload, where VERSION 427 is Python's version number as defined at the beginning of this file. 428 429 First. See if the %PYTHONHOME% environment variable points to the 430 installed location of the Python libraries. If %PYTHONHOME% is set, then 431 it points to prefix and exec_prefix. %PYTHONHOME% can be a single 432 directory, which is used for both, or the prefix and exec_prefix 433 directories separated by the DELIM character. 434 435 Next. Search the directories pointed to by the preprocessor variables 436 PREFIX and EXEC_PREFIX. These paths are prefixed with the volume name 437 extracted from argv0_path. The volume names correspond to the UEFI 438 shell "map" names. 439 440 That's it! 441 442 Well, almost. Once we have determined prefix and exec_prefix, the 443 preprocessor variable PYTHONPATH is used to construct a path. Each 444 relative path on PYTHONPATH is prefixed with prefix. Then the directory 445 containing the shared library modules is appended. The environment 446 variable $PYTHONPATH is inserted in front of it all. Finally, the 447 prefix and exec_prefix globals are tweaked so they reflect the values 448 expected by other code, by stripping the "lib/python$VERSION/..." stuff 449 off. This seems to make more sense given that currently the only 450 known use of sys.prefix and sys.exec_prefix is for the ILU installation 451 process to find the installed Python tree. 452 453 The final, fully resolved, paths should look something like: 454 fs0:/Efi/Tools/python.efi 455 fs0:/Efi/StdLib/lib/python27 456 fs0:/Efi/StdLib/lib/python27/dynaload 457 458 **/ 459 static void 460 calculate_path(void) 461 { 462 extern char *Py_GetProgramName(void); 463 464 static char delimiter[2] = {DELIM, '\0'}; 465 static char separator[2] = {SEP, '\0'}; 466 char *pythonpath = PYTHONPATH; 467 char *rtpypath = Py_GETENV("PYTHONPATH"); 468 //char *home = Py_GetPythonHome(); 469 char *path = getenv("PATH"); 470 char *prog = Py_GetProgramName(); 471 char argv0_path[MAXPATHLEN+1]; 472 char zip_path[MAXPATHLEN+1]; 473 char *buf; 474 size_t bufsz; 475 size_t prefixsz; 476 char *defpath; 477 478 479 /* ########################################################################### 480 Determine path to the Python.efi binary. 481 Produces progpath, argv0_path, and volume_name. 482 ########################################################################### */ 483 484 /* If there is no slash in the argv0 path, then we have to 485 * assume python is on the user's $PATH, since there's no 486 * other way to find a directory to start the search from. If 487 * $PATH isn't exported, you lose. 488 */ 489 if (strchr(prog, SEP)) 490 strncpy(progpath, prog, MAXPATHLEN); 491 else if (path) { 492 while (1) { 493 char *delim = strchr(path, DELIM); 494 495 if (delim) { 496 size_t len = delim - path; 497 if (len > MAXPATHLEN) 498 len = MAXPATHLEN; 499 strncpy(progpath, path, len); 500 *(progpath + len) = '\0'; 501 } 502 else 503 strncpy(progpath, path, MAXPATHLEN); 504 505 joinpath(progpath, prog); 506 if (isxfile(progpath)) 507 break; 508 509 if (!delim) { 510 progpath[0] = '\0'; 511 break; 512 } 513 path = delim + 1; 514 } 515 } 516 else 517 progpath[0] = '\0'; 518 if ( (!is_absolute(progpath)) && (progpath[0] != '\0') ) 519 absolutize(progpath); 520 strncpy(argv0_path, progpath, MAXPATHLEN); 521 argv0_path[MAXPATHLEN] = '\0'; 522 set_volume(volume_name, argv0_path); 523 524 reduce(argv0_path); 525 /* At this point, argv0_path is guaranteed to be less than 526 MAXPATHLEN bytes long. 527 */ 528 529 /* ########################################################################### 530 Build the FULL prefix string, including volume name. 531 This is the full path to the platform independent libraries. 532 ########################################################################### */ 533 534 strncpy(prefix, volume_name, MAXPATHLEN); 535 joinpath(prefix, PREFIX); 536 joinpath(prefix, lib_python); 537 538 /* ########################################################################### 539 Build the FULL path to the zipped-up Python library. 540 ########################################################################### */ 541 542 strncpy(zip_path, prefix, MAXPATHLEN); 543 zip_path[MAXPATHLEN] = '\0'; 544 reduce(zip_path); 545 joinpath(zip_path, "python00.zip"); 546 bufsz = strlen(zip_path); /* Replace "00" with version */ 547 zip_path[bufsz - 6] = VERSION[0]; 548 zip_path[bufsz - 5] = VERSION[1]; 549 550 /* ########################################################################### 551 Build the FULL path to dynamically loadable libraries. 552 ########################################################################### */ 553 554 strncpy(exec_prefix, volume_name, MAXPATHLEN); 555 joinpath(exec_prefix, EXEC_PREFIX); 556 joinpath(exec_prefix, lib_python); 557 joinpath(exec_prefix, "lib-dynload"); 558 559 /* ########################################################################### 560 Build the module search path. 561 ########################################################################### */ 562 563 /* Reduce prefix and exec_prefix to their essence, 564 * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. 565 * If we're loading relative to the build directory, 566 * return the compiled-in defaults instead. 567 */ 568 reduce(prefix); 569 reduce(prefix); 570 /* The prefix is the root directory, but reduce() chopped 571 * off the "/". */ 572 if (!prefix[0]) { 573 strcpy(prefix, volume_name); 574 } 575 bufsz = strlen(prefix); 576 if(prefix[bufsz-1] == ':') { 577 prefix[bufsz] = SEP; 578 prefix[bufsz+1] = 0; 579 } 580 581 /* Calculate size of return buffer. 582 */ 583 defpath = pythonpath; 584 bufsz = 0; 585 586 if (rtpypath) 587 bufsz += strlen(rtpypath) + 1; 588 589 prefixsz = strlen(prefix) + 1; 590 591 while (1) { 592 char *delim = strchr(defpath, DELIM); 593 594 if (is_absolute(defpath) == 0) 595 /* Paths are relative to prefix */ 596 bufsz += prefixsz; 597 598 if (delim) 599 bufsz += delim - defpath + 1; 600 else { 601 bufsz += strlen(defpath) + 1; 602 break; 603 } 604 defpath = delim + 1; 605 } 606 607 bufsz += strlen(zip_path) + 1; 608 bufsz += strlen(exec_prefix) + 1; 609 610 /* This is the only malloc call in this file */ 611 buf = (char *)PyMem_Malloc(bufsz); 612 613 if (buf == NULL) { 614 /* We can't exit, so print a warning and limp along */ 615 fprintf(stderr, "Not enough memory for dynamic PYTHONPATH.\n"); 616 fprintf(stderr, "Using default static PYTHONPATH.\n"); 617 module_search_path = PYTHONPATH; 618 } 619 else { 620 /* Run-time value of $PYTHONPATH goes first */ 621 if (rtpypath) { 622 strcpy(buf, rtpypath); 623 strcat(buf, delimiter); 624 } 625 else 626 buf[0] = '\0'; 627 628 /* Next is the default zip path */ 629 strcat(buf, zip_path); 630 strcat(buf, delimiter); 631 632 /* Next goes merge of compile-time $PYTHONPATH with 633 * dynamically located prefix. 634 */ 635 defpath = pythonpath; 636 while (1) { 637 char *delim = strchr(defpath, DELIM); 638 639 if (is_absolute(defpath) != 1) { 640 strcat(buf, prefix); 641 strcat(buf, separator); 642 } 643 644 if (delim) { 645 size_t len = delim - defpath + 1; 646 size_t end = strlen(buf) + len; 647 strncat(buf, defpath, len); 648 *(buf + end) = '\0'; 649 } 650 else { 651 strcat(buf, defpath); 652 break; 653 } 654 defpath = delim + 1; 655 } 656 strcat(buf, delimiter); 657 658 /* Finally, on goes the directory for dynamic-load modules */ 659 strcat(buf, exec_prefix); 660 661 /* And publish the results */ 662 module_search_path = buf; 663 } 664 /* At this point, exec_prefix is set to VOL:/Efi/StdLib/lib/python.27/dynalib. 665 We want to get back to the root value, so we have to remove the final three 666 segments to get VOL:/Efi/StdLib. Because we don't know what VOL is, and 667 EXEC_PREFIX is also indeterminate, we just remove the three final segments. 668 */ 669 reduce(exec_prefix); 670 reduce(exec_prefix); 671 reduce(exec_prefix); 672 if (!exec_prefix[0]) { 673 strcpy(exec_prefix, volume_name); 674 } 675 bufsz = strlen(exec_prefix); 676 if(exec_prefix[bufsz-1] == ':') { 677 exec_prefix[bufsz] = SEP; 678 exec_prefix[bufsz+1] = 0; 679 } 680 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: module_search_path = \"%s\"\n", __func__, __LINE__, module_search_path); 681 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: prefix = \"%s\"\n", __func__, __LINE__, prefix); 682 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: exec_prefix = \"%s\"\n", __func__, __LINE__, exec_prefix); 683 if (Py_VerboseFlag) PySys_WriteStderr("%s[%d]: progpath = \"%s\"\n", __func__, __LINE__, progpath); 684 } 685 686 687 /* External interface */ 688 689 char * 690 Py_GetPath(void) 691 { 692 if (!module_search_path) 693 calculate_path(); 694 return module_search_path; 695 } 696 697 char * 698 Py_GetPrefix(void) 699 { 700 if (!module_search_path) 701 calculate_path(); 702 return prefix; 703 } 704 705 char * 706 Py_GetExecPrefix(void) 707 { 708 if (!module_search_path) 709 calculate_path(); 710 return exec_prefix; 711 } 712 713 char * 714 Py_GetProgramFullPath(void) 715 { 716 if (!module_search_path) 717 calculate_path(); 718 return progpath; 719 } 720 721 722 #ifdef __cplusplus 723 } 724 #endif 725 726