annotate src/helper.cpp @ 19:c80c55cabfcd

Untabify
author Chris Cannam
date Tue, 01 Nov 2016 15:16:08 +0000
parents 7eff522b23ae
children 65b6c64992dd
rev   line source
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@10 62 #include <string>
Chris@10 63 #ifdef UNICODE
Chris@18 64 static std::string lastLibraryName = "";
Chris@10 65 static HMODULE LoadLibraryUTF8(std::string name) {
Chris@18 66 lastLibraryName = name;
Chris@10 67 int n = name.size();
Chris@16 68 int wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, 0, 0);
Chris@16 69 wchar_t *wname = new wchar_t[wn+1];
Chris@16 70 wn = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), n, wname, wn);
Chris@16 71 wname[wn] = L'\0';
Chris@10 72 HMODULE h = LoadLibraryW(wname);
Chris@10 73 delete[] wname;
Chris@10 74 return h;
Chris@10 75 }
Chris@10 76 static std::string GetErrorText() {
Chris@10 77 wchar_t *buffer;
Chris@10 78 DWORD err = GetLastError();
Chris@10 79 FormatMessage(
Chris@10 80 FORMAT_MESSAGE_ALLOCATE_BUFFER |
Chris@10 81 FORMAT_MESSAGE_FROM_SYSTEM |
Chris@10 82 FORMAT_MESSAGE_IGNORE_INSERTS,
Chris@10 83 NULL,
Chris@10 84 err,
Chris@10 85 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
Chris@10 86 (LPTSTR) &buffer,
Chris@10 87 0, NULL );
Chris@16 88 int wn = wcslen(buffer);
Chris@16 89 int n = WideCharToMultiByte(CP_UTF8, 0, buffer, wn, 0, 0, 0, 0);
Chris@17 90 if (n < 0) {
Chris@17 91 LocalFree(&buffer);
Chris@17 92 return "Unable to convert error string (internal error)";
Chris@17 93 }
Chris@16 94 char *text = new char[n+1];
Chris@17 95 (void)WideCharToMultiByte(CP_UTF8, 0, buffer, wn, text, n, 0, 0);
Chris@16 96 text[n] = '\0';
Chris@10 97 std::string s(text);
Chris@10 98 LocalFree(&buffer);
Chris@10 99 delete[] text;
Chris@10 100 for (int i = s.size(); i > 0; ) {
Chris@10 101 --i;
Chris@10 102 if (s[i] == '\n' || s[i] == '\r') {
Chris@10 103 s.erase(i, 1);
Chris@10 104 }
Chris@10 105 }
Chris@18 106 std::size_t pos = s.find("%1");
Chris@18 107 if (pos != std::string::npos && lastLibraryName != "") {
Chris@18 108 s.replace(pos, 2, lastLibraryName);
Chris@18 109 }
Chris@10 110 return s;
Chris@10 111 }
Chris@10 112 #define DLOPEN(a,b) LoadLibraryUTF8(a)
Chris@10 113 #else
Chris@10 114 #define DLOPEN(a,b) LoadLibrary((a).c_str())
Chris@10 115 #define GetErrorText() ""
Chris@10 116 #endif
Chris@10 117 #define DLSYM(a,b) (void *)GetProcAddress((HINSTANCE)(a),(b).c_str())
Chris@0 118 #define DLCLOSE(a) (!FreeLibrary((HINSTANCE)(a)))
Chris@10 119 #define DLERROR() (GetErrorText())
Chris@0 120 #else
Chris@0 121 #include <dlfcn.h>
Chris@0 122 #define DLOPEN(a,b) dlopen((a).c_str(),(b))
Chris@0 123 #define DLSYM(a,b) dlsym((a),(b).c_str())
Chris@0 124 #define DLCLOSE(a) dlclose((a))
Chris@0 125 #define DLERROR() dlerror()
Chris@0 126 #endif
Chris@0 127
Chris@0 128 #include <string>
Chris@0 129 #include <iostream>
Chris@0 130
Chris@12 131 //#include <unistd.h>
Chris@6 132
Chris@0 133 using namespace std;
Chris@0 134
Chris@0 135 string error()
Chris@0 136 {
Chris@10 137 string e = DLERROR();
Chris@0 138 if (e == "") return "(unknown error)";
Chris@0 139 else return e;
Chris@0 140 }
Chris@0 141
Chris@1 142 string check(string soname, string descriptor)
Chris@0 143 {
Chris@0 144 void *handle = DLOPEN(soname, RTLD_NOW | RTLD_LOCAL);
Chris@0 145 if (!handle) {
Chris@10 146 return "Unable to open plugin library: " + error();
Chris@0 147 }
Chris@0 148
Chris@0 149 void *fn = DLSYM(handle, descriptor);
Chris@0 150 if (!fn) {
Chris@10 151 return "Failed to find plugin descriptor " + descriptor +
Chris@10 152 " in library: " + error();
Chris@0 153 }
Chris@0 154
Chris@0 155 return "";
Chris@0 156 }
Chris@0 157
Chris@0 158 int main(int argc, char **argv)
Chris@0 159 {
Chris@0 160 bool allGood = true;
Chris@0 161 string soname;
Chris@0 162
Chris@1 163 if (argc != 2) {
Chris@11 164 cerr << "\nUsage:\n " << argv[0] << " descriptorname\n"
Chris@11 165 "\nwhere descriptorname is the name of a plugin descriptor symbol to be sought\n"
Chris@11 166 "in each library (e.g. vampGetPluginDescriptor for Vamp plugins). The list of\n"
Chris@11 167 "candidate plugin library filenames is read from stdin.\n" << endl;
Chris@11 168 return 2;
Chris@1 169 }
Chris@1 170
Chris@1 171 string descriptor = argv[1];
Chris@1 172
Chris@0 173 while (getline(cin, soname)) {
Chris@11 174 string report = check(soname, descriptor);
Chris@11 175 if (report != "") {
Chris@11 176 cout << "FAILURE|" << soname << "|" << report << endl;
Chris@11 177 allGood = false;
Chris@11 178 } else {
Chris@11 179 cout << "SUCCESS|" << soname << "|" << endl;
Chris@11 180 }
Chris@0 181 }
Chris@11 182
Chris@0 183 return allGood ? 0 : 1;
Chris@0 184 }