static int do_open_via_path(const char *dir, const char *name, const char *ext, char *dirresult, char **nameresult, unsigned int size, int bin, t_namelist *searchpath) { t_namelist *nl; int fd = -1; /* first check if "name" is absolute (and if so, try to open) */ if (sys_open_absolute(name, ext, dirresult, nameresult, size, bin, &fd)) return (fd); /* otherwise "name" is relative; try the directory "dir" first. */ if ((fd = sys_trytoopenone(dir, name, ext, dirresult, nameresult, size, bin)) >= 0) return (fd); /* next go through the search path */ for (nl = searchpath; nl; nl = nl->nl_next) if ((fd = sys_trytoopenone(nl->nl_string, name, ext, dirresult, nameresult, size, bin)) >= 0) return (fd); /* next look in built-in paths like "extra" */ if (sys_usestdpath) for (nl = sys_staticpath; nl; nl = nl->nl_next) if ((fd = sys_trytoopenone(nl->nl_string, name, ext, dirresult, nameresult, size, bin)) >= 0) return (fd); *dirresult = 0; *nameresult = dirresult; return (-1); }
static int libdir_loader_pathwise(t_canvas *canvas, const char *classname, const char*path) { int fd = -1; char fullclassname[FILENAME_MAX], dirbuf[FILENAME_MAX]; char *nameptr; if(!path) { /* we already tried all paths, so skip this */ return 0; } /* look for meta file (classname)/(classname)-meta.pd */ libdir_get_fullname(fullclassname, FILENAME_MAX, classname); if ((fd = sys_trytoopenone(path, fullclassname, ".pd", dirbuf, &nameptr, FILENAME_MAX, 0)) < 0) { return 0; } sys_close(fd); if(libdir_add_to_path(dirbuf, canvas)) logpost(NULL, 3, "libdir_loader: added '%s' to the %s objectclass path", classname, canvas?"canvas-local":"global"); /* post("libdir_loader loaded fullclassname: '%s'\n", fullclassname); */ logpost(NULL, 14, "Loaded libdir '%s' from '%s'", classname, dirbuf); return (1); }
/* search for abstraction; register a creator if found */ static int sys_do_load_abs(t_canvas *canvas, const char *objectname, const char *path) { int fd; static t_gobj*abstraction_classes = 0; char dirbuf[MAXPDSTRING], classslashclass[MAXPDSTRING], *nameptr; /* NULL-path is only used as a last resort, but we have already tried all paths */ if (!path) return (0); snprintf(classslashclass, MAXPDSTRING, "%s/%s", objectname, objectname); if ((fd = sys_trytoopenone(path, objectname, ".pd", dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0 || (fd = sys_trytoopenone(path, objectname, ".pat", dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0 || (fd = sys_trytoopenone(path, classslashclass, ".pd", dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) { t_class*c=0; close(fd); /* found an abstraction, now register it as a new pseudo-class */ class_set_extern_dir(gensym(dirbuf)); if((c=class_new(gensym(objectname), (t_newmethod)do_create_abstraction, 0, 0, 0, A_GIMME, 0))) { /* store away the newly created class, maybe we will need it one day */ t_gobj*absclass=0; absclass=t_getbytes(sizeof(*absclass)); absclass->g_pd=c; absclass->g_next=abstraction_classes; abstraction_classes=absclass; } class_set_extern_dir(&s_); return (1); } return (0); }
static int do_open_via_path(const char *dir, const char *name, const char *ext, char *dirresult, char **nameresult, unsigned int size, int bin, t_namelist *searchpath) { t_namelist *nl; int fd = -1; char final_name[FILENAME_MAX]; /* first check for @ and ~ (and later others) and replace */ sys_expandpathelems(name, final_name); /* first check if "name" is absolute (and if so, try to open) */ if (sys_open_absolute(final_name, ext, dirresult, nameresult, size, bin, &fd)) goto do_open_via_path_end; /* otherwise "name" is relative; try the directory "dir" first. */ if ((fd = sys_trytoopenone(dir, final_name, ext, dirresult, nameresult, size, bin)) >= 0) goto do_open_via_path_end; /* next go through the search path */ for (nl = searchpath; nl; nl = nl->nl_next) if ((fd = sys_trytoopenone(nl->nl_string, final_name, ext, dirresult, nameresult, size, bin)) >= 0) goto do_open_via_path_end; /* next look in built-in paths like "extra" */ if (sys_usestdpath) for (nl = pd_extrapath; nl; nl = nl->nl_next) if ((fd = sys_trytoopenone(nl->nl_string, final_name, ext, dirresult, nameresult, size, bin)) >= 0) goto do_open_via_path_end; *dirresult = 0; *nameresult = dirresult; return (-1); do_open_via_path_end: return (fd); }
/* check if we were given an absolute pathname, if so try to open it and return 1 to signal the caller to cancel any path searches */ int sys_open_absolute(const char *name, const char* ext, char *dirresult, char **nameresult, unsigned int size, int bin, int *fdp) { if (sys_isabsolutepath(name)) { char dirbuf[MAXPDSTRING], *z = strrchr(name, '/'); int dirlen; if (!z) return (0); dirlen = z - name; if (dirlen > MAXPDSTRING-1) dirlen = MAXPDSTRING-1; strncpy(dirbuf, name, dirlen); dirbuf[dirlen] = 0; *fdp = sys_trytoopenone(dirbuf, name+(dirlen+1), ext, dirresult, nameresult, size, bin); return (1); } else return (0); }
static int sys_do_load_lib(t_canvas *canvas, const char *objectname, const char *path) { char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING], *nameptr; const char**dllextent; const char *classname, *cnameptr; void *dlobj; t_xxx makeout = NULL; int i, hexmunge = 0, fd; #ifdef _WIN32 HINSTANCE ntdll; #endif /* NULL-path is only used as a last resort, but we have already tried all paths */ if(!path)return (0); if ((classname = strrchr(objectname, '/'))) classname++; else classname = objectname; for (i = 0, cnameptr = classname; i < MAXPDSTRING-7 && *cnameptr; cnameptr++) { char c = *cnameptr; if ((c>='0' && c<='9') || (c>='A' && c<='Z')|| (c>='a' && c<='z' )|| c == '_') { symname[i] = c; i++; } /* trailing tilde becomes "_tilde" */ else if (c == '~' && cnameptr[1] == 0) { strcpy(symname+i, "_tilde"); i += strlen(symname+i); } else /* anything you can't put in a C symbol is sprintf'ed in hex */ { sprintf(symname+i, "0x%02x", c); i += strlen(symname+i); hexmunge = 1; } } symname[i] = 0; if (hexmunge) { memmove(symname+6, symname, strlen(symname)+1); strncpy(symname, "setup_", 6); } else strcat(symname, "_setup"); #if 0 fprintf(stderr, "lib: %s\n", classname); #endif /* try looking in the path for (objectname).(sys_dllextent) ... */ for(dllextent=sys_dllextent; *dllextent; dllextent++) { if ((fd = sys_trytoopenone(path, objectname, *dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) goto gotone; } /* next try (objectname)/(classname).(sys_dllextent) ... */ strncpy(filename, objectname, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(filename, "/"); strncat(filename, classname, MAXPDSTRING-strlen(filename)); filename[MAXPDSTRING-1] = 0; for(dllextent=sys_dllextent; *dllextent; dllextent++) { if ((fd = sys_trytoopenone(path, filename, *dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) goto gotone; } #ifdef ANDROID /* Android libs have a 'lib' prefix, '.so' suffix and don't allow ~ */ char libname[MAXPDSTRING] = "lib"; strncat(libname, objectname, MAXPDSTRING - 4); int len = strlen(libname); if (libname[len-1] == '~' && len < MAXPDSTRING - 6) { strcpy(libname+len-1, "_tilde"); } if ((fd = sys_trytoopenone(path, libname, ".so", dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) goto gotone; #endif return (0); gotone: close(fd); class_set_extern_dir(gensym(dirbuf)); /* rebuild the absolute pathname */ strncpy(filename, dirbuf, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(filename, "/"); strncat(filename, nameptr, MAXPDSTRING-strlen(filename)); filename[MAXPDSTRING-1] = 0; #ifdef _WIN32 { char dirname[MAXPDSTRING], *s, *basename; sys_bashfilename(filename, filename); /* set the dirname as DllDirectory, meaning in the path for loading other DLLs so that dependent libraries can be included in the same folder as the external. SetDllDirectory() needs a minimum supported version of Windows XP SP1 for SetDllDirectory, so WINVER must be 0x0502 */ strncpy(dirname, filename, MAXPDSTRING); s = strrchr(dirname, '\\'); basename = s; if (s && *s) *s = '\0'; if (!SetDllDirectory(dirname)) error("Could not set '%s' as DllDirectory(), '%s' might not load.", dirname, basename); /* now load the DLL for the external */ ntdll = LoadLibrary(filename); if (!ntdll) { error("%s: couldn't load", filename); class_set_extern_dir(&s_); return (0); } makeout = (t_xxx)GetProcAddress(ntdll, symname); if (!makeout) makeout = (t_xxx)GetProcAddress(ntdll, "setup"); SetDllDirectory(NULL); /* reset DLL dir to nothing */ } #elif defined(HAVE_LIBDL) || defined(__FreeBSD__) dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if (!dlobj) { error("%s: %s", filename, dlerror()); class_set_extern_dir(&s_); return (0); } makeout = (t_xxx)dlsym(dlobj, symname); if(!makeout) makeout = (t_xxx)dlsym(dlobj, "setup"); #else #warning "No dynamic loading mechanism specified, \ libdl or WIN32 required for loading externals!" #endif if (!makeout) { error("load_object: Symbol \"%s\" not found", symname); class_set_extern_dir(&s_); return 0; } (*makeout)(); class_set_extern_dir(&s_); return (1); }