LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - util.h (source / functions) Hit Total Coverage
Test: stap.info Lines: 68 83 81.9 %
Date: 2013-03-08 Functions: 41 49 83.7 %
Branches: 196 524 37.4 %

           Branch data     Line data    Source code
       1                 :            : #ifndef UTIL_H
       2                 :            : #define UTIL_H
       3                 :            : 
       4                 :            : #include "config.h"
       5                 :            : #include <cstdlib>
       6                 :            : #include <cstring>
       7                 :            : #include <cerrno>
       8                 :            : #include <string>
       9                 :            : #include <vector>
      10                 :            : #include <iostream>
      11                 :            : #include <sstream>
      12                 :            : #include <stdexcept>
      13                 :            : #include <cctype>
      14                 :            : #include <set>
      15                 :            : #include <iomanip>
      16                 :            : #include <map>
      17                 :            : extern "C" {
      18                 :            : #include <libintl.h>
      19                 :            : #include <locale.h>
      20                 :            : #include <signal.h>
      21                 :            : #include <stdint.h>
      22                 :            : #include <spawn.h>
      23                 :            : #include <assert.h>
      24                 :            : #include <poll.h>
      25                 :            : }
      26                 :            : 
      27                 :            : #include "privilege.h"
      28                 :            : 
      29                 :            : #if ENABLE_NLS
      30                 :            : #define _(string) gettext(string)
      31                 :            : #define _N(string, string_plural, count) \
      32                 :            :         ngettext((string), (string_plural), (count))
      33                 :            : #else
      34                 :            : #define _(string) (string)
      35                 :            : #define _N(string, string_plural, count) \
      36                 :            :         ( (count) == 1 ? (string) : (string_plural) )
      37                 :            : #endif
      38                 :            : #define _F(format, ...) autosprintf(_(format), __VA_ARGS__)
      39                 :            : #define _NF(format, format_plural, count, ...) \
      40                 :            :         autosprintf(_N((format), (format_plural), (count)), __VA_ARGS__)
      41                 :            : 
      42                 :            : const char *get_home_directory(void);
      43                 :            : size_t get_file_size(const std::string &path);
      44                 :            : size_t get_file_size(int fd);
      45                 :            : bool file_exists (const std::string &path);
      46                 :            : bool copy_file(const std::string& src, const std::string& dest,
      47                 :            :                bool verbose=false);
      48                 :            : int create_dir(const char *dir, int mode = 0777);
      49                 :            : int remove_file_or_dir(const char *dir);
      50                 :            : extern "C" gid_t get_gid (const char *group_name);
      51                 :            : bool in_group_id (gid_t target_gid);
      52                 :            : std::string getmemusage ();
      53                 :            : void tokenize(const std::string& str, std::vector<std::string>& tokens,
      54                 :            :               const std::string& delimiters);
      55                 :            : void tokenize_full(const std::string& str, std::vector<std::string>& tokens,
      56                 :            :               const std::string& delimiters);
      57                 :            : void tokenize_cxx(const std::string& str, std::vector<std::string>& tokens);
      58                 :            : std::string find_executable(const std::string& name);
      59                 :            : std::string find_executable(const std::string& name,
      60                 :            :                             const std::string& sysroot,
      61                 :            :                             const std::map<std::string,std::string>& sysenv,
      62                 :            :                             const std::string& env_path = "PATH");
      63                 :            : const std::string cmdstr_quoted(const std::string& cmd);
      64                 :            : const std::string cmdstr_join(const std::vector<std::string>& cmds);
      65                 :            : int stap_waitpid(int verbose, pid_t pid);
      66                 :            : pid_t stap_spawn(int verbose, const std::vector<std::string>& args);
      67                 :            : pid_t stap_spawn(int verbose, const std::vector<std::string>& args,
      68                 :            :                  posix_spawn_file_actions_t* fa, const std::vector<std::string>& envVec = std::vector<std::string> ());
      69                 :            : pid_t stap_spawn_piped(int verbose, const std::vector<std::string>& args,
      70                 :            :                        int* child_in=NULL, int* child_out=NULL, int* child_err=NULL);
      71                 :            : int stap_system(int verbose, const std::string& description,
      72                 :            :                 const std::vector<std::string>& args,
      73                 :            :                 bool null_out=false, bool null_err=false);
      74                 :       2689 : inline int stap_system(int verbose, const std::vector<std::string>& args,
      75                 :            :                        bool null_out=false, bool null_err=false)
      76                 :       2689 : { return stap_system(verbose, args.front(), args, null_out, null_err); }
      77                 :            : int stap_system_read(int verbose, const std::vector<std::string>& args, std::ostream& out);
      78                 :            : int kill_stap_spawn(int sig);
      79                 :            : void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re);
      80                 :            : int regexp_match (const std::string& value, const std::string& re, std::vector<std::string>& matches);
      81                 :            : bool contains_glob_chars (const std::string &str);
      82                 :            : std::string escape_glob_chars (const std::string& str);
      83                 :            : std::string unescape_glob_chars (const std::string& str);
      84                 :            : std::string kernel_release_from_build_tree (const std::string &kernel_build_tree, int verbose = 0);
      85                 :            : std::string normalize_machine(const std::string& machine);
      86                 :            : int elf_class_from_normalized_machine(const std::string& machine);
      87                 :            : std::string autosprintf(const char* format, ...) __attribute__ ((format (printf, 1, 2)));
      88                 :            : const std::set<std::string>& localization_variables();
      89                 :            : std::string get_self_path();
      90                 :            : 
      91                 :            : // stringification generics
      92                 :            : 
      93                 :            : 
      94                 :            : template <typename IN>
      95                 :    5853417 : inline std::string lex_cast(IN const & in)
      96                 :            : {
      97 [ +  - ][ +  - ]:    5853417 :   std::ostringstream ss;
         [ +  - ][ +  - ]
                 [ +  - ]
      98 [ +  - ][ +  - ]:    5853417 :   if (!(ss << in))
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ -  + ]
      99 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     100 [ +  - ][ +  - ]:    5853417 :   return ss.str();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     101                 :            : }
     102                 :            : 
     103                 :            : 
     104                 :            : template <typename OUT>
     105                 :     152521 : inline OUT lex_cast(std::string const & in)
     106                 :            : {
     107 [ +  - ][ #  # ]:     152521 :   std::istringstream ss(in);
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
     108                 :            :   OUT out;
     109 [ +  - ][ +  - ]:     152521 :   if (!(ss >> out && ss.eof()))
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     110 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     111 [ +  - ][ #  # ]:     152521 :   return out;
         [ +  - ][ +  - ]
         [ #  # ][ #  # ]
     112                 :            : }
     113                 :            : 
     114                 :            : 
     115                 :            : // We want [u]int8_t to be treated numerically, not just extracting a char.
     116                 :            : template <>
     117                 :          0 : inline int8_t lex_cast(std::string const & in)
     118                 :            : {
     119                 :          0 :   int16_t out = lex_cast<int16_t>(in);
     120 [ #  # ][ #  # ]:          0 :   if (out < -128 || out > 127)
     121 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
     122                 :          0 :   return out;
     123                 :            : }
     124                 :            : template <>
     125                 :          0 : inline uint8_t lex_cast(std::string const & in)
     126                 :            : {
     127                 :          0 :   uint16_t out = lex_cast<uint16_t>(in);
     128 [ #  # ][ #  # ]:          0 :   if (out > 0xff && out < 0xff80) // don't error if it looks sign-extended
     129 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
     130                 :          0 :   return out;
     131                 :            : }
     132                 :            : 
     133                 :            : 
     134                 :            : template <typename IN>
     135                 :            : inline std::string
     136                 :      61187 : lex_cast_hex(IN const & in)
     137                 :            : {
     138         [ +  - ]:      61187 :   std::ostringstream ss;
     139 [ +  - ][ +  - ]:      61187 :   if (!(ss << std::showbase << std::hex << in << std::dec))
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
     140 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
     141 [ +  - ][ +  - ]:      61187 :   return ss.str();
     142                 :            : }
     143                 :            : 
     144                 :            : //Convert binary data to hex data.
     145                 :            : template <typename IN>
     146                 :            : inline std::string
     147                 :       2549 : hex_dump(IN const & in,  size_t len)
     148                 :            : {
     149 [ +  - ][ #  # ]:       2549 :   std::ostringstream ss;
     150                 :            :   unsigned i;
     151 [ +  - ][ +  - ]:       2549 :   if (!(ss << std::hex << std::setfill('0')))
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     152 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
         [ #  # ][ #  # ]
     153                 :            : 
     154 [ +  + ][ #  # ]:      53529 :   for(i = 0; i < len; i++)
     155                 :            :   {
     156                 :      50980 :     int temp = in[i];
     157 [ +  - ][ +  - ]:      50980 :     ss << std::setw(2) << temp;
         [ #  # ][ #  # ]
     158                 :            :   }
     159 [ +  - ][ #  # ]:       2549 :   std::string hex = ss.str();
     160 [ +  - ][ -  + ]:       2549 :   assert(hex.length() == 2 * len);
         [ #  # ][ #  # ]
     161 [ +  - ][ #  # ]:       2549 :   return hex;
     162                 :            : }
     163                 :            : 
     164                 :            : // Return as quoted string, so that when compiled as a C literal, it
     165                 :            : // would print to the user out nicely.
     166                 :            : template <typename IN>
     167                 :            : inline std::string
     168                 :    1546709 : lex_cast_qstring(IN const & in)
     169                 :            : {
     170 [ +  - ][ +  - ]:    1546709 :   std::stringstream ss;
         [ +  - ][ +  - ]
                 [ +  - ]
     171 [ +  - ][ +  - ]:    1546709 :   if (!(ss << in))
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ -  + ]
     172 [ #  # ][ #  # ]:          0 :     throw std::runtime_error(_("bad lexical cast"));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     173 [ +  - ][ +  - ]:    1546709 :   return lex_cast_qstring(ss.str());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     174                 :            : }
     175                 :            : 
     176                 :            : 
     177                 :            : template <>
     178                 :            : inline std::string
     179                 :    1760118 : lex_cast_qstring(std::string const & in)
     180                 :            : {
     181                 :    1760118 :   std::string out;
     182         [ +  - ]:    1760118 :   out += '"';
     183 [ +  - ][ +  + ]:   44693507 :   for (const char *p = in.c_str(); *p; ++p)
     184                 :            :     {
     185                 :   42933389 :       unsigned char c = *p;
     186         [ +  + ]:   42933389 :       if (! isprint(c))
     187                 :            :         {
     188         [ +  - ]:          4 :           out += '\\';
     189                 :            :           // quick & dirty octal converter
     190         [ +  - ]:          4 :           out += "01234567" [(c >> 6) & 0x07];
     191         [ +  - ]:          4 :           out += "01234567" [(c >> 3) & 0x07];
     192         [ +  - ]:          4 :           out += "01234567" [(c >> 0) & 0x07];
     193                 :            :         }
     194 [ +  + ][ +  + ]:   42933385 :       else if (c == '"' || c == '\\')
     195                 :            :         {
     196         [ +  - ]:     229775 :           out += '\\';
     197         [ +  - ]:     229775 :           out += c;
     198                 :            :         }
     199                 :            :       else
     200         [ +  - ]:   42703610 :         out += c;
     201                 :            :     }
     202         [ +  - ]:    1760118 :   out += '"';
     203                 :    1760118 :   return out;
     204                 :            : }
     205                 :            : 
     206                 :            : 
     207                 :            : // Delete all values from a map-like container and clear it
     208                 :            : // (The template is permissive -- be good!)
     209                 :            : template <typename T>
     210                 :     256663 : void delete_map(T& t)
     211                 :            : {
     212 [ +  - ][ +  - ]:   10696582 :   for (typename T::iterator i = t.begin(); i != t.end(); ++i)
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
                 [ +  + ]
     213 [ +  - ][ +  - ]:   10439919 :     delete i->second;
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     214                 :     256663 :   t.clear();
     215                 :     256663 : }
     216                 :            : 
     217                 :            : 
     218                 :            : // Automatically save a variable, and restore it at the
     219                 :            : // end of the function.
     220                 :            : template <class V>
     221                 :            : class save_and_restore
     222                 :            : {
     223                 :            :     V* ptr;
     224                 :            :     V previous_value;
     225                 :            : 
     226                 :            :   public:
     227                 :            :     // Optionally pass a second argument to the constructor to initialize the
     228                 :            :     // variable to some value, after saving its old value.
     229                 :            :     save_and_restore(V* ptr_in, V value_in): ptr(ptr_in), previous_value(*ptr_in) { *ptr_in = value_in; }
     230                 :       2150 :     save_and_restore(V*ptr_in): ptr(ptr_in), previous_value(*ptr_in){}
     231                 :            : 
     232                 :            :     // Retrieve the old value and restore it in the destructor
     233                 :       2150 :     ~save_and_restore() { *ptr = previous_value; }
     234                 :            : };
     235                 :            : 
     236                 :            : 
     237                 :            : // Returns whether a string starts with the given prefix
     238                 :            : inline bool
     239                 :    7493357 : startswith(const std::string & s, const char * prefix)
     240                 :            : {
     241                 :    7493357 :   return (s.compare(0, std::strlen(prefix), prefix) == 0);
     242                 :            : }
     243                 :            : 
     244                 :            : 
     245                 :            : // Returns whether a string ends with the given suffix
     246                 :            : inline bool
     247                 :      33602 : endswith(const std::string & s, const char * suffix)
     248                 :            : {
     249                 :      33602 :   size_t s_len = s.size(), suffix_len = std::strlen(suffix);
     250         [ +  + ]:      33602 :   if (suffix_len > s_len)
     251                 :          2 :     return false;
     252                 :      33602 :   return (s.compare(s_len - suffix_len, suffix_len, suffix) == 0);
     253                 :            : }
     254                 :            : 
     255                 :            : 
     256                 :            : // Mask our usual signals for the life of this object.
     257                 :            : struct stap_sigmasker {
     258                 :            :     sigset_t old;
     259                 :      10871 :     stap_sigmasker()
     260                 :            :       {
     261                 :            :         sigset_t mask;
     262                 :      10871 :         sigemptyset (&mask);
     263                 :      10871 :         sigaddset (&mask, SIGHUP);
     264                 :      10871 :         sigaddset (&mask, SIGPIPE);
     265                 :      10871 :         sigaddset (&mask, SIGINT);
     266                 :      10871 :         sigaddset (&mask, SIGTERM);
     267                 :      10871 :         sigprocmask (SIG_BLOCK, &mask, &old);
     268                 :      10871 :       }
     269                 :      10871 :     ~stap_sigmasker()
     270                 :            :       {
     271                 :      10871 :         sigprocmask (SIG_SETMASK, &old, NULL);
     272                 :      10871 :       }
     273                 :            : };
     274                 :            : 
     275                 :            : // Convert a possibly-relative path to a full path
     276                 :            : inline std::string
     277                 :            : resolve_path(const std::string& path)
     278                 :            : {
     279                 :            :   std::string result(path);
     280                 :            :   char* resolved_path = realpath(path.c_str(), NULL);
     281                 :            :   if (resolved_path)
     282                 :            :     {
     283                 :            :       result = resolved_path;
     284                 :            :       std::free(resolved_path);
     285                 :            :     }
     286                 :            :   return result;
     287                 :            : }
     288                 :            : 
     289                 :            : 
     290                 :            : #ifndef HAVE_PPOLL
     291                 :            : // This is a poor-man's ppoll; see the implementation for more details...
     292                 :            : int ppoll(struct pollfd *fds, nfds_t nfds,
     293                 :            :           const struct timespec *timeout_ts,
     294                 :            :           const sigset_t *sigmask);
     295                 :            : #endif
     296                 :            : 
     297                 :            : 
     298                 :            : #endif // UTIL_H
     299                 :            : 
     300                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9