LCOV - code coverage report
Current view: top level - Python - dynload_shlib.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 20 30 66.7 %
Date: 2017-04-19 Functions: 1 1 100.0 %

          Line data    Source code
       1             : 
       2             : /* Support for dynamic loading of extension modules */
       3             : 
       4             : #include "Python.h"
       5             : #include "importdl.h"
       6             : 
       7             : #include <sys/types.h>
       8             : #include <sys/stat.h>
       9             : 
      10             : #if defined(__NetBSD__)
      11             : #include <sys/param.h>
      12             : #if (NetBSD < 199712)
      13             : #include <nlist.h>
      14             : #include <link.h>
      15             : #define dlerror() "error in dynamic linking"
      16             : #endif
      17             : #endif /* NetBSD */
      18             : 
      19             : #ifdef HAVE_DLFCN_H
      20             : #include <dlfcn.h>
      21             : #else
      22             : #if defined(PYOS_OS2) && defined(PYCC_GCC)
      23             : #include "dlfcn.h"
      24             : #endif
      25             : #endif
      26             : 
      27             : #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
      28             : #define LEAD_UNDERSCORE "_"
      29             : #else
      30             : #define LEAD_UNDERSCORE ""
      31             : #endif
      32             : 
      33             : 
      34             : const struct filedescr _PyImport_DynLoadFiletab[] = {
      35             : #ifdef __CYGWIN__
      36             :     {".dll", "rb", C_EXTENSION},
      37             :     {"module.dll", "rb", C_EXTENSION},
      38             : #else
      39             : #if defined(PYOS_OS2) && defined(PYCC_GCC)
      40             :     {".pyd", "rb", C_EXTENSION},
      41             :     {".dll", "rb", C_EXTENSION},
      42             : #else
      43             : #ifdef __VMS
      44             :     {".exe", "rb", C_EXTENSION},
      45             :     {".EXE", "rb", C_EXTENSION},
      46             :     {"module.exe", "rb", C_EXTENSION},
      47             :     {"MODULE.EXE", "rb", C_EXTENSION},
      48             : #else
      49             :     {".so", "rb", C_EXTENSION},
      50             :     {"module.so", "rb", C_EXTENSION},
      51             : #endif
      52             : #endif
      53             : #endif
      54             :     {0, 0}
      55             : };
      56             : 
      57             : static struct {
      58             :     dev_t dev;
      59             : #ifdef __VMS
      60             :     ino_t ino[3];
      61             : #else
      62             :     ino_t ino;
      63             : #endif
      64             :     void *handle;
      65             : } handles[128];
      66             : static int nhandles = 0;
      67             : 
      68             : 
      69          54 : dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
      70             :                                     const char *pathname, FILE *fp)
      71             : {
      72             :     dl_funcptr p;
      73             :     void *handle;
      74             :     char funcname[258];
      75             :     char pathbuf[260];
      76          54 :     int dlopenflags=0;
      77             : 
      78             :     /* DISABLING FOR OIL */
      79             : #ifdef DISABLE_DLOPEN_FOR_OIL
      80             :     printf("GetDynLoadFunc fq:%s short:%s path:%s -> DISABLED\n",
      81             :            fqname, shortname, pathname);
      82             :     PyErr_SetString(PyExc_ImportError, "Oil doesn't allow dynamic modules");
      83             :     return NULL;
      84             : #endif
      85             : 
      86          54 :     if (strchr(pathname, '/') == NULL) {
      87             :         /* Prefix bare filename with "./" */
      88           0 :         PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
      89           0 :         pathname = pathbuf;
      90             :     }
      91             : 
      92          54 :     PyOS_snprintf(funcname, sizeof(funcname),
      93             :                   LEAD_UNDERSCORE "init%.200s", shortname);
      94             : 
      95          54 :     if (fp != NULL) {
      96             :         int i;
      97             :         struct stat statb;
      98          54 :         fstat(fileno(fp), &statb);
      99         513 :         for (i = 0; i < nhandles; i++) {
     100         918 :             if (statb.st_dev == handles[i].dev &&
     101         459 :                 statb.st_ino == handles[i].ino) {
     102           0 :                 p = (dl_funcptr) dlsym(handles[i].handle,
     103             :                                        funcname);
     104           0 :                 return p;
     105             :             }
     106             :         }
     107          54 :         if (nhandles < 128) {
     108          54 :             handles[nhandles].dev = statb.st_dev;
     109             : #ifdef __VMS
     110             :             handles[nhandles].ino[0] = statb.st_ino[0];
     111             :             handles[nhandles].ino[1] = statb.st_ino[1];
     112             :             handles[nhandles].ino[2] = statb.st_ino[2];
     113             : #else
     114          54 :             handles[nhandles].ino = statb.st_ino;
     115             : #endif
     116             :         }
     117             :     }
     118             : 
     119             : #if !(defined(PYOS_OS2) && defined(PYCC_GCC))
     120          54 :     dlopenflags = PyThreadState_GET()->interp->dlopenflags;
     121             : #endif
     122             : 
     123          54 :     if (Py_VerboseFlag)
     124           0 :         PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
     125             :                           dlopenflags);
     126             : 
     127             : #ifdef __VMS
     128             :     /* VMS currently don't allow a pathname, use a logical name instead */
     129             :     /* Concatenate 'python_module_' and shortname */
     130             :     /* so "import vms.bar" will use the logical python_module_bar */
     131             :     /* As C module use only one name space this is probably not a */
     132             :     /* important limitation */
     133             :     PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
     134             :                   shortname);
     135             :     pathname = pathbuf;
     136             : #endif
     137             : 
     138          54 :     handle = dlopen(pathname, dlopenflags);
     139             : 
     140          54 :     if (handle == NULL) {
     141           0 :         const char *error = dlerror();
     142           0 :         if (error == NULL)
     143           0 :             error = "unknown dlopen() error";
     144           0 :         PyErr_SetString(PyExc_ImportError, error);
     145           0 :         return NULL;
     146             :     }
     147          54 :     if (fp != NULL && nhandles < 128)
     148          54 :         handles[nhandles++].handle = handle;
     149          54 :     p = (dl_funcptr) dlsym(handle, funcname);
     150          54 :     return p;
     151             : }

Generated by: LCOV version 1.10