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