Remove skygw_utils.h

The general purpose stuff in skygw_utils.h was moved to utils.h
and the corresponding implementation from skygw_utils.cc to utils.c.
Includes updated accordingly.

Skygw_utils.h is now only used by log_manager and by mlist, which
is only used by log_manager. Consequently, skygw_utils.h was moved
to server/maxscale.

Utils.h needs a separate overhaul.
This commit is contained in:
Johan Wikman 2016-10-14 19:41:50 +03:00
parent 571919264f
commit 1333da0712
69 changed files with 521 additions and 567 deletions

View File

@ -37,6 +37,9 @@ MXS_BEGIN_DECLS
#define MXS_ARRAY_NELEMS(array) ((size_t)(sizeof(array)/sizeof(array[0])))
bool utils_init(); /*< Call this first before using any other function */
void utils_end();
int setnonblocking(int fd);
char *gw_strend(register const char *s);
static char gw_randomchar();
@ -49,6 +52,21 @@ void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_le
int gw_getsockerrno(int fd);
char *create_hex_sha1_sha1_passwd(char *passwd);
char* trim(char *str);
char* squeeze_whitespace(char* str);
bool strip_escape_chars(char*);
bool is_valid_posix_path(char* path);
char* remove_mysql_comments(const char** src, const size_t* srcsize, char** dest,
size_t* destsize);
char* replace_values(const char** src, const size_t* srcsize, char** dest,
size_t* destsize);
char* replace_literal(char* haystack,
const char* needle,
const char* replacement);
char* replace_quoted(const char** src, const size_t* srcsize, char** dest, size_t* destsize);
MXS_END_DECLS
#endif

View File

@ -20,7 +20,6 @@
#include <maxscale/protocol/mysql.h>
#include <maxscale/platform.h>
#include <maxscale/query_classifier.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/modutil.h>
#include <maxscale/alloc.h>
#include "builtin_functions.h"

View File

@ -18,7 +18,7 @@
#include <maxscale/query_classifier.h>
#include <maxscale/buffer.h>
#include <maxscale/gwdirs.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/utils.h>
int main(int argc, char** argv)
{

View File

@ -21,7 +21,6 @@
#include <crypt.h>
#include <maxscale/users.h>
#include <maxscale/adminusers.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/gwdirs.h>
#include <sys/stat.h>

View File

@ -43,7 +43,6 @@
#include <maxscale/alloc.h>
#include <maxscale/atomic.h>
#include <maxscale/debug.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/spinlock.h>
#include <maxscale/hint.h>
#include <maxscale/log_manager.h>

View File

@ -58,7 +58,7 @@
#include <maxscale/users.h>
#include <maxscale/monitor.h>
#include <maxscale/modules.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/utils.h>
#include <maxscale/log_manager.h>
#include <mysql.h>
#include <sys/utsname.h>

View File

@ -43,7 +43,6 @@
#include <maxscale/service.h>
#include <maxscale/users.h>
#include <maxscale/dbusers.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/protocol/mysql.h>

View File

@ -81,7 +81,6 @@
#include <maxscale/gw.h>
#include <maxscale/poll.h>
#include <maxscale/atomic.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/hashtable.h>
#include <maxscale/listener.h>

View File

@ -30,7 +30,6 @@
#include <maxscale/session.h>
#include <maxscale/modules.h>
#include <maxscale/spinlock.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/alloc.h>

View File

@ -74,7 +74,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/query_classifier.h>

View File

@ -37,8 +37,6 @@
#include <maxscale/gw.h>
#include <maxscale/dcb.h>
#include <maxscale/session.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
SPINLOCK tmplock = SPINLOCK_INIT;

View File

@ -36,7 +36,6 @@
#include <dlfcn.h>
#include <maxscale/modules.h>
#include <maxscale/modinfo.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/version.h>
#include <maxscale/notification.h>

View File

@ -28,7 +28,6 @@
#include <maxscale/hashtable.h>
#include <maxscale/spinlock.h>
#include <maxscale/debug.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/alloc.h>
#include <maxscale/utils.h>
#include "maxscale/mlist.h"

View File

@ -25,7 +25,6 @@
#include <getopt.h>
#include <stdio.h>
#include <maxscale/secrets.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/gwdirs.h>

View File

@ -26,7 +26,6 @@
#include <maxscale/gwdirs.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/skygw_utils.h>
struct option options[] =
{

View File

@ -15,7 +15,7 @@
*/
#include <maxscale/cdefs.h>
#include <maxscale/skygw_utils.h>
#include "skygw_utils.h"
MXS_BEGIN_DECLS

View File

@ -96,9 +96,6 @@ struct skygw_file_st
skygw_chk_t sf_chk_tail;
};
bool utils_init(); /*< Call this first before using any other function */
void utils_end();
/** Skygw thread routines */
skygw_thread_t* skygw_thread_init(const char* name,
void* (*sth_thrfun)(void* data),
@ -167,19 +164,6 @@ int skygw_rwlock_init(skygw_rwlock_t** rwlock);
size_t get_decimal_len(size_t s);
char* remove_mysql_comments(const char** src, const size_t* srcsize, char** dest,
size_t* destsize);
char* replace_values(const char** src, const size_t* srcsize, char** dest,
size_t* destsize);
char* replace_literal(char* haystack,
const char* needle,
const char* replacement);
char* replace_quoted(const char** src, const size_t* srcsize, char** dest, size_t* destsize);
bool is_valid_posix_path(char* path);
bool strip_escape_chars(char*);
char* trim(char *str);
char* squeeze_whitespace(char* str);
MXS_END_DECLS
#endif /* SKYGW_UTILS_H */

View File

@ -30,7 +30,6 @@
#include <maxscale/alloc.h>
#include <maxscale/poll.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <strings.h>
/** These are used when converting MySQL wildcards to regular expressions */

View File

@ -33,7 +33,6 @@
#include <maxscale/monitor.h>
#include <maxscale/spinlock.h>
#include <maxscale/modules.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/pcre2.h>

View File

@ -24,7 +24,6 @@
#include <maxscale/dcb.h>
#include <maxscale/atomic.h>
#include <maxscale/gwbitmask.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/gw.h>
#include <maxscale/housekeeper.h>

View File

@ -16,7 +16,7 @@
#include <maxscale/modules.h>
#include <maxscale/modutil.h>
#include <maxscale/alloc.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/utils.h>
//#define QC_TRACE_ENABLED
#undef QC_TRACE_ENABLED

View File

@ -13,7 +13,6 @@
#include <maxscale/secrets.h>
#include <time.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <ctype.h>
#include <maxscale/protocol/mysql.h>

View File

@ -40,7 +40,6 @@
#include <maxscale/spinlock.h>
#include <maxscale/dcb.h>
#include <maxscale/poll.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/gw_ssl.h>
#include <maxscale/alloc.h>

View File

@ -55,7 +55,6 @@
#include <maxscale/filter.h>
#include <maxscale/dbusers.h>
#include <maxscale/poll.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <sys/stat.h>
#include <sys/types.h>

View File

@ -40,7 +40,6 @@
#include <maxscale/dcb.h>
#include <maxscale/spinlock.h>
#include <maxscale/atomic.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/housekeeper.h>

View File

@ -27,7 +27,7 @@
#include <regex.h>
#include <maxscale/debug.h>
#include <sys/time.h>
#include <maxscale/skygw_utils.h>
#include "maxscale/skygw_utils.h"
#include <maxscale/atomic.h>
#include <maxscale/random_jkiss.h>
#include <pcre2.h>
@ -40,8 +40,6 @@
# endif
#endif
#define MAX_ERROR_MSG PATH_MAX
static void simple_mutex_free_memory(simple_mutex_t* sm);
static void thread_free_memory(skygw_thread_t* th, char* name);
/** End of static function declarations */
@ -1006,298 +1004,6 @@ void skygw_file_close(skygw_file_t* file)
}
}
#define BUFFER_GROWTH_RATE 1.2
static pcre2_code* remove_comments_re = NULL;
static const PCRE2_SPTR remove_comments_pattern = (PCRE2_SPTR)
"(?:`[^`]*`\\K)|(\\/[*](?!(M?!)).*?[*]\\/)|(?:#.*|--[[:space:]].*)";
/**
* Remove SQL comments from the end of a string
*
* The inline executable comments are not removed due to the fact that they can
* alter the behavior of the query.
* @param src Pointer to the string to modify.
* @param srcsize Pointer to a size_t variable which holds the length of the string to
* be modified.
* @param dest The address of the pointer where the result will be stored. If the
* value pointed by this parameter is NULL, new memory will be allocated as needed.
* @param Pointer to a size_t variable where the size of the result string is stored.
* @return Pointer to new modified string or NULL if memory allocation failed.
* If NULL is returned and the value pointed by @c dest was not NULL, no new
* memory will be allocated, the memory pointed by @dest will be freed and the
* contents of @c dest and @c destsize will be invalid.
*/
char* remove_mysql_comments(const char** src, const size_t* srcsize, char** dest, size_t* destsize)
{
static const PCRE2_SPTR replace = (PCRE2_SPTR) "";
pcre2_match_data* mdata;
char* output = *dest;
size_t orig_len = *srcsize;
size_t len = output ? *destsize : orig_len;
if (orig_len > 0)
{
if ((output || (output = (char*) malloc(len * sizeof (char)))) &&
(mdata = pcre2_match_data_create_from_pattern(remove_comments_re, NULL)))
{
while (pcre2_substitute(remove_comments_re, (PCRE2_SPTR) * src, orig_len, 0,
PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL,
replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY)
{
char* tmp = (char*) realloc(output, (len = (size_t) (len * BUFFER_GROWTH_RATE + 1)));
if (tmp == NULL)
{
free(output);
output = NULL;
break;
}
output = tmp;
}
pcre2_match_data_free(mdata);
}
else
{
free(output);
output = NULL;
}
}
else if (output == NULL)
{
output = strdup(*src);
}
if (output)
{
*destsize = strlen(output);
*dest = output;
}
return output;
}
static pcre2_code* replace_values_re = NULL;
static const PCRE2_SPTR replace_values_pattern = (PCRE2_SPTR) "(?i)([-=,+*/([:space:]]|\\b|[@])"
"(?:[0-9.-]+|(?<=[@])[a-z_0-9]+)([-=,+*/)[:space:];]|$)";
/**
* Replace literal numbers and user variables with a question mark.
* @param src Pointer to the string to modify.
* @param srcsize Pointer to a size_t variable which holds the length of the string to
* be modified.
* @param dest The address of the pointer where the result will be stored. If the
* value pointed by this parameter is NULL, new memory will be allocated as needed.
* @param Pointer to a size_t variable where the size of the result string is stored.
* @return Pointer to new modified string or NULL if memory allocation failed.
* If NULL is returned and the value pointed by @c dest was not NULL, no new
* memory will be allocated, the memory pointed by @dest will be freed and the
* contents of @c dest and @c destsize will be invalid.
*/
char* replace_values(const char** src, const size_t* srcsize, char** dest, size_t* destsize)
{
static const PCRE2_SPTR replace = (PCRE2_SPTR) "$1?$2";
pcre2_match_data* mdata;
char* output = *dest;
size_t orig_len = *srcsize;
size_t len = output ? *destsize : orig_len;
if (orig_len > 0)
{
if ((output || (output = (char*) malloc(len * sizeof (char)))) &&
(mdata = pcre2_match_data_create_from_pattern(replace_values_re, NULL)))
{
while (pcre2_substitute(replace_values_re, (PCRE2_SPTR) * src, orig_len, 0,
PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL,
replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY)
{
char* tmp = (char*) realloc(output, (len = (size_t) (len * BUFFER_GROWTH_RATE + 1)));
if (tmp == NULL)
{
free(output);
output = NULL;
break;
}
output = tmp;
}
pcre2_match_data_free(mdata);
}
else
{
free(output);
output = NULL;
}
}
else if (output == NULL)
{
output = strdup(*src);
}
if (output)
{
*destsize = strlen(output);
*dest = output;
}
return output;
}
/**
* Find the given needle - user-provided literal - and replace it with
* replacement string. Separate user-provided literals from matching table names
* etc. by searching only substrings preceded by non-letter and non-number.
*
* @param haystack Plain text query string, not to be freed
* @param needle Substring to be searched, not to be freed
* @param replacement Replacement text, not to be freed
*
* @return newly allocated string where needle is replaced
*/
char* replace_literal(char* haystack, const char* needle, const char* replacement)
{
const char* prefix = "[ ='\",\\(]"; /*< ' ','=','(',''',''"',',' are allowed before needle */
const char* suffix = "([^[:alnum:]]|$)"; /*< alpha-num chars aren't allowed after the needle */
char* search_re;
char* newstr;
regex_t re;
regmatch_t match;
int rc;
size_t rlen = strlen(replacement);
size_t nlen = strlen(needle);
size_t hlen = strlen(haystack);
search_re = (char *) malloc(strlen(prefix) + nlen + strlen(suffix) + 1);
if (search_re == NULL)
{
char errbuf[MXS_STRERROR_BUFLEN];
fprintf(stderr, "Regex memory allocation failed : %s\n",
strerror_r(errno, errbuf, sizeof (errbuf)));
newstr = haystack;
goto retblock;
}
sprintf(search_re, "%s%s%s", prefix, needle, suffix);
/** Allocate memory for new string +1 for terminating byte */
newstr = (char *) malloc(hlen - nlen + rlen + 1);
if (newstr == NULL)
{
char errbuf[MXS_STRERROR_BUFLEN];
fprintf(stderr, "Regex memory allocation failed : %s\n",
strerror_r(errno, errbuf, sizeof (errbuf)));
free(search_re);
free(newstr);
newstr = haystack;
goto retblock;
}
rc = regcomp(&re, search_re, REG_EXTENDED | REG_ICASE);
ss_info_dassert(rc == 0, "Regex check");
if (rc != 0)
{
char error_message[MAX_ERROR_MSG];
regerror(rc, &re, error_message, MAX_ERROR_MSG);
fprintf(stderr, "Regex error compiling '%s': %s\n",
search_re, error_message);
free(search_re);
free(newstr);
newstr = haystack;
goto retblock;
}
rc = regexec(&re, haystack, 1, &match, 0);
if (rc != 0)
{
free(search_re);
free(newstr);
regfree(&re);
newstr = haystack;
goto retblock;
}
memcpy(newstr, haystack, match.rm_so + 1);
memcpy(newstr + match.rm_so + 1, replacement, rlen);
/** +1 is terminating byte */
memcpy(newstr + match.rm_so + 1 + rlen, haystack + match.rm_so + 1 + nlen, hlen - (match.rm_so + 1) - nlen + 1);
regfree(&re);
free(haystack);
free(search_re);
retblock:
return newstr;
}
static pcre2_code* replace_quoted_re = NULL;
static const PCRE2_SPTR replace_quoted_pattern = (PCRE2_SPTR)
"(?>[^'\"]*)(?|(?:\"\\K(?:(?:(?<=\\\\)\")|[^\"])*(\"))|(?:'\\K(?:(?:(?<=\\\\)')|[^'])*(')))";
/**
* Replace contents of single or double quoted strings with question marks.
* @param src Pointer to the string to modify.
* @param srcsize Pointer to a size_t variable which holds the length of the string to
* be modified.
* @param dest The address of the pointer where the result will be stored. If the
* value pointed by this parameter is NULL, new memory will be allocated as needed.
* @param Pointer to a size_t variable where the size of the result string is stored.
* @return Pointer to new modified string or NULL if memory allocation failed.
* If NULL is returned and the value pointed by @c dest was not NULL, no new
* memory will be allocated, the memory pointed by @dest will be freed and the
* contents of @c dest and @c destsize will be invalid.
*/
char* replace_quoted(const char** src, const size_t* srcsize, char** dest, size_t* destsize)
{
static const PCRE2_SPTR replace = (PCRE2_SPTR) "?$1";
pcre2_match_data* mdata;
char* output = *dest;
size_t orig_len = *srcsize;
size_t len = output ? *destsize : orig_len;
if (orig_len > 0)
{
if ((output || (output = (char*) malloc(len * sizeof (char)))) &&
(mdata = pcre2_match_data_create_from_pattern(replace_quoted_re, NULL)))
{
while (pcre2_substitute(replace_quoted_re, (PCRE2_SPTR) * src, orig_len, 0,
PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL,
replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY)
{
char* tmp = (char*) realloc(output, (len = (size_t) (len * BUFFER_GROWTH_RATE + 1)));
if (tmp == NULL)
{
free(output);
output = NULL;
break;
}
output = tmp;
}
pcre2_match_data_free(mdata);
}
else
{
free(output);
output = NULL;
}
}
else if (output == NULL)
{
output = strdup(*src);
}
if (output)
{
*destsize = strlen(output);
*dest = output;
}
else
{
*dest = NULL;
}
return output;
}
/**
* Calculate the number of decimal numbers from a size_t value.
*
@ -1312,192 +1018,3 @@ size_t get_decimal_len(
{
return value > 0 ? (size_t) log10((double) value) + 1 : 1;
}
/**
* Check if the provided pathname is POSIX-compliant. The valid characters
* are [a-z A-Z 0-9._-].
* @param path A null-terminated string
* @return true if it is a POSIX-compliant pathname, otherwise false
*/
bool is_valid_posix_path(char* path)
{
char* ptr = path;
while (*ptr != '\0')
{
if (isalnum(*ptr) || *ptr == '/' || *ptr == '.' || *ptr == '-' || *ptr == '_')
{
ptr++;
}
else
{
return false;
}
}
return true;
}
/**
* Strip escape characters from a character string.
* @param String to parse.
* @return True if parsing was successful, false on errors.
*/
bool
strip_escape_chars(char* val)
{
int cur, end;
if (val == NULL)
{
return false;
}
end = strlen(val) + 1;
cur = 0;
while (cur < end)
{
if (val[cur] == '\\')
{
memmove(val + cur, val + cur + 1, end - cur - 1);
end--;
}
cur++;
}
return true;
}
/**
* Trim leading and trailing whitespace from a string
*
* @param str String to trim
* @return Trimmed string
*/
char* trim(char *str)
{
char* ptr = strchr(str, '\0') - 1;
while (ptr > str && isspace(*ptr))
{
ptr--;
}
if (isspace(*(ptr + 1)))
{
*(ptr + 1) = '\0';
}
ptr = str;
while (isspace(*ptr))
{
ptr++;
}
if (ptr != str)
{
memmove(str, ptr, strlen(ptr) + 1);
}
return str;
}
/**
* Replace all whitespace with spaces and squeeze repeating whitespace characters
*
* @param str String to squeeze
* @return Squeezed string
*/
char* squeeze_whitespace(char* str)
{
char* store = str;
char* ptr = str;
/** Remove leading whitespace */
while (isspace(*ptr) && *ptr != '\0')
{
ptr++;
}
/** Squeeze all repeating whitespace */
while (*ptr != '\0')
{
while (isspace(*ptr) && isspace(*(ptr + 1)))
{
ptr++;
}
if (isspace(*ptr))
{
*store++ = ' ';
ptr++;
}
else
{
*store++ = *ptr++;
}
}
*store = '\0';
/** Remove trailing whitespace */
while (store > str && isspace(*(store - 1)))
{
store--;
*store = '\0';
}
return str;
}
/**
* Initialize the utils library
*
* This function initializes structures used in various functions.
* @return true on success, false on error
*/
bool utils_init()
{
bool rval = true;
PCRE2_SIZE erroffset;
int errcode;
ss_info_dassert(remove_comments_re == NULL, "utils_init called multiple times");
remove_comments_re = pcre2_compile(remove_comments_pattern, PCRE2_ZERO_TERMINATED, 0, &errcode,
&erroffset, NULL);
if (remove_comments_re == NULL)
{
rval = false;
}
ss_info_dassert(replace_quoted_re == NULL, "utils_init called multiple times");
replace_quoted_re = pcre2_compile(replace_quoted_pattern, PCRE2_ZERO_TERMINATED, 0, &errcode,
&erroffset, NULL);
if (replace_quoted_re == NULL)
{
rval = false;
}
ss_info_dassert(replace_values_re == NULL, "utils_init called multiple times");
replace_values_re = pcre2_compile(replace_values_pattern, PCRE2_ZERO_TERMINATED, 0, &errcode,
&erroffset, NULL);
if (replace_values_re == NULL)
{
rval = false;
}
return rval;
}
/**
* Close the utils library. This should be the last call to this library.
*/
void utils_end()
{
pcre2_code_free(remove_comments_re);
remove_comments_re = NULL;
pcre2_code_free(replace_quoted_re);
replace_quoted_re = NULL;
pcre2_code_free(replace_values_re);
replace_values_re = NULL;
}

View File

@ -31,7 +31,6 @@
#include <maxscale/dcb.h>
#include <maxscale/service.h>
#include <maxscale/users.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/dbusers.h>

View File

@ -37,7 +37,7 @@
#include <maxscale/gwdirs.h>
#include <maxscale/adminusers.h>
#include <maxscale/alloc.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/utils.h>
/**
* test1 default user

View File

@ -15,7 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include <maxscale/alloc.h>
#include <maxscale/skygw_utils.h>
#include "../maxscale/skygw_utils.h"
#include <maxscale/log_manager.h>
static void skygw_log_enable(int priority)

View File

@ -16,7 +16,7 @@
#include <stdlib.h>
#include <string.h>
#include <maxscale/alloc.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/debug.h>
#include <maxscale/log_manager.h>
static void skygw_log_enable(int priority)

View File

@ -29,16 +29,27 @@
*/
#include <regex.h>
#include <maxscale/gw.h>
#include <maxscale/dcb.h>
#include <maxscale/session.h>
#include <openssl/sha.h>
#include <maxscale/alloc.h>
#include <maxscale/poll.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/random_jkiss.h>
#include <maxscale/pcre2.h>
#if !defined(PATH_MAX)
# if defined(__USE_POSIX)
# define PATH_MAX _POSIX_PATH_MAX
# else
# define PATH_MAX 256
# endif
#endif
#define MAX_ERROR_MSG PATH_MAX
/* used in the hex2bin function */
#define char_val(X) (X >= '0' && X <= '9' ? X-'0' : \
@ -50,6 +61,29 @@
char hex_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char hex_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
/**
* Check if the provided pathname is POSIX-compliant. The valid characters
* are [a-z A-Z 0-9._-].
* @param path A null-terminated string
* @return true if it is a POSIX-compliant pathname, otherwise false
*/
bool is_valid_posix_path(char* path)
{
char* ptr = path;
while (*ptr != '\0')
{
if (isalnum(*ptr) || *ptr == '/' || *ptr == '.' || *ptr == '-' || *ptr == '_')
{
ptr++;
}
else
{
return false;
}
}
return true;
}
/*****************************************
* backend read event triggered by EPOLLIN
*****************************************/
@ -388,3 +422,461 @@ bool mxs_mkdir_all(const char *path, int mask)
return mkdir_all_internal(local_path, (mode_t)mask);
}
/**
* Trim leading and trailing whitespace from a string
*
* @param str String to trim
* @return Trimmed string
*/
char* trim(char *str)
{
char* ptr = strchr(str, '\0') - 1;
while (ptr > str && isspace(*ptr))
{
ptr--;
}
if (isspace(*(ptr + 1)))
{
*(ptr + 1) = '\0';
}
ptr = str;
while (isspace(*ptr))
{
ptr++;
}
if (ptr != str)
{
memmove(str, ptr, strlen(ptr) + 1);
}
return str;
}
/**
* Replace all whitespace with spaces and squeeze repeating whitespace characters
*
* @param str String to squeeze
* @return Squeezed string
*/
char* squeeze_whitespace(char* str)
{
char* store = str;
char* ptr = str;
/** Remove leading whitespace */
while (isspace(*ptr) && *ptr != '\0')
{
ptr++;
}
/** Squeeze all repeating whitespace */
while (*ptr != '\0')
{
while (isspace(*ptr) && isspace(*(ptr + 1)))
{
ptr++;
}
if (isspace(*ptr))
{
*store++ = ' ';
ptr++;
}
else
{
*store++ = *ptr++;
}
}
*store = '\0';
/** Remove trailing whitespace */
while (store > str && isspace(*(store - 1)))
{
store--;
*store = '\0';
}
return str;
}
/**
* Strip escape characters from a character string.
* @param String to parse.
* @return True if parsing was successful, false on errors.
*/
bool
strip_escape_chars(char* val)
{
int cur, end;
if (val == NULL)
{
return false;
}
end = strlen(val) + 1;
cur = 0;
while (cur < end)
{
if (val[cur] == '\\')
{
memmove(val + cur, val + cur + 1, end - cur - 1);
end--;
}
cur++;
}
return true;
}
#define BUFFER_GROWTH_RATE 1.2
static pcre2_code* remove_comments_re = NULL;
static const PCRE2_SPTR remove_comments_pattern = (PCRE2_SPTR)
"(?:`[^`]*`\\K)|(\\/[*](?!(M?!)).*?[*]\\/)|(?:#.*|--[[:space:]].*)";
/**
* Remove SQL comments from the end of a string
*
* The inline executable comments are not removed due to the fact that they can
* alter the behavior of the query.
* @param src Pointer to the string to modify.
* @param srcsize Pointer to a size_t variable which holds the length of the string to
* be modified.
* @param dest The address of the pointer where the result will be stored. If the
* value pointed by this parameter is NULL, new memory will be allocated as needed.
* @param Pointer to a size_t variable where the size of the result string is stored.
* @return Pointer to new modified string or NULL if memory allocation failed.
* If NULL is returned and the value pointed by @c dest was not NULL, no new
* memory will be allocated, the memory pointed by @dest will be freed and the
* contents of @c dest and @c destsize will be invalid.
*/
char* remove_mysql_comments(const char** src, const size_t* srcsize, char** dest, size_t* destsize)
{
static const PCRE2_SPTR replace = (PCRE2_SPTR) "";
pcre2_match_data* mdata;
char* output = *dest;
size_t orig_len = *srcsize;
size_t len = output ? *destsize : orig_len;
if (orig_len > 0)
{
if ((output || (output = (char*) malloc(len * sizeof (char)))) &&
(mdata = pcre2_match_data_create_from_pattern(remove_comments_re, NULL)))
{
while (pcre2_substitute(remove_comments_re, (PCRE2_SPTR) * src, orig_len, 0,
PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL,
replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY)
{
char* tmp = (char*) realloc(output, (len = (size_t) (len * BUFFER_GROWTH_RATE + 1)));
if (tmp == NULL)
{
free(output);
output = NULL;
break;
}
output = tmp;
}
pcre2_match_data_free(mdata);
}
else
{
free(output);
output = NULL;
}
}
else if (output == NULL)
{
output = strdup(*src);
}
if (output)
{
*destsize = strlen(output);
*dest = output;
}
return output;
}
static pcre2_code* replace_values_re = NULL;
static const PCRE2_SPTR replace_values_pattern = (PCRE2_SPTR) "(?i)([-=,+*/([:space:]]|\\b|[@])"
"(?:[0-9.-]+|(?<=[@])[a-z_0-9]+)([-=,+*/)[:space:];]|$)";
/**
* Replace literal numbers and user variables with a question mark.
* @param src Pointer to the string to modify.
* @param srcsize Pointer to a size_t variable which holds the length of the string to
* be modified.
* @param dest The address of the pointer where the result will be stored. If the
* value pointed by this parameter is NULL, new memory will be allocated as needed.
* @param Pointer to a size_t variable where the size of the result string is stored.
* @return Pointer to new modified string or NULL if memory allocation failed.
* If NULL is returned and the value pointed by @c dest was not NULL, no new
* memory will be allocated, the memory pointed by @dest will be freed and the
* contents of @c dest and @c destsize will be invalid.
*/
char* replace_values(const char** src, const size_t* srcsize, char** dest, size_t* destsize)
{
static const PCRE2_SPTR replace = (PCRE2_SPTR) "$1?$2";
pcre2_match_data* mdata;
char* output = *dest;
size_t orig_len = *srcsize;
size_t len = output ? *destsize : orig_len;
if (orig_len > 0)
{
if ((output || (output = (char*) malloc(len * sizeof (char)))) &&
(mdata = pcre2_match_data_create_from_pattern(replace_values_re, NULL)))
{
while (pcre2_substitute(replace_values_re, (PCRE2_SPTR) * src, orig_len, 0,
PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL,
replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY)
{
char* tmp = (char*) realloc(output, (len = (size_t) (len * BUFFER_GROWTH_RATE + 1)));
if (tmp == NULL)
{
free(output);
output = NULL;
break;
}
output = tmp;
}
pcre2_match_data_free(mdata);
}
else
{
free(output);
output = NULL;
}
}
else if (output == NULL)
{
output = strdup(*src);
}
if (output)
{
*destsize = strlen(output);
*dest = output;
}
return output;
}
/**
* Find the given needle - user-provided literal - and replace it with
* replacement string. Separate user-provided literals from matching table names
* etc. by searching only substrings preceded by non-letter and non-number.
*
* @param haystack Plain text query string, not to be freed
* @param needle Substring to be searched, not to be freed
* @param replacement Replacement text, not to be freed
*
* @return newly allocated string where needle is replaced
*/
char* replace_literal(char* haystack, const char* needle, const char* replacement)
{
const char* prefix = "[ ='\",\\(]"; /*< ' ','=','(',''',''"',',' are allowed before needle */
const char* suffix = "([^[:alnum:]]|$)"; /*< alpha-num chars aren't allowed after the needle */
char* search_re;
char* newstr;
regex_t re;
regmatch_t match;
int rc;
size_t rlen = strlen(replacement);
size_t nlen = strlen(needle);
size_t hlen = strlen(haystack);
search_re = (char *) malloc(strlen(prefix) + nlen + strlen(suffix) + 1);
if (search_re == NULL)
{
char errbuf[MXS_STRERROR_BUFLEN];
fprintf(stderr, "Regex memory allocation failed : %s\n",
strerror_r(errno, errbuf, sizeof (errbuf)));
newstr = haystack;
goto retblock;
}
sprintf(search_re, "%s%s%s", prefix, needle, suffix);
/** Allocate memory for new string +1 for terminating byte */
newstr = (char *) malloc(hlen - nlen + rlen + 1);
if (newstr == NULL)
{
char errbuf[MXS_STRERROR_BUFLEN];
fprintf(stderr, "Regex memory allocation failed : %s\n",
strerror_r(errno, errbuf, sizeof (errbuf)));
free(search_re);
free(newstr);
newstr = haystack;
goto retblock;
}
rc = regcomp(&re, search_re, REG_EXTENDED | REG_ICASE);
ss_info_dassert(rc == 0, "Regex check");
if (rc != 0)
{
char error_message[MAX_ERROR_MSG];
regerror(rc, &re, error_message, MAX_ERROR_MSG);
fprintf(stderr, "Regex error compiling '%s': %s\n",
search_re, error_message);
free(search_re);
free(newstr);
newstr = haystack;
goto retblock;
}
rc = regexec(&re, haystack, 1, &match, 0);
if (rc != 0)
{
free(search_re);
free(newstr);
regfree(&re);
newstr = haystack;
goto retblock;
}
memcpy(newstr, haystack, match.rm_so + 1);
memcpy(newstr + match.rm_so + 1, replacement, rlen);
/** +1 is terminating byte */
memcpy(newstr + match.rm_so + 1 + rlen, haystack + match.rm_so + 1 + nlen, hlen - (match.rm_so + 1) - nlen + 1);
regfree(&re);
free(haystack);
free(search_re);
retblock:
return newstr;
}
static pcre2_code* replace_quoted_re = NULL;
static const PCRE2_SPTR replace_quoted_pattern = (PCRE2_SPTR)
"(?>[^'\"]*)(?|(?:\"\\K(?:(?:(?<=\\\\)\")|[^\"])*(\"))|(?:'\\K(?:(?:(?<=\\\\)')|[^'])*(')))";
/**
* Replace contents of single or double quoted strings with question marks.
* @param src Pointer to the string to modify.
* @param srcsize Pointer to a size_t variable which holds the length of the string to
* be modified.
* @param dest The address of the pointer where the result will be stored. If the
* value pointed by this parameter is NULL, new memory will be allocated as needed.
* @param Pointer to a size_t variable where the size of the result string is stored.
* @return Pointer to new modified string or NULL if memory allocation failed.
* If NULL is returned and the value pointed by @c dest was not NULL, no new
* memory will be allocated, the memory pointed by @dest will be freed and the
* contents of @c dest and @c destsize will be invalid.
*/
char* replace_quoted(const char** src, const size_t* srcsize, char** dest, size_t* destsize)
{
static const PCRE2_SPTR replace = (PCRE2_SPTR) "?$1";
pcre2_match_data* mdata;
char* output = *dest;
size_t orig_len = *srcsize;
size_t len = output ? *destsize : orig_len;
if (orig_len > 0)
{
if ((output || (output = (char*) malloc(len * sizeof (char)))) &&
(mdata = pcre2_match_data_create_from_pattern(replace_quoted_re, NULL)))
{
while (pcre2_substitute(replace_quoted_re, (PCRE2_SPTR) * src, orig_len, 0,
PCRE2_SUBSTITUTE_GLOBAL, mdata, NULL,
replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR8*) output, &len) == PCRE2_ERROR_NOMEMORY)
{
char* tmp = (char*) realloc(output, (len = (size_t) (len * BUFFER_GROWTH_RATE + 1)));
if (tmp == NULL)
{
free(output);
output = NULL;
break;
}
output = tmp;
}
pcre2_match_data_free(mdata);
}
else
{
free(output);
output = NULL;
}
}
else if (output == NULL)
{
output = strdup(*src);
}
if (output)
{
*destsize = strlen(output);
*dest = output;
}
else
{
*dest = NULL;
}
return output;
}
/**
* Initialize the utils library
*
* This function initializes structures used in various functions.
* @return true on success, false on error
*/
bool utils_init()
{
bool rval = true;
PCRE2_SIZE erroffset;
int errcode;
ss_info_dassert(remove_comments_re == NULL, "utils_init called multiple times");
remove_comments_re = pcre2_compile(remove_comments_pattern, PCRE2_ZERO_TERMINATED, 0, &errcode,
&erroffset, NULL);
if (remove_comments_re == NULL)
{
rval = false;
}
ss_info_dassert(replace_quoted_re == NULL, "utils_init called multiple times");
replace_quoted_re = pcre2_compile(replace_quoted_pattern, PCRE2_ZERO_TERMINATED, 0, &errcode,
&erroffset, NULL);
if (replace_quoted_re == NULL)
{
rval = false;
}
ss_info_dassert(replace_values_re == NULL, "utils_init called multiple times");
replace_values_re = pcre2_compile(replace_values_pattern, PCRE2_ZERO_TERMINATED, 0, &errcode,
&erroffset, NULL);
if (replace_values_re == NULL)
{
rval = false;
}
return rval;
}
/**
* Close the utils library. This should be the last call to this library.
*/
void utils_end()
{
pcre2_code_free(remove_comments_re);
remove_comments_re = NULL;
pcre2_code_free(replace_quoted_re);
replace_quoted_re = NULL;
pcre2_code_free(replace_values_re);
replace_values_re = NULL;
}

View File

@ -14,7 +14,6 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <string.h>
#include <maxscale/hint.h>

View File

@ -13,7 +13,6 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>

View File

@ -16,7 +16,6 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <string.h>
#include <regex.h>

View File

@ -40,7 +40,7 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/utils.h>
#include <maxscale/log_manager.h>
#include <time.h>
#include <sys/time.h>

View File

@ -16,7 +16,6 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <string.h>
#include <pcre2.h>

View File

@ -46,7 +46,6 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <sys/time.h>
#include <regex.h>

View File

@ -37,7 +37,6 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <string.h>
#include <time.h>

View File

@ -45,7 +45,6 @@
#include <maxscale/filter.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <string.h>
#include <time.h>

View File

@ -35,7 +35,6 @@
#include <maxscale/thread.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/dcb.h>

View File

@ -23,7 +23,6 @@
#include <maxscale/thread.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/dcb.h>

View File

@ -43,7 +43,6 @@
#include <maxscale/thread.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/secrets.h>
#include <maxscale/dcb.h>

View File

@ -21,7 +21,6 @@
#include <thread.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <secrets.h>
#include <dcb.h>

View File

@ -12,7 +12,6 @@
*/
#include <maxscale/protocol/mysql.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/modutil.h>
#include <maxscale/utils.h>

View File

@ -46,7 +46,6 @@
* 31/05/2016 Martin Brampton Implement connection throttling
*/
#include <maxscale/gw_protocol.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/alloc.h>
#include <maxscale/log_manager.h>
#include <maxscale/protocol/mysql.h>

View File

@ -46,7 +46,6 @@
#include <maxscale/utils.h>
#include <maxscale/protocol/mysql.h>
#include <maxscale/alloc.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <netinet/tcp.h>
#include <maxscale/modutil.h>

View File

@ -30,7 +30,6 @@
#include <maxscale/atomic.h>
#include <maxscale/gw.h>
#include <maxscale/adminusers.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/modinfo.h>
#include "maxscaled.h"

View File

@ -31,7 +31,6 @@
#include <maxscale/gw.h>
#include <telnetd.h>
#include <maxscale/adminusers.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/modinfo.h>

View File

@ -39,7 +39,6 @@
#include <maxscale/housekeeper.h>
#include <time.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/protocol/mysql.h>

View File

@ -35,7 +35,6 @@
#include <maxscale/spinlock.h>
#include <maxscale/dcb.h>
#include <maxscale/spinlock.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/version.h>
#include "avrorouter.h"

View File

@ -40,7 +40,6 @@
#include <stdlib.h>
#include <glob.h>
#include <maxscale/alloc.h>
#include <maxscale/skygw_utils.h>
static const char *statefile_section = "avro-conversion";
static const char *ddl_list_name = "table-ddl.list";

View File

@ -27,7 +27,6 @@
#include <maxscale/log_manager.h>
#include <sys/stat.h>
#include <errno.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/debug.h>
#include <string.h>
#include <strings.h>

View File

@ -71,7 +71,6 @@
#include <maxscale/housekeeper.h>
#include <time.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/protocol/mysql.h>

View File

@ -43,7 +43,6 @@
#include <maxscale/dcb.h>
#include <maxscale/spinlock.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>

View File

@ -56,7 +56,6 @@
#include <maxscale/dcb.h>
#include <maxscale/spinlock.h>
#include <maxscale/gwdirs.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/alloc.h>

View File

@ -69,7 +69,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/rdtsc.h>

View File

@ -79,7 +79,6 @@
#include <maxscale/spinlock.h>
#include <maxscale/housekeeper.h>
#include <sys/stat.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/version.h>
#include <zlib.h>

View File

@ -36,7 +36,6 @@
#include <maxscale/spinlock.h>
#include <maxscale/housekeeper.h>
#include <time.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/gwdirs.h>
#include <maxscale/alloc.h>

View File

@ -38,7 +38,6 @@
#include <maxscale/alloc.h>
#include <maxscale/poll.h>
#include <debugcli.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>

View File

@ -37,7 +37,6 @@
#include <maxscale/alloc.h>
#include <maxscale/poll.h>
#include <debugcli.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>

View File

@ -72,7 +72,6 @@
#include <maxscale/housekeeper.h>
#include <maxscale/listmanager.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <sys/syslog.h>

View File

@ -44,7 +44,6 @@
#include <maxscale/maxscale.h>
#include <maxscale/poll.h>
#include "maxinfo.h"
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/resultset.h>
#include <maxscale/version.h>

View File

@ -37,7 +37,6 @@
#include <maxscale/dcb.h>
#include <maxscale/poll.h>
#include "maxinfo.h"
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>

View File

@ -41,7 +41,6 @@
#include <maxscale/maxscale.h>
#include <maxscale/poll.h>
#include "maxinfo.h"
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/resultset.h>
#include <maxscale/config.h>

View File

@ -40,7 +40,6 @@
#include <maxscale/dcb.h>
#include <maxscale/poll.h>
#include "maxinfo.h"
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
static MAXINFO_TREE *make_tree_node(MAXINFO_OPERATOR, char *, MAXINFO_TREE *, MAXINFO_TREE *);

View File

@ -84,7 +84,6 @@
#include <maxscale/spinlock.h>
#include <maxscale/modinfo.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/protocol/mysql.h>

View File

@ -20,7 +20,6 @@
#include "readwritesplit.h"
#include "rwsplit_internal.h"
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/query_classifier.h>
#include <maxscale/dcb.h>

View File

@ -22,7 +22,6 @@
#include "rwsplit_internal.h"
#include <mysql.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/query_classifier.h>
#include <maxscale/dcb.h>

View File

@ -21,7 +21,6 @@
#include "sharding_common.h"
#include <maxscale/secrets.h>
#include <mysql.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/query_classifier.h>
#include <maxscale/dcb.h>