1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2 // -*- Mode: C++ -*-
3 //
4 // Copyright (C) 2013-2021 Red Hat, Inc.
5 
6 ///@file
7 
8 #ifndef __ABG_TOOLS_UTILS_H
9 #define __ABG_TOOLS_UTILS_H
10 
11 #include <iostream>
12 #include <istream>
13 #include <memory>
14 #include <ostream>
15 #include <set>
16 #include <string>
17 #include "abg-suppression.h"
18 
19 namespace abigail
20 {
21 
22 namespace tools_utils
23 {
24 
25 using std::ostream;
26 using std::istream;
27 using std::ifstream;
28 using std::string;
29 using std::set;
30 using std::shared_ptr;
31 
32 const char* get_system_libdir();
33 const char* get_anonymous_struct_internal_name_prefix();
34 const char* get_anonymous_union_internal_name_prefix();
35 const char* get_anonymous_enum_internal_name_prefix();
36 
37 bool file_exists(const string&);
38 bool is_regular_file(const string&);
39 bool is_dir(const string&);
40 bool dir_exists(const string&);
41 bool dir_is_empty(const string &);
42 bool decl_names_equal(const string&, const string&);
43 bool maybe_get_symlink_target_file_path(const string& file_path,
44 					string& target_path);
45 bool base_name(string const& path,
46 	       string& file_name);
47 bool dir_name(string const &path,
48 	      string& path_dir_name,
49 	      bool keep_separator_at_end=false);
50 void real_path(const string&path, string& realpath);
51 bool ensure_dir_path_created(const string&);
52 bool ensure_parent_dir_created(const string&);
53 ostream& emit_prefix(const string& prog_name, ostream& out);
54 bool check_file(const string& path, ostream& out, const string& prog_name = "");
55 bool check_dir(const string& path, ostream& out, const string& prog_name="");
56 bool string_ends_with(const string&, const string&);
57 bool string_begins_with(const string&, const string&);
58 bool string_is_ascii(const string&);
59 bool string_is_ascii_identifier(const string&);
60 bool split_string(const string&, const string&, vector<string>&);
61 bool string_suffix(const string&, const string&, string&);
62 bool sorted_strings_common_prefix(vector<string>&, string&);
63 string get_library_version_string();
64 bool execute_command_and_get_output(const string&, vector<string>&);
65 bool get_dsos_provided_by_rpm(const string& rpm_path,
66 			      set<string>& provided_dsos);
67 string trim_white_space(const string&);
68 string trim_leading_string(const string& from, const string& to_trim);
69 void convert_char_stars_to_char_star_stars(const vector<char*>&,
70 					   vector<char**>&);
71 
72 suppr::type_suppression_sptr
73 gen_suppr_spec_from_headers(const string& hdrs_root_dir);
74 
75 suppr::type_suppression_sptr
76 gen_suppr_spec_from_headers(const string& hdrs_root_dir,
77 			    const vector<string>& hdr_files);
78 
79 suppr::type_suppression_sptr
80 gen_suppr_spec_from_headers(const vector<string>& headers_root_dirs,
81 			    const vector<string>& header_files);
82 
83 suppr::suppressions_type
84 gen_suppr_spec_from_kernel_abi_whitelists
85    (const vector<string>& abi_whitelist_paths);
86 
87 bool
88 get_vmlinux_path_from_kernel_dist(const string&	from,
89 				  string&		vmlinux_path);
90 
91 bool
92 get_binary_paths_from_kernel_dist(const string&	dist_root,
93 				  const string&	debug_info_root_path,
94 				  string&		vmlinux_path,
95 				  vector<string>&	module_paths);
96 
97 bool
98 get_binary_paths_from_kernel_dist(const string&	dist_root,
99 				  string&		vmlinux_path,
100 				  vector<string>&	module_paths);
101 
102 string
103 get_default_system_suppression_file_path();
104 
105 string
106 get_default_user_suppression_file_path();
107 
108 void
109 load_default_system_suppressions(suppr::suppressions_type&);
110 
111 void
112 load_default_user_suppressions(suppr::suppressions_type&);
113 
114 bool
115 find_file_under_dir(const string& root_dir,
116 		    const string& file_path_to_look_for,
117 		    string& result);
118 
119 class temp_file;
120 
121 /// Convenience typedef for a shared_ptr to @ref temp_file.
122 typedef shared_ptr<temp_file> temp_file_sptr;
123 
124 /// A temporary file.
125 ///
126 /// This is a helper file around the  mkstemp API.
127 ///
128 /// Once the temporary file is created, users can interact with it
129 /// using an fstream.  They can also get the path to the newly
130 /// created temporary file.
131 ///
132 /// When the instance of @ref temp_file is destroyed, the underlying
133 /// resources are de-allocated, the underlying temporary file is
134 /// closed and removed.
135 class temp_file
136 {
137   struct priv;
138   typedef shared_ptr<priv> priv_sptr;
139 
140   priv_sptr priv_;
141 
142   temp_file();
143 
144 public:
145 
146   bool
147   is_good() const;
148 
149   const char*
150   get_path() const;
151 
152   std::fstream&
153   get_stream();
154 
155   static temp_file_sptr
156   create();
157 }; // end class temp_file
158 
159 size_t
160 get_random_number();
161 
162 string
163 get_random_number_as_string();
164 
165 /// The different types of files understood the bi* suite of tools.
166 enum file_type
167 {
168   /// A file type we don't know about.
169   FILE_TYPE_UNKNOWN,
170   /// The native xml file format representing a translation unit.
171   FILE_TYPE_NATIVE_BI,
172   /// An elf file.  Read this kind of file should yield an
173   /// abigail::corpus type.
174   FILE_TYPE_ELF,
175   /// An archive (AR) file.
176   FILE_TYPE_AR,
177   // A native abixml file format representing a corpus of one or
178   // several translation units.
179   FILE_TYPE_XML_CORPUS,
180   // A native abixml file format representing a corpus group of one or
181   // several corpora.
182   FILE_TYPE_XML_CORPUS_GROUP,
183   /// An RPM (.rpm) binary file
184   FILE_TYPE_RPM,
185   /// An SRPM (.src.rpm) file
186   FILE_TYPE_SRPM,
187   /// A DEB (.deb) binary file
188   FILE_TYPE_DEB,
189   /// A plain directory
190   FILE_TYPE_DIR,
191   /// A tar archive.  The archive can be compressed with the popular
192   /// compression schemes recognized by GNU tar.
193   FILE_TYPE_TAR
194 };
195 
196 /// Exit status for abidiff and abicompat tools.
197 ///
198 /// It's actually a bit mask.  The value of each enumerator is a power
199 /// of two.
200 enum abidiff_status
201 {
202   /// This is for when the compared ABIs are equal.
203   ///
204   /// Its numerical value is 0.
205   ABIDIFF_OK = 0,
206 
207   /// This bit is set if there is an application error.
208   ///
209   /// Its numerical value is 1.
210   ABIDIFF_ERROR = 1,
211 
212   /// This bit is set if the tool is invoked in an non appropriate
213   /// manner.
214   ///
215   /// Its numerical value is 2.
216   ABIDIFF_USAGE_ERROR = 1 << 1,
217 
218   /// This bit is set if the ABIs being compared are different.
219   ///
220   /// Its numerical value is 4.
221   ABIDIFF_ABI_CHANGE = 1 << 2,
222 
223   /// This bit is set if the ABIs being compared are different *and*
224   /// are incompatible.
225   ///
226   /// Its numerical value is 8.
227   ABIDIFF_ABI_INCOMPATIBLE_CHANGE = 1 << 3
228 };
229 
230 abidiff_status
231 operator|(abidiff_status, abidiff_status);
232 
233 abidiff_status
234 operator&(abidiff_status, abidiff_status);
235 
236 abidiff_status&
237 operator|=(abidiff_status&l, abidiff_status r);
238 
239 bool
240 abidiff_status_has_error(abidiff_status s);
241 
242 bool
243 abidiff_status_has_abi_change(abidiff_status s);
244 
245 bool
246 abidiff_status_has_incompatible_abi_change(abidiff_status s);
247 
248 /// A type used to time various part of the libabigail system.
249 class timer
250 {
251   struct priv;
252   typedef shared_ptr<priv> priv_sptr;
253 
254   priv_sptr priv_;
255 
256 public:
257   enum kind
258   {
259     /// Default timer kind.
260     DEFAULT_TIMER_KIND = 0,
261     /// This kind of timer starts upon instantiation.
262     START_ON_INSTANTIATION_TIMER_KIND = 1,
263   };
264 
265   timer (kind k = DEFAULT_TIMER_KIND);
266   bool start();
267   bool stop();
268   time_t value_in_seconds() const;
269   bool value(time_t& hours,
270 	     time_t& minutes,
271 	     time_t& seconds,
272 	     time_t& milliseconds) const;
273   string value_as_string() const;
274   ~timer();
275 }; //end class timer
276 
277 ostream& operator<<(ostream&, const timer&);
278 
279 ostream&
280 operator<<(ostream& output, file_type r);
281 
282 file_type guess_file_type(istream& in);
283 
284 file_type guess_file_type(const string& file_path);
285 
286 bool
287 get_rpm_name(const string& str, string& name);
288 
289 bool
290 get_rpm_arch(const string& str, string& arch);
291 
292 bool
293 get_deb_name(const string& str, string& name);
294 
295 bool
296 file_is_kernel_package(const string& file_path,
297 		       file_type file_type);
298 
299 bool
300 file_is_kernel_debuginfo_package(const string& file_path,
301 				 file_type file_type);
302 
303 std::shared_ptr<char>
304 make_path_absolute(const char*p);
305 
306 char*
307 make_path_absolute_to_be_freed(const char*p);
308 
309 corpus_group_sptr
310 build_corpus_group_from_kernel_dist_under(const string&	root,
311 					  const string		debug_info_root,
312 					  const string&	vmlinux_path,
313 					  vector<string>&	suppr_paths,
314 					  vector<string>&	kabi_wl_paths,
315 					  suppr::suppressions_type&	supprs,
316 					  bool				verbose,
317 					  environment_sptr&		env);
318 }// end namespace tools_utils
319 
320 /// A macro that expands to aborting the program when executed.
321 ///
322 /// Before aborting, the macro emits informatin about the source
323 /// location where it was expanded.
324 #define ABG_ASSERT_NOT_REACHED \
325   do {									\
326     std::cerr << "in " << __FUNCTION__					\
327 	      << " at: " << __FILE__ << ":" << __LINE__			\
328 	      << ": execution should not have reached this point!\n";	\
329       abort();								\
330   } while (false)
331 }//end namespace abigail
332 
333 #endif //__ABG_TOOLS_UTILS_H
334