Chris@2
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 /**
|
Chris@1
|
4 * Plugin Load Checker Helper
|
Chris@0
|
5 *
|
Chris@4
|
6 * This program accepts the name of a descriptor symbol as its only
|
Chris@1
|
7 * command-line argument. It then reads a list of plugin library paths
|
Chris@1
|
8 * from stdin, one per line. For each path read, it attempts to load
|
Chris@4
|
9 * that library and retrieve the named descriptor symbol, printing a
|
Chris@1
|
10 * line to stdout reporting whether this was successful or not and
|
Chris@1
|
11 * then flushing stdout. The output line format is described
|
Chris@1
|
12 * below. The program exits with code 0 if all libraries were loaded
|
Chris@1
|
13 * successfully and non-zero otherwise.
|
Chris@0
|
14 *
|
Chris@0
|
15 * Note that library paths must be ready to pass to dlopen() or
|
Chris@0
|
16 * equivalent; this usually means they should be absolute paths.
|
Chris@0
|
17 *
|
Chris@0
|
18 * Output line for successful load of library libname.so:
|
Chris@0
|
19 * SUCCESS|/path/to/libname.so|
|
Chris@0
|
20 *
|
Chris@0
|
21 * Output line for failed load of library libname.so:
|
Chris@0
|
22 * FAILURE|/path/to/libname.so|Reason for failure if available
|
Chris@0
|
23 *
|
Chris@2
|
24 * Sometimes plugins will crash completely on load, bringing down this
|
Chris@2
|
25 * program with them. If the program exits before all listed plugins
|
Chris@2
|
26 * have been checked, this means that the plugin following the last
|
Chris@2
|
27 * reported one has crashed. Typically the caller may want to run it
|
Chris@2
|
28 * again, omitting that plugin.
|
Chris@0
|
29 */
|
Chris@0
|
30
|
Chris@5
|
31 /*
|
Chris@5
|
32 Copyright (c) 2016 Queen Mary, University of London
|
Chris@5
|
33
|
Chris@5
|
34 Permission is hereby granted, free of charge, to any person
|
Chris@5
|
35 obtaining a copy of this software and associated documentation
|
Chris@5
|
36 files (the "Software"), to deal in the Software without
|
Chris@5
|
37 restriction, including without limitation the rights to use, copy,
|
Chris@5
|
38 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@5
|
39 of the Software, and to permit persons to whom the Software is
|
Chris@5
|
40 furnished to do so, subject to the following conditions:
|
Chris@5
|
41
|
Chris@5
|
42 The above copyright notice and this permission notice shall be
|
Chris@5
|
43 included in all copies or substantial portions of the Software.
|
Chris@5
|
44
|
Chris@5
|
45 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@5
|
46 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@5
|
47 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@5
|
48 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
Chris@5
|
49 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@5
|
50 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@5
|
51 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@5
|
52
|
Chris@5
|
53 Except as contained in this notice, the names of the Centre for
|
Chris@5
|
54 Digital Music and Queen Mary, University of London shall not be
|
Chris@5
|
55 used in advertising or otherwise to promote the sale, use or other
|
Chris@5
|
56 dealings in this Software without prior written authorization.
|
Chris@5
|
57 */
|
Chris@5
|
58
|
Chris@0
|
59 #ifdef _WIN32
|
Chris@0
|
60 #include <windows.h>
|
Chris@0
|
61 #include <process.h>
|
Chris@0
|
62 #define DLOPEN(a,b) LoadLibrary((a).toStdWString().c_str())
|
Chris@0
|
63 #define DLSYM(a,b) GetProcAddress((HINSTANCE)(a),(b))
|
Chris@0
|
64 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a)))
|
Chris@0
|
65 #define DLERROR() ""
|
Chris@0
|
66 #else
|
Chris@0
|
67 #include <dlfcn.h>
|
Chris@0
|
68 #define DLOPEN(a,b) dlopen((a).c_str(),(b))
|
Chris@0
|
69 #define DLSYM(a,b) dlsym((a),(b).c_str())
|
Chris@0
|
70 #define DLCLOSE(a) dlclose((a))
|
Chris@0
|
71 #define DLERROR() dlerror()
|
Chris@0
|
72 #endif
|
Chris@0
|
73
|
Chris@0
|
74 #include <string>
|
Chris@0
|
75 #include <iostream>
|
Chris@0
|
76
|
Chris@0
|
77 using namespace std;
|
Chris@0
|
78
|
Chris@0
|
79 string error()
|
Chris@0
|
80 {
|
Chris@0
|
81 string e = dlerror();
|
Chris@0
|
82 if (e == "") return "(unknown error)";
|
Chris@0
|
83 else return e;
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@1
|
86 string check(string soname, string descriptor)
|
Chris@0
|
87 {
|
Chris@4
|
88 // cerr << "helper: trying: " << soname << endl;
|
Chris@4
|
89
|
Chris@0
|
90 void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL);
|
Chris@0
|
91 if (!handle) {
|
Chris@4
|
92 // cerr << "helper: failed to open" << endl;
|
Chris@0
|
93 return "Unable to open plugin library: " + error();
|
Chris@0
|
94 }
|
Chris@0
|
95
|
Chris@0
|
96 void *fn = DLSYM(handle, descriptor);
|
Chris@0
|
97 if (!fn) {
|
Chris@4
|
98 // cerr << "helper: failed to find descriptor" << endl;
|
Chris@0
|
99 return "Failed to find plugin descriptor " + descriptor +
|
Chris@0
|
100 " in library: " + error();
|
Chris@0
|
101 }
|
Chris@0
|
102
|
Chris@4
|
103 // cerr << "helper: succeeded" << endl;
|
Chris@4
|
104
|
Chris@0
|
105 return "";
|
Chris@0
|
106 }
|
Chris@0
|
107
|
Chris@0
|
108 int main(int argc, char **argv)
|
Chris@0
|
109 {
|
Chris@0
|
110 bool allGood = true;
|
Chris@0
|
111 string soname;
|
Chris@0
|
112
|
Chris@1
|
113 if (argc != 2) {
|
Chris@1
|
114 cerr << "\nUsage:\n " << argv[0] << " descriptorname\n"
|
Chris@4
|
115 "\nwhere descriptorname is the name of a plugin descriptor symbol to be sought\n"
|
Chris@1
|
116 "in each library (e.g. vampGetPluginDescriptor for Vamp plugins). The list of\n"
|
Chris@1
|
117 "candidate plugin library filenames is read from stdin.\n" << endl;
|
Chris@1
|
118 return 2;
|
Chris@1
|
119 }
|
Chris@1
|
120
|
Chris@1
|
121 string descriptor = argv[1];
|
Chris@1
|
122
|
Chris@0
|
123 while (getline(cin, soname)) {
|
Chris@1
|
124 string report = check(soname, descriptor);
|
Chris@0
|
125 if (report != "") {
|
Chris@0
|
126 cout << "FAILURE|" << soname << "|" << report << endl;
|
Chris@0
|
127 allGood = false;
|
Chris@0
|
128 } else {
|
Chris@0
|
129 cout << "SUCCESS|" << soname << "|" << endl;
|
Chris@0
|
130 }
|
Chris@0
|
131 }
|
Chris@0
|
132
|
Chris@0
|
133 return allGood ? 0 : 1;
|
Chris@0
|
134 }
|