xref: /openbmc/phosphor-ipmi-blobs/utils.cpp (revision 52509572)
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "utils.hpp"
18 
19 #include "fs.hpp"
20 #include "manager.hpp"
21 
22 #include <dlfcn.h>
23 
24 #include <phosphor-logging/log.hpp>
25 
26 #include <memory>
27 #include <regex>
28 #include <string>
29 #include <unordered_set>
30 #include <vector>
31 
32 namespace blobs
33 {
34 
35 using namespace phosphor::logging;
36 
matchBlobHandler(const std::string & filename)37 bool matchBlobHandler(const std::string& filename)
38 {
39     return filename.find(".so") != std::string::npos;
40 }
41 
loadLibraries(ManagerInterface * manager,const std::string & path,const internal::DlSysInterface * sys)42 void loadLibraries(ManagerInterface* manager, const std::string& path,
43                    const internal::DlSysInterface* sys)
44 {
45     std::unordered_set<HandlerFactory> seen;
46     void* libHandle = NULL;
47     HandlerFactory factory;
48 
49     std::vector<std::string> libs = getLibraryList(path, matchBlobHandler);
50 
51     for (const auto& p : libs)
52     {
53         libHandle = sys->dlopen(p.c_str(), RTLD_NOW | RTLD_GLOBAL);
54         if (!libHandle)
55         {
56             log<level::ERR>("ERROR opening", entry("HANDLER=%s", p.c_str()),
57                             entry("ERROR=%s", sys->dlerror()));
58             continue;
59         }
60 
61         sys->dlerror(); /* Clear any previous error. */
62 
63         factory = reinterpret_cast<HandlerFactory>(
64             sys->dlsym(libHandle, "createHandler"));
65 
66         const char* error = sys->dlerror();
67         if (error)
68         {
69             log<level::ERR>("ERROR loading symbol",
70                             entry("HANDLER=%s", p.c_str()),
71                             entry("ERROR=%s", error));
72             continue;
73         }
74 
75         // We may have duplicate libraries in the blobs directory that we only
76         // want to initialize once.
77         if (seen.count(factory) > 0)
78         {
79             continue;
80         }
81         seen.emplace(factory);
82 
83         try
84         {
85             std::unique_ptr<GenericBlobInterface> result = factory();
86             if (!result)
87             {
88                 log<level::ERR>("Unable to create handler",
89                                 entry("HANDLER=%s", p.c_str()));
90                 continue;
91             }
92 
93             manager->registerHandler(std::move(result));
94         }
95         catch (const std::exception& e)
96         {
97             log<level::ERR>("Received exception loading handler",
98                             entry("HANDLER=%s", p.c_str()),
99                             entry("EXCEPTION=%s", e.what()));
100         }
101     }
102 }
103 
104 } // namespace blobs
105