1 /*********************************************************************/ 2 // dar - disk archive - a backup/restoration program 3 // Copyright (C) 2002-2052 Denis Corbin 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 // 19 // to contact the author : http://dar.linux.free.fr/email.html 20 /*********************************************************************/ 21 22 /// \defgroup Tools Tools 23 /// \brief a set of tool routine 24 /// 25 /// these routines are available from libdar for historical 26 /// reason, but are not part of the API. 27 /// They are shared and used by dar, dar_slave, dar_xform, 28 /// and dar_manager command. You should avoid using them in 29 /// external program as they may be removed or changed without 30 /// backward compatibility support. 31 32 /// \file tools.hpp 33 /// \brief a set of general purpose routines 34 /// \ingroup Tools 35 36 37 #ifndef TOOLS_HPP 38 #define TOOLS_HPP 39 40 #include "../my_config.h" 41 42 extern "C" 43 { 44 #if STDC_HEADERS 45 #include <stdarg.h> 46 #endif 47 #if HAVE_SIGNAL_H 48 #include <signal.h> 49 #endif 50 #if HAVE_GPGME_H 51 #include <gpgme.h> 52 #endif 53 } 54 55 #include <string> 56 #include <vector> 57 #include <map> 58 #include "path.hpp" 59 #include "infinint.hpp" 60 #include "generic_file.hpp" 61 #include "tuyau.hpp" 62 #include "integers.hpp" 63 #include "tlv_list.hpp" 64 #include "memory_pool.hpp" 65 #include "datetime.hpp" 66 67 #define TOOLS_SI_SUFFIX 1000 68 #define TOOLS_BIN_SUFFIX 1024 69 70 namespace libdar 71 { 72 73 /// \addtogroup Tools 74 /// @{ 75 76 77 /// libdar internal use only: it is launched from get_version() and initializes tools internal variables 78 extern void tools_init(); 79 /// libdar internal use only: it is launched from close_and_clean() and releases tools internal variables 80 extern void tools_end(); 81 82 /// convert a string to a char * 83 84 /// \param[in] x is the string to convert 85 /// \return the address of newly allocated memory containing the equivalent string as the argument 86 /// \exception Ememory is thrown if the memory allocation failed, this call never return nullptr 87 /// \note Do not use this function, use std::string::c_str(). The allocated memory must be released by the caller thanks to the "delete []" operator 88 extern char *tools_str2charptr(const std::string &x); 89 90 /// write a string to a file with a '\\0' at then end 91 92 /// \param[in] f the file to write to 93 /// \param[in] s the string to write to file 94 extern void tools_write_string(generic_file & f, const std::string & s); 95 96 /// read a string from a file expecting it to terminate by '\\0' 97 98 /// \param f the file to read from 99 /// \param s the string to put the data to (except the ending '\\0') 100 extern void tools_read_string(generic_file & f, std::string & s); 101 102 /// write a string to a file, '\\0' has no special meaning nor is added at the end 103 104 /// \param[in] f the file to write to 105 /// \param[in] s the string to write to file 106 extern void tools_write_string_all(generic_file & f, const std::string & s); 107 108 /// read a string if given size from a file '\\0' has no special meaning 109 110 /// \param[in] f is the file to read from 111 /// \param[in] s is the string to put read data in 112 /// \param[in] taille is the size in byte to read 113 extern void tools_read_string_size(generic_file & f, std::string & s, infinint taille); 114 115 /// retrieve the size in byte of a file 116 117 /// \param[in] p is the path to the file which size is to get 118 /// \return the size of the file in byte 119 extern infinint tools_get_filesize(const path &p); 120 121 /// convert the given string to infinint taking care of multiplication suffixes like k, M, T, etc. 122 123 /// \param[in] s is the string to read 124 /// \param[in] base is the multiplication factor (base = 1000 for SI, base = 1024 for computer science use) 125 /// \return the value encoded in the given string 126 extern infinint tools_get_extended_size(std::string s, U_I base); 127 128 /// convert an integer to its decimal representation with the highest unit of metric system 129 /// \param[in] number is the integer to convert 130 /// \param[in] unit unit symbol (o for octet, m for meter, etc.) to apply metric system to, this may be nullptr 131 /// \param[in] binary if set to true using the ki, Gi, Mi ... scale instead of the traditional k, G, M, ... prefixes 132 /// \return the string representing the number in metric system (ex: "1 ko", "200 Mio", ...) 133 extern std::string tools_display_integer_in_metric_system(infinint number, const std::string & unit, bool binary); 134 135 /// extracts the basename of a file (removing path part) 136 137 /// \param[in] command_name is the full path of the file 138 /// \param[out] basename the basename of the file 139 /// \exception Ememory can be thrown if memory allocation failed 140 extern void tools_extract_basename(const char *command_name, std::string & basename); 141 142 143 /// give a pointer to the last character of the given value in the given string 144 145 /// \param[in] s is the given string 146 /// \param[in] v is the given char value 147 /// \return a interator on s, pointing on the last char of s equal to v or a pointing to s.end() if no such char could be found is "s" 148 /// \note the arguments are not modified neither the data they are pointing to. However the const statement has not been used to 149 /// be able to return a iterator on the string (and not a const_interator). There is probably other ways to do that (using const_cast) for example 150 extern std::string::iterator tools_find_last_char_of(std::string &s, unsigned char v); 151 152 /// give a pointer to the last character of the given value in the given string 153 154 /// \param[in] s is the given string 155 /// \param[in] v is the given char value 156 /// \return a interator on s, pointing on the first char of s equal to v or a pointing to s.end() if no such char could be found is "s" 157 /// \note the arguments are not modified neither the data they are pointing to. However the const statement has not been used to 158 /// be able to return a iterator on the string (and not a const_interator). There is probably other ways to do that (using const_cast) for example 159 extern std::string::iterator tools_find_first_char_of(std::string &s, unsigned char v); 160 161 /// split a given full path in path part and basename part 162 163 /// \param[in] all is the path to split 164 /// \param[out] chemin is the resulting path part, it points to a newly allocated path object 165 /// \param[out] base is the resulting basename 166 /// \param[in] pool memory pool to use for allocation or nullptr for default memory allocation 167 /// \note chemin argument must be release by the caller thanks to the "delete" operator. 168 extern void tools_split_path_basename(const char *all, path * &chemin, std::string & base, memory_pool *pool = nullptr); 169 170 /// split a given full path in path part and basename part 171 172 /// \param[in] all is the path to split 173 /// \param[out] chemin is the resulting path part, it points to a newly allocated path object 174 /// \param[out] base is the resulting basename 175 /// \param[in] pool memory pool to use for allocation or nullptr for default memory allocation 176 /// \note chemin argument must be release by the caller thanks to the "delete" operator. 177 extern void tools_split_path_basename(const std::string &all, std::string & chemin, std::string & base, memory_pool *pool = nullptr); 178 179 /// open a pair of tuyau objects encapsulating two named pipes. 180 181 /// \param[in,out] dialog for user interaction 182 /// \param[in] input path to the input named pipe 183 /// \param[in] output path to the output named pipe 184 /// \param[out] in resulting tuyau object for input 185 /// \param[out] out resulting tuyau object for output 186 /// \param[in] pool memory pool to use for allocation or nullptr for default memory allocation 187 /// \note in and out parameters must be released by the caller thanks to the "delete" operator 188 extern void tools_open_pipes(user_interaction & dialog, 189 const std::string &input, 190 const std::string & output, 191 tuyau *&in, 192 tuyau *&out, 193 memory_pool *pool = nullptr); 194 195 /// set blocking/not blocking mode for reading on a file descriptor 196 197 /// \param[in] fd file descriptor to read on 198 /// \param[in] mode set to true for a blocking read and to false for non blocking read 199 extern void tools_blocking_read(int fd, bool mode); 200 201 /// convert uid to name in regards to the current system's configuration 202 203 /// \param[in] uid the User ID number 204 /// \return the name of the corresponding user or the uid if none corresponds 205 extern std::string tools_name_of_uid(const infinint & uid); 206 207 /// convert gid to name in regards of the current system's configuration 208 209 /// \param[in] gid the Group ID number 210 /// \return the name of the corresponding group or the gid if none corresponds 211 extern std::string tools_name_of_gid(const infinint & gid); 212 213 /// convert unsigned word to string 214 215 /// \param[in] x the unsigned word to convert 216 /// \return the decimal representation of the given integer 217 extern std::string tools_uword2str(U_16 x); 218 219 /// convert integer to string 220 221 /// \param[in] x the integer to convert 222 /// \return the decimal representation of the given integer 223 extern std::string tools_int2str(S_I x); 224 extern std::string tools_uint2str(U_I x); 225 226 /// convert an integer written in decimal notation to the corresponding value 227 228 /// \param[in] x the decimal representation of the integer 229 /// \return the value corresponding to the decimal representation given 230 extern U_I tools_str2int(const std::string & x); 231 232 /// convert a signed integer written in decimal notation to the corresponding value 233 234 /// \param[in] x the decimal representation of the integer 235 /// \return the value corresponding to the decimal representation given 236 extern S_I tools_str2signed_int(const std::string & x); 237 238 /// ascii to integer conversion 239 240 /// \param[in] a is the ascii string to convert 241 /// \param[out] val is the resulting value 242 /// \return true if the conversion could be done false if the given string does not 243 /// correspond to the decimal representation of an unsigned integer 244 /// \note this call is now a warapper around tools_str2int 245 extern bool tools_my_atoi(const char *a, U_I & val); 246 247 /// prepend spaces before the given string 248 249 /// \param[in] s the string to append spaces to 250 /// \param[in] expected_size the minimum size of the resulting string 251 /// \return a string at least as much long as expected_size with prepended leading spaces if necessary 252 extern std::string tools_addspacebefore(std::string s, U_I expected_size); 253 254 /// convert a date in second to its human readable representation 255 256 /// \param[in] date the date in second 257 /// \return the human representation corresponding to the argument 258 extern std::string tools_display_date(const datetime & date); 259 260 /// convert a human readable date representation in number of second since the system reference date 261 262 /// \param[in] repres the date's human representation 263 /// \return the corresponding number of seconds (computer time) 264 /// \note the string expected format is "[[[year/]month/]day-]hour:minute[:second]" 265 extern infinint tools_convert_date(const std::string & repres); 266 267 /// wrapper to the "system" system call. 268 269 /// \param[in,out] dialog for user interaction 270 /// \param[in] argvector the equivalent to the argv[] vector 271 extern void tools_system(user_interaction & dialog, const std::vector<std::string> & argvector); 272 273 /// wrapper to the "system" system call using anonymous pipe to tranmit arguments to the child process 274 275 /// \param[in,out] dialog for user interaction 276 /// \param[in] dar_cmd the path to the executable to run 277 /// \param[in] argvpipe the list of arguments to pass through anonymous pipe 278 /// \param[in] pool memory pool to use or nullptr for default memory allocation 279 /// \note the command to execute must understand the --pipe-fd option that 280 /// gives the filedescriptor to read from the command-line options 281 extern void tools_system_with_pipe(user_interaction & dialog, 282 const std::string & dar_cmd, 283 const std::vector<std::string> & argvpipe, 284 memory_pool *pool = nullptr); 285 286 /// write a list of string to file 287 288 /// \param[in] f the file to write to 289 /// \param[in] x the list of string to write 290 extern void tools_write_vector(generic_file & f, const std::vector<std::string> & x); 291 292 /// read a list of string from a file 293 294 /// \param[in] f the file to read from 295 /// \param[out] x the list to fill from file 296 extern void tools_read_vector(generic_file & f, std::vector<std::string> & x); 297 298 /// concatenate a vectors of strings in a single string 299 300 /// \param[in] separator string to insert between two elements 301 /// \param[in] x the list string 302 /// \return the result of the concatenation of the members of the list with separtor between two consecutive members 303 extern std::string tools_concat_vector(const std::string & separator, 304 const std::vector<std::string> & x); 305 306 /// concatenate two vectors 307 308 /// \param[in] a the first vector 309 /// \param[in] b the second vector 310 /// \return a vector containing the elements of a and the element of b 311 std::vector<std::string> operator + (std::vector<std::string> a, std::vector<std::string> b); 312 313 314 /// display the compilation time features of libdar 315 316 /// \param[in,out] dialog for user interaction 317 /// \note this call uses the compile_time:: routines, and will 318 /// not change its interface upon new feature addition 319 extern void tools_display_features(user_interaction & dialog); 320 321 322 /// test if two dates are equal taking care of a integer hour of difference 323 324 /// \param[in] hourshift is the number of integer hour more or less two date can be considered equal 325 /// \param[in] date1 first date to compare 326 /// \param[in] date2 second date to compare to 327 /// \return whether dates are equal or not 328 extern bool tools_is_equal_with_hourshift(const infinint & hourshift, const datetime & date1, const datetime & date2); 329 330 /// template function to add two vectors 331 operator +=(std::vector<T> & a,const std::vector<T> & b)332 template <class T> std::vector<T> operator +=(std::vector<T> & a, const std::vector<T> & b) 333 { 334 a = a + b; 335 return a; 336 } 337 338 339 /// isolate the value of a given variable from the environment vector 340 341 /// \param[in] env the environment vector as retreived from the third argument of the main() function 342 /// \param[in] clef the key or variable name too look for 343 /// \return nullptr if the key could not be find or a pointer to the env data giving the value of the requested key 344 /// \note the returned value must not be released by any mean as it is just a pointer to an system allocated memory (the env vector). 345 extern const char *tools_get_from_env(const char **env, const char *clef); 346 347 /// does sanity checks on a slice name, check presence and detect whether the given basename is not rather a filename 348 349 /// \param[in,out] dialog for user interaction 350 /// \param[in] loc the path where resides the slice 351 /// \param[in,out] base the basename of the slice 352 /// \param[in] extension the extension of dar's slices 353 /// \param[in] pool memory pool to use of nullptr for default memory allocation 354 /// \note if user accepted the change of slice name proposed by libdar through dialog the base argument is changed 355 extern void tools_check_basename(user_interaction & dialog, 356 const path & loc, 357 std::string & base, 358 const std::string & extension, 359 memory_pool *pool = nullptr); 360 361 /// get current working directory 362 363 extern std::string tools_getcwd(); 364 365 /// returns the file pointed to by a symbolic link (or transparent if the file is not a symlink). 366 367 /// \param root the path to the file to read 368 /// \return the file pointed to by the symlink or the value given in argument if it is not a symlink 369 /// \note an exception can occur if lack of memory or invalid argument given (nullptr or empty string), system call error... 370 extern std::string tools_readlink(const char *root); 371 372 /// test the presence of an argument 373 374 /// \param[in] argument is the command line argument to look for 375 /// \param[in] argc is the number of argument on the command line 376 /// \param[in] argv is the list of argument on the command line 377 /// \return true if the argument is present in the list 378 /// \note THIS ROUTINE IS DEPRECATED AND WILL BE REMOVED IN A FUTURE VERSION OF LIBDAR 379 extern bool tools_look_for(const char *argument, S_I argc, char *const argv[]); 380 381 382 /// set dates of a given file, no exception thrown 383 384 /// \param[in] chem the path to the file to set 385 /// \param[in] symlink true if the file is a symlink 386 /// \param[in] last_acc last access date to use 387 /// \param[in] last_mod last modification date to use 388 /// \param[in] birth creation date of the file, if not known, use the value of last_mod for efficiency 389 extern void tools_noexcept_make_date(const std::string & chem, bool symlink, const datetime & last_acc, const datetime & last_mod, const datetime & birth); 390 391 /// set dates of a given file, may throw exception 392 393 /// \param[in] chemin the path to the file to set 394 /// \param[in] symlink true if the file is a symlink 395 /// \param[in] access last access date to use 396 /// \param[in] modif last modification date to use 397 /// \param[in] birth time of creation of the file 398 /// \note if birth time is not known, it should be set to the value of modif for efficiency 399 extern void tools_make_date(const std::string & chemin, bool symlink, const datetime & access, const datetime & modif, const datetime & birth); 400 401 /// compare two string in case insensitive manner 402 403 /// \param[in] a first string to compare 404 /// \param[in] b second string to compare 405 /// \return whether the two string given in argument are equal in case insensitive comparison 406 extern bool tools_is_case_insensitive_equal(const std::string & a, const std::string & b); 407 408 /// \brief convert a string to upper case 409 /// 410 /// \param[in] r the string to convert 411 /// \param[out] uppered resulting upper cased string 412 /// \note in case of invalid wide char met in source string, the upper case convertion 413 /// is done in ASCII mode (byte by byte) 414 extern void tools_to_upper(const std::string & r, std::string & uppered); 415 416 #if HAVE_WCTYPE_H 417 /// \brief convert a wstring to upper case 418 /// 419 /// \param[in,out] r to convert 420 /// \note wstring is a string of wchar_t (wide-char) type used to store 421 /// on variable lenght of byte sequence the many characters defined with UTF 422 /// like cirillic and greek letters. 423 extern void tools_to_wupper(std::wstring & r); 424 #endif 425 426 /// remove last character of a string is it equal to a given value 427 428 /// \param[in] c the given value to compare the last char with 429 /// \param[in,out] s the string to modify 430 extern void tools_remove_last_char_if_equal_to(char c, std::string & s); 431 432 /// from a string with a range notation (min-max) extract the range values 433 434 /// \param[in] s the string to parse 435 /// \param[out] min the minimum value of the range 436 /// \param[out] max the maximum value of the range 437 /// \exception Erange is thrown is the string to parse is incorrect 438 /// \note: either a single number (positive or negative) is returned in min 439 /// (max is set to min if min is positive or to zero if min is negative) 440 /// or a range of positive numbers. 441 extern void tools_read_range(const std::string & s, S_I & min, U_I & max); 442 443 444 /// make printf-like formating to a std::string 445 446 /// \param[in] format the format string 447 /// \param[in] ... list of argument to use against the format string 448 /// \return the resulting string 449 /// \note the supported masks for the format are: 450 /// - \%s \%c \%d \%\% (usual behavior) 451 /// - \%x display an integer under hexadecimal notation 452 /// - \%i (matches infinint *) 453 /// - \%S (matches std::string *) 454 /// . 455 extern std::string tools_printf(const char *format, ...); 456 457 /// make printf-like formating to a std::string 458 459 /// \param[in] format the format string 460 /// \param[in] ap list of argument to use against the format string 461 /// \return the resulting string 462 /// \note the supported masks for the format are: 463 /// - \%s \%c \%d \%\% (normal behavior) 464 /// - \%i (matches infinint *) 465 /// - \%S (matches std::string *) 466 /// . 467 extern std::string tools_vprintf(const char *format, va_list ap); 468 469 /// test the presence of files corresponding to a given mask in a directory (regex mask) 470 471 /// \param[in,out] ui for user interaction 472 /// \param[in] c_chemin directory where file have to be looked for 473 /// \param[in] file_mask regex expression which designates the files to look for 474 /// \return true if some files have found matching the file_mask 475 extern bool tools_do_some_files_match_mask_regex(user_interaction & ui, const std::string & c_chemin, const std::string & file_mask); 476 477 478 /// remove files from a given directory 479 480 /// \param[in,out] dialog for user interaction 481 /// \param[in] c_chemin directory where files have to be removed 482 /// \param[in] file_mask regex expression which designates the files to remove 483 /// \param[in] info_details whether user must be displayed details of the operation 484 /// \note This is equivalent to the 'rm' command with regex expression in place of glob one 485 extern void tools_unlink_file_mask_regex(user_interaction & dialog, const std::string & c_chemin, const std::string & file_mask, bool info_details); 486 487 488 /// prevents slice overwriting: check the presence of slice and if necessary ask the user if they can be removed 489 490 /// \param[in,out] dialog for user interaction 491 /// \param[in] chemin where slice is about to be created 492 /// \param[in] basename is the archive basename 493 /// \param[in] extension is the archive filename extension 494 /// \param[in] info_details whether user must be displayed details of the operation 495 /// \param[in] allow_overwriting whether overwriting is allowed by the user 496 /// \param[in] warn_overwriting whether a warning must be issued before overwriting (if allowed) 497 /// \param[in] dry_run do a dry-run exection (no filesystem modification is performed) 498 /// \note may thow exceptions. 499 extern void tools_avoid_slice_overwriting_regex(user_interaction & dialog, 500 const path & chemin, 501 const std::string & basename, 502 const std::string & extension, 503 bool info_details, 504 bool allow_overwriting, 505 bool warn_overwriting, 506 bool dry_run); 507 508 /// append an elastic buffer of given size to the file 509 510 /// \param[in,out] f file to append elastic buffer to 511 /// \param[in] max_size size of the elastic buffer to add 512 /// \param[in] modulo defines the size to choose (see note) 513 /// \param[in] offset defines the offset to apply (see note) 514 /// \note the size of the elastic buffer should not exceed max_size but 515 /// should be chosen in order to reach a size which is zero modulo "modulo" 516 /// assuming the offset we add the elastic buffer at is "offset". If modulo is zero 517 /// this the elastic buffer is randomly chosen from 1 to max_size without any 518 /// concern about being congruent to a given modulo. 519 /// Example if module is 5 and offset is 2, the elastic buffer possible size 520 /// can be 3 (2+3 is congruent to 0 modulo 5), 8 (2+8 is congruent to modulo 5), 12, etc. 521 /// but not exceed max_size+modulo-1 522 /// \note this is to accomodate the case when encrypted data is followed by clear data 523 /// at the end of an archive. There is no way to known when we read clear data, but we 524 /// know the clear data size is very inferior to crypted block size, thus when reading 525 /// a uncompleted block of data we can be sure we have reached and of file and that 526 /// the data is clear without any encrypted part because else we would have read an entire 527 /// block of data. 528 extern void tools_add_elastic_buffer(generic_file & f, 529 U_32 max_size, 530 U_32 modulo, 531 U_32 offset); 532 533 534 /// tells whether two files are on the same mounted filesystem 535 /// 536 /// \param[in] file1 first file 537 /// \param[in] file2 second file 538 /// \return true if the two file are located under the same mounting point 539 /// \note if one of the file is not present or if the filesystem information 540 /// is not possible to be read an exception is throw (Erange) 541 extern bool tools_are_on_same_filesystem(const std::string & file1, const std::string & file2); 542 543 544 /// transform a relative path to an absolute one given the current directory value 545 546 /// \param[in] src the relative path to transform 547 /// \param[in] cwd the value to take for the current directory 548 /// \return the corresponding absolute path 549 extern path tools_relative2absolute_path(const path & src, const path & cwd); 550 551 /// block all signals (based on POSIX sigprocmask) 552 553 /// \param[out] old_mask is set to the old mask value (for later unmasking signals) 554 /// \exception Erange is thrown if system call failed for some reason 555 extern void tools_block_all_signals(sigset_t &old_mask); 556 557 /// unblock signals according to given mask 558 559 /// \param[in] old_mask value to set to blocked signal mask 560 /// \exception Erange is thrown if system call failed for some reason 561 extern void tools_set_back_blocked_signals(sigset_t old_mask); 562 563 /// counts the number of a given char in a given string 564 565 /// \param[in] s string to look inside of 566 /// \param[in] a char to look for 567 /// \return the number of char found 568 extern U_I tools_count_in_string(const std::string & s, const char a); 569 570 /// returns the last modification date of the given file 571 572 /// \param[in,out] dialog for user interaction 573 /// \param[in] s path of the file to get the last mtime 574 /// \param[in] auto_zeroing whether to just warn instead of asking user confirmation 575 /// \param[in] silent if set do not warn nor ask 576 /// \return the mtime of the given file 577 extern datetime tools_get_mtime(user_interaction & dialog, 578 const std::string & s, 579 bool auto_zeroing, 580 bool silent); 581 582 /// returns the size of the given plain file 583 584 /// \param[in] s path of the file to get the size 585 /// \return the size if the file in byte 586 extern infinint tools_get_size(const std::string & s); 587 588 /// returns the last change date of the given file 589 590 /// \param[in] s path of the file to get the last ctime 591 /// \return the ctime of the given file 592 extern datetime tools_get_ctime(const std::string & s); 593 594 /// read a file and split its contents into words 595 596 /// \param[in,out] f is the file to read 597 /// \return the list of words found in this order in the file 598 /// \note The different quotes are taken into account 599 extern std::vector<std::string> tools_split_in_words(generic_file & f); 600 601 602 /// read a std::string and split its contents into words 603 604 /// \param[in,out] arg is the string to read 605 /// \return the list of words found in this order in the file 606 /// \note The different quotes are taken into account 607 extern std::vector<std::string> tools_split_in_words(const std::string & arg); 608 609 610 /// look next char in string out of parenthesis 611 612 /// \param[in] data is the string to look into 613 /// \param[in] what is the char to look for 614 /// \param[in] start is the index in string to start from, assuming at given position we are out of parenthesis 615 /// \param[out] found the position of the next char equal to what 616 /// \return true if a char equal to 'what' has been found and set the 'found' argument to its position or returns false if 617 /// no such character has been found out of parenthesis 618 /// \note the 'found' argument is assigned only if the call returns true, its value is not to be used when false is returned from the call 619 /// \note second point, the start data should point to a character that is out of any parenthesis, behavior is undefined else. 620 extern bool tools_find_next_char_out_of_parenthesis(const std::string & data, const char what, U_32 start, U_32 & found); 621 622 623 /// produce the string resulting from the substition of % macro defined in the map 624 625 /// \param[in] hook is the user's expression in which to proceed to substitution 626 /// \param[in] corres is a map telling which char following a % sign to replace by which string 627 /// \return the resulting string of the substitution 628 extern std::string tools_substitute(const std::string & hook, 629 const std::map<char, std::string> & corres); 630 631 632 /// produces the string resulting from the substitution of %... macro 633 634 /// \param[in] hook the string in which to substitute 635 /// \param[in] path is by what %p will be replaced 636 /// \param[in] basename is by what %b will be replaced 637 /// \param[in] num is by what %n will be replaced 638 /// \param[in] padded_num is by what %N will be replaced 639 /// \param[in] ext is by what %e will be replaced 640 /// \param[in] context is by what %c will be replaced 641 /// \return the substitued resulting string 642 /// \note it now relies on tools_substitue 643 extern std::string tools_hook_substitute(const std::string & hook, 644 const std::string & path, 645 const std::string & basename, 646 const std::string & num, 647 const std::string & padded_num, 648 const std::string & ext, 649 const std::string & context); 650 651 652 /// execute and retries at user will a given command line 653 654 /// \param[in] ui which way to ask the user whether to continue upon command line error 655 /// \param[in] cmd_line the command line to execute 656 extern void tools_hook_execute(user_interaction & ui, 657 const std::string & cmd_line); 658 659 660 /// subsititue and execute command line 661 662 /// \param[in,out] ui this is the way to contact the user 663 /// \param[in] hook the string in which to substitute 664 /// \param[in] path is by what %p will be replaced 665 /// \param[in] basename is by what %b will be replaced 666 /// \param[in] num is by what %n will be replaced 667 /// \param[in] padded_num is by what %N will be replaced 668 /// \param[in] ext is by what %e will be replaced 669 /// \param[in] context is by what %c will be replaced 670 extern void tools_hook_substitute_and_execute(user_interaction & ui, 671 const std::string & hook, 672 const std::string & path, 673 const std::string & basename, 674 const std::string & num, 675 const std::string & padded_num, 676 const std::string & ext, 677 const std::string & context); 678 679 /// builds a regex from root directory and user provided regex to be applied to the relative path 680 681 682 /// \param[in] prefix is the root portion of the path 683 /// \param[in] relative_part is the user provided regex to be applied to the relative path 684 /// \return the corresponding regex to be applied to full absolute path 685 extern std::string tools_build_regex_for_exclude_mask(const std::string & prefix, 686 const std::string & relative_part); 687 688 /// convert string for xml output 689 690 /// \note any < > & quote and double quote are replaced by adequate sequence for unicode 691 /// \note second point, nothing is done here to replace system native strings to unicode 692 extern std::string tools_output2xml(const std::string & src); 693 694 /// convert octal string to integer 695 696 /// \param perm is a string representing a number in octal (string must have a leading zero) 697 /// \return the corresponding value as an integer 698 extern U_I tools_octal2int(const std::string & perm); 699 700 701 /// convert a number to a string corresponding to its octal representation 702 703 /// \param perm is the octal number 704 /// \return the corresponding octal string 705 extern std::string tools_int2octal(const U_I & perm); 706 707 /// convert a permission number into its string representation (rwxrwxrwx) 708 709 extern std::string tools_get_permission_string(char type, U_32 perm, bool hard); 710 711 /// change the permission of the file which descriptor is given 712 713 /// \param[in] fd file's descriptor 714 /// \param[in] perm file permission to set the file to 715 extern void tools_set_permission(S_I fd, U_I perm); 716 717 /// obtain the permission of the file which descriptor is given 718 719 /// \param[in] fd file's descriptor 720 /// \return permission of the given file 721 /// \note in case of error exception may be thrown 722 extern U_I tools_get_permission(S_I fd); 723 724 /// change ownership of the file which descriptor is given 725 726 /// convert string user name or uid to numeric uid value 727 728 /// \param[in] user string username 729 /// \return uid value 730 extern uid_t tools_ownership2uid(const std::string & user); 731 732 /// convert string group name or gid to numeric gid value 733 734 /// \param[in] group string username 735 /// \return uid value 736 extern uid_t tools_ownership2gid(const std::string & group); 737 738 /// change ownership of the file which descriptor is given 739 740 /// \param[in] filedesc file's descriptor 741 /// \param[in] slice_user the user to set the file to. For empty string, no attempts to change the user ownership is done 742 /// \param[in] slice_group the group to set the file to. For empty string, no attempts to change the group ownership is done 743 /// \note this call may throw Erange exception upon system error 744 extern void tools_set_ownership(S_I filedesc, const std::string & slice_user, const std::string & slice_group); 745 746 /// Produces in "dest" the XORed value of "dest" and "src" 747 748 /// \param[in,out] dest is the area where to write down the result 749 /// \param[in] src points to vector or array of values to convert 750 /// \param[in] n is the number of byte to convert from src to dest 751 /// \note dest *must* be a valid pointer to an allocated memory area of at least n bytes 752 extern void tools_memxor(void *dest, const void *src, U_I n); 753 754 /// Produces a list of TLV from a constant type and a list of string 755 756 /// \param[in,out] dialog for user interaction 757 /// \param[in] type is the type each TLV will have 758 /// \param[in] data is the list of string to convert into a list of TLV 759 /// \return a tlv_list object. Each TLV in the list correspond to a string in the given list 760 extern tlv_list tools_string2tlv_list(user_interaction & dialog, const U_16 & type, const std::vector<std::string> & data); 761 762 763 764 /// Extract from anonymous pipe a tlv_list 765 766 /// \param[in,out] dialog for user interaction 767 /// \param[in] fd the filedescriptor for the anonymous pipe's read extremity 768 /// \param[out] result the resulting tlv_list 769 extern void tools_read_from_pipe(user_interaction & dialog, S_I fd, tlv_list & result); 770 771 772 773 /// Produces a pseudo random number x, where 0 <= x < max 774 775 /// \param[in] max defines the range of the random number to return 776 /// \return the returned value ranges from 0 (zero) up to max (= including max) 777 extern U_I tools_pseudo_random(U_I max); 778 779 780 /// Template for the decomposition of any number in any base (decimal, octal, hexa, etc.) 781 782 /// \param[in] number is the number to decompose 783 /// \param[in] base is the base to decompose the number into 784 /// \return a vector of 'digit' int the specified base, the first beeing the less significative 785 /// \note this template does not take care of the possibily existing optimized euclide division to speed up the operation 786 /// like what exists for infinint. A specific overriden fonction for this type would be better. 787 /// \note, the name "big_endian" is erroneous, it gives a little endian vector 788 tools_number_base_decomposition_in_big_endian(N number,const B & base)789 template <class N, class B> std::vector<B> tools_number_base_decomposition_in_big_endian(N number, const B & base) 790 { 791 std::vector<B> ret; 792 793 if(base <= 0) 794 throw Erange("tools_number_decoupe_in_big_endian", "base must be strictly positive"); 795 796 while(number != 0) 797 { 798 ret.push_back(number % base); 799 number /= base; 800 } 801 802 return ret; 803 } 804 805 /// convert a unsigned char into its hexa decima representation 806 807 /// \param[in] x is the byte to convert 808 /// \return the string representing the value of x written in hexadecimal 809 std::string tools_unsigned_char_to_hexa(unsigned char x); 810 811 /// convert a string into its hexadecima representation 812 813 /// \param[in] input input string to convert 814 /// \return a string containing an hexadecimal number corresponding to the bytes of the input string 815 816 std::string tools_string_to_hexa(const std::string & input); 817 818 /// Defines the CRC size to use for a given filesize 819 820 /// \param[in] size is the size of the file to protect by CRC 821 /// \return crc_size is the size of the crc to use 822 extern infinint tools_file_size_to_crc_size(const infinint & size); 823 824 /// return a string containing the Effective UID 825 extern std::string tools_get_euid(); 826 827 /// return a string containing the Effective UID 828 extern std::string tools_get_egid(); 829 830 /// return a string containing the hostname of the current host 831 extern std::string tools_get_hostname(); 832 833 /// return a string containing the current time (UTC) 834 extern std::string tools_get_date_utc(); 835 836 /// return the string about compression ratio 837 extern std::string tools_get_compression_ratio(const infinint & storage_size, const infinint & file_size, bool compressed); 838 839 /// wrapper routine to strerror_r 840 extern std::string tools_strerror_r(int errnum); 841 842 #ifdef GPGME_SUPPORT 843 /// wrapper routint to gpgme_strerror_r 844 extern std::string tools_gpgme_strerror_r(gpgme_error_t err); 845 #endif 846 847 #if HAVE_WCHAR_H 848 /// convert a std::string to std::wstring (wide-string, aka string of wchar_t) 849 extern std::wstring tools_string_to_wstring(const std::string & val); 850 851 /// convert a std::wstring to std::string 852 extern std::string tools_wstring_to_string(const std::wstring & val); 853 #endif 854 855 /// add in 'a', element of 'b' not already found in 'a' 856 extern void tools_merge_to_vector(std::vector<std::string> & a, const std::vector<std::string> & b); 857 858 /// remove from 'a' elements found in 'b' and return the resulting vector 859 extern std::vector<std::string> tools_substract_from_vector(const std::vector<std::string> & a, const std::vector<std::string> & b); 860 861 /// allocate a new dirent structure for use with readdir_r 862 /// 863 /// \param[in] path_name is the path of to the directory (and its underlying filesystem) 864 /// where the resulting dirent will be used. Depending on fileystem, the size of the dirent 865 /// structure may vary it is necessary to know the directory where the corresponding files 866 /// resides 867 /// \param[in] pool whether to allocate the structure on a memory_pool or out of memory_pool 868 /// \param[out] max_name_length is the maximum filename length allocated in the returned structure 869 /// which succeeds when pool is set to nullptr 870 /// \return a pointer to the newly allocated dirent structure 871 struct dirent *tools_allocate_struct_dirent(const std::string & path_name, U_64 & max_name_length, memory_pool *pool = nullptr); 872 873 874 /// release a dirent structure as allocated by tools_allocate_struct_dirent 875 /// 876 /// \param[in] ptr is the address of the structure to release 877 extern void tools_release_struct_dirent(struct dirent *ptr); 878 879 /// display the content of a secu_string, this function is only for trouble shooting! 880 extern void tools_secu_string_show(user_interaction & dialog, const std::string & msg, const secu_string & key); 881 tools_max(T a,T b)882 template <class T> T tools_max(T a, T b) { return a > b ? a : b; } tools_min(T a,T b)883 template <class T> T tools_min(T a, T b) { return a > b ? b : a; } 884 885 /// escape with a anti-slash character a set of chars found in the given string 886 extern std::string tools_escape_chars_in_string(const std::string & val, const char *to_escape); 887 888 /// convert an infinint to U_64 (aka "uint64_t" or yet "unsigned long long") 889 890 /// \note: if the infinint is too large to fit in an U_64 it returns false 891 extern bool tools_infinint2U_64(infinint val, U_64 & res); 892 893 894 /// check the value is not negative, and if asked set it to zero 895 896 ///\param[in,out] val variable which value to check 897 ///\param[in,out] ui for user interaction if necessary 898 ///\param[in] inode_path to the inode for message info 899 ///\param[in] nature type of the date/time (mtime,atime,ctime,birthtime,...) 900 ///\param[in] ask_before whether to just warn or ask user for confirmation 901 ///\param[in] silent if set, do not warn nor ask tools_check_negative_date(T & val,user_interaction & ui,const char * inode_path,const char * nature,bool ask_before,bool silent)902 template <class T> void tools_check_negative_date(T & val, 903 user_interaction & ui, 904 const char *inode_path, 905 const char *nature, 906 bool ask_before, 907 bool silent) 908 { 909 if(val < 0) 910 { 911 if(!silent) 912 { 913 std::string msg = tools_printf(gettext("Found negative date (%s) for inode %s ."), 914 nature, 915 inode_path); 916 if(ask_before) 917 ui.pause(tools_printf(gettext("%S Can we read it as if it was zero (1st January 1970 at 00:00:00 UTC)?"), 918 &msg)); 919 else // just warn 920 ui.warning(msg + gettext("Considering date as if it was zero (Jan 1970)")); 921 } 922 923 val = 0; 924 } 925 } 926 927 } /// end of namespace 928 929 #endif 930