FOSSology  4.4.0
Open Source License Compliance by Open Source Software
compatibility.cc
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2024 Siemens AG
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
44 #include <stdexcept>
45 #include "compatibility.hpp"
46 
47 using namespace fo;
48 
53 #define return_sched(retval) \
54  do \
55  { \
56  fo_scheduler_disconnect((retval)); \
57  return (retval); \
58  } while (0)
59 
68 void check_file_compatibility(const string& lic_type_loc,
69  const string& rule_loc, bool json,
70  const string& lic_result_json,
71  const string& main_license)
72 {
73  bool printComma = false;
74 
75  set<string> all_license_list;
76  const unordered_map<string, string>& license_map =
77  initialize_license_map(lic_type_loc);
78  const map<tuple<string, string, string, string>, bool>& rule_list =
79  initialize_rule_list(rule_loc);
80  map<tuple<string, string>, bool> compatibility_results;
81 
82  auto main_license_set = mainLicenseToSet(main_license);
83 
84  if (json)
85  {
86  cout << "[\n";
87  }
88 
89  Json::Value root;
90  std::ifstream ifs(lic_result_json.c_str());
91  ifs >> root;
92  ifs.close();
93 
94  for (const auto& fileItems : root["results"]) // iterating the json_file
95  {
96  const string fileName = fileItems["file"].asString();
97  set<string> file_license_set = set<string>(main_license_set);
98  for (const auto& license : fileItems["licenses"]) // iterating the
99  // license array
100  {
101  string str = license.asString();
102  if (str == "Dual-license" || str == "No_license_found" || str == "Void")
103  {
104  continue;
105  }
106  file_license_set.insert(str);
107  all_license_list.insert(str);
108  }
109  if (file_license_set.size() > 1) // Compute only if file has > 1 license
110  {
111  vector<tuple<string, string, bool>> result;
112  result = checkCompatibility(file_license_set, license_map, rule_list,
113  compatibility_results);
114  if (json)
115  {
116  appendToJson(result, fileName, printComma);
117  }
118  else
119  {
120  printResultToStdout(result, fileName);
121  }
122  }
123  }
124  vector<tuple<string, string, bool>> result;
125  string name = "null";
126  result = checkCompatibility(all_license_list, license_map, rule_list,
127  compatibility_results);
128  if (json)
129  {
130  appendToJson(result, name, printComma);
131  }
132  else
133  {
134  printResultToStdout(result, name);
135  }
136 
137  if (json)
138  {
139  cout << "\n]\n";
140  }
141 }
142 
143 int main(int argc, char** argv)
144 {
145  CompatibilityCliOptions cliOptions;
146  vector<string> licenseNames;
147  string lic_types, rule, jFile, mainLicense;
148  if (!parseCliOptions(argc, argv, cliOptions, lic_types, rule, jFile,
149  mainLicense))
150  {
151  return_sched(1);
152  }
153 
154  bool json = cliOptions.doJsonOutput();
155  CompatibilityState state = getState(std::move(cliOptions));
156 
157  if (jFile.empty())
158  {
159  DbManager dbManager(&argc, argv);
160  CompatibilityDatabaseHandler databaseHandler(dbManager);
161 
163 
164  while (fo_scheduler_next() != nullptr)
165  {
166  int uploadId = atoi(fo_scheduler_current());
167  int groupId = fo_scheduler_groupID();
168 
169  if (uploadId == 0)
170  {
171  continue;
172  }
173 
174  int arsId = writeARS(state, 0, uploadId, 0, dbManager);
175 
176  if (arsId <= 0)
177  {
178  bail(5);
179  }
180 
181  if (!processUploadId(state, uploadId, databaseHandler, groupId))
182  {
183  bail(2);
184  }
185 
187  writeARS(state, arsId, uploadId, 1, dbManager);
188  }
190 
191  /* do not use bail, as it would prevent the destructors from running */
193  }
194  else
195  {
196  try
197  {
198  check_file_compatibility(lic_types, rule, json, jFile, mainLicense);
199  }
200  catch (invalid_argument& e)
201  {
202  cerr << e.what();
203  return -1;
204  }
205  }
206  return 0;
207 }
208 
216 vector<tuple<string, string, bool>> checkCompatibility(
217  const set<string>& license_set,
218  const unordered_map<string, string>& license_map,
219  const map<tuple<string, string, string, string>, bool>& rule_list,
220  map<tuple<string, string>, bool>& scan_results)
221 {
222  string first_name, first_type, second_name, second_type;
223  vector<tuple<string, string, bool>> res;
224  vector<string> license_list = vector<string>(license_set.begin(),
225  license_set.end());
226 
227  unsigned int license_len = license_list.size();
228  for (unsigned int i = 0; i < (license_len - 1); i++)
229  {
230  first_name = license_list[i];
231  try
232  {
233  first_type = license_map.at(first_name);
234  }
235  catch (out_of_range&)
236  {
237  first_type = "";
238  }
239  for (unsigned int j = (i + 1); j < license_len; j++)
240  {
241  second_name = license_list[j];
242  try
243  {
244  second_type = license_map.at(second_name);
245  }
246  catch (out_of_range&)
247  {
248  second_type = "";
249  }
250 
251  auto existing_result = scan_results.find(
252  make_tuple(first_name, second_name));
253  if (existing_result == scan_results.end())
254  {
255  existing_result = scan_results.find(
256  make_tuple(second_name, first_name));
257  }
258 
259  if (existing_result != scan_results.end())
260  {
261  res.emplace_back(first_name, second_name, existing_result->second);
262  continue;
263  }
264 
265  bool compatibility = are_licenses_compatible(first_name, first_type,
266  second_name, second_type,
267  rule_list);
268  res.emplace_back(first_name, second_name, compatibility);
269  scan_results[make_tuple(first_name, second_name)] = compatibility;
270  }
271  }
272  return res;
273 }
map< tuple< string, string, string, string >, bool > initialize_rule_list(const string &file_location)
Read YAML file of rules and parse it as map.
unordered_map< string, string > initialize_license_map(const string &file_location)
Parse license type CSV and create a map.
bool processUploadId(const CompatibilityState &state, int uploadId, CompatibilityDatabaseHandler &databaseHandler, int groupId)
bool parseCliOptions(int argc, char **argv, CompatibilityCliOptions &dest, std::string &types, std::string &rules, string &jFile, string &mainLicense)
Parse the options sent by CLI to CliOptions object.
void printResultToStdout(const std::vector< tuple< string, string, bool >> &resultPair, const std::string &fileName)
CompatibilityState getState(DbManager &dbManager, CompatibilityCliOptions &&cliOptions)
Create a new state for the current agent based on CliOptions.
int writeARS(const CompatibilityState &state, int arsId, int uploadId, int success, DbManager &dbManager)
int queryAgentId(DbManager &dbManager)
std::set< std::string > mainLicenseToSet(const string &mainLicense)
void appendToJson(const std::vector< tuple< string, string, bool >> &resultPair, const std::string &fileName, bool &printComma)
void bail(int exitval)
bool are_licenses_compatible(const string &first_name, const string &first_type, const string &second_name, const string &second_type, const map< tuple< string, string, string, string >, bool > &rule_list)
Check the licenses against rules and get the compatibility result.
Store the options sent through the CLI.
bool doJsonOutput() const
Check if JSON output is required.
Store the state of the agent.
void setAgentId(const int agentId)
DB wrapper for agents.
#define return_sched(retval)
vector< tuple< string, string, bool > > checkCompatibility(const set< string > &license_set, const unordered_map< string, string > &license_map, const map< tuple< string, string, string, string >, bool > &rule_list, map< tuple< string, string >, bool > &scan_results)
find the compatibility for cli mode
void check_file_compatibility(const string &lic_type_loc, const string &rule_loc, bool json, const string &lic_result_json, const string &main_license)
Check and print license compatibility of scan result.
void fo_scheduler_disconnect(int retcode)
Disconnect the scheduler connection.
void fo_scheduler_heart(int i)
This function must be called by agents to let the scheduler know they are alive and how many items th...
char * fo_scheduler_current()
Get the last read string from the scheduler.
char * fo_scheduler_next()
Get the next data to process from the scheduler.
int fo_scheduler_groupID()
Gets the id of the group that created the job that the agent is running.
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
fo namespace holds the FOSSology library functions.
Definition: nomos.h:426