From 854c4a1ed39d465da7dbd13ca6e4b429ad105d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 28 Jul 2017 14:14:47 +0300 Subject: [PATCH] Add support for non-glibc systems MaxScale can now be built on systems that use an alternative libc implementation e.g. musl. --- client/maxadmin.c | 51 +++---------------- cmake/CheckPlatform.cmake | 20 ++++++-- include/maxscale/config.h | 7 +-- include/maxscale/utils.h | 1 + .../qc_sqlite/sqlite-src-3110100/configure | 2 +- server/core/CMakeLists.txt | 8 ++- server/core/adminusers.cc | 30 ++++++++--- server/core/config.cc | 6 +-- server/core/gateway.cc | 12 +++++ server/core/log_manager.cc | 11 ++-- server/core/maxkeys.c | 6 +++ server/core/maxpasswd.c | 6 +++ server/core/messagequeue.cc | 1 - server/core/test/testlogthrottling.cc | 3 +- server/core/utils.cc | 6 --- .../modules/routing/binlogrouter/blr_master.c | 4 +- .../routing/binlogrouter/maxbinlogcheck.c | 7 ++- 17 files changed, 104 insertions(+), 77 deletions(-) diff --git a/client/maxadmin.c b/client/maxadmin.c index f6ad531b8..fe25af4ab 100644 --- a/client/maxadmin.c +++ b/client/maxadmin.c @@ -39,19 +39,12 @@ #include #include +#include #ifdef HISTORY #include #endif -#include -/* - * We need a common.h file that is included by every component. - */ -#if !defined(STRERROR_BUFLEN) -#define STRERROR_BUFLEN 512 -#endif - #define MAX_PASSWORD_LEN 80 static int connectUsingUnixSocket(const char *socket); @@ -441,27 +434,22 @@ connectUsingUnixSocket(const char *socket_path) } else { - char errbuf[STRERROR_BUFLEN]; - fprintf(stderr, "Could not set SO_PASSCRED: %s\n", - strerror_r(errno, errbuf, sizeof(errbuf))); + fprintf(stderr, "Could not set SO_PASSCRED: %s\n", strerror(errno)); close(so); so = -1; } } else { - char errbuf[STRERROR_BUFLEN]; fprintf(stderr, "Unable to connect to MaxScale at %s: %s\n", - socket_path, strerror_r(errno, errbuf, sizeof(errbuf))); + socket_path, strerror(errno)); close(so); so = -1; } } else { - char errbuf[STRERROR_BUFLEN]; - fprintf(stderr, "Unable to create socket: %s\n", - strerror_r(errno, errbuf, sizeof(errbuf))); + fprintf(stderr, "Unable to create socket: %s\n", strerror(errno)); } return so; @@ -505,18 +493,15 @@ connectUsingInetSocket(const char *hostname, const char *port, } else { - char errbuf[STRERROR_BUFLEN]; fprintf(stderr, "Unable to connect to MaxScale at %s, %s: %s\n", - hostname, port, strerror_r(errno, errbuf, sizeof(errbuf))); + hostname, port, strerror(errno)); close(so); so = -1; } } else { - char errbuf[STRERROR_BUFLEN]; - fprintf(stderr, "Unable to create socket: %s\n", - strerror_r(errno, errbuf, sizeof(errbuf))); + fprintf(stderr, "Unable to create socket: %s\n", strerror(errno)); } return so; @@ -532,7 +517,7 @@ connectUsingInetSocket(const char *hostname, const char *port, static int setipaddress(struct in_addr *a, const char *p) { -#ifdef __USE_POSIX + struct addrinfo *ai = NULL, hint; int rc; struct sockaddr_in * res_addr; @@ -557,28 +542,6 @@ setipaddress(struct in_addr *a, const char *p) return 1; } -#else - struct hostent *h; - - spinlock_acquire(&tmplock); - h = gethostbyname(p); - spinlock_release(&tmplock); - - if (h == NULL) - { - if ((a->s_addr = inet_addr(p)) == -1) - { - return 0; - } - } - else - { - /* take the first one */ - memcpy(a, h->h_addr, h->h_length); - - return 1; - } -#endif return 0; } diff --git a/cmake/CheckPlatform.cmake b/cmake/CheckPlatform.cmake index 3cddc8d05..755602b69 100644 --- a/cmake/CheckPlatform.cmake +++ b/cmake/CheckPlatform.cmake @@ -3,6 +3,7 @@ include(CheckFunctionExists) include(CheckLibraryExists) include(CheckIncludeFiles) +include(CheckCXXSourceCompiles) check_include_files(arpa/inet.h HAVE_ARPA_INET) check_include_files(crypt.h HAVE_CRYPT) @@ -69,11 +70,6 @@ if(NOT HAVE_LIBM) message(FATAL_ERROR "Could not find libm") endif() -find_library(HAVE_LIBDL NAMES dl) -if(NOT HAVE_LIBDL) - message(FATAL_ERROR "Could not find libdl") -endif() - find_library(HAVE_LIBRT NAMES rt) if(NOT HAVE_LIBRT) message(FATAL_ERROR "Could not find librt") @@ -83,3 +79,17 @@ find_library(HAVE_LIBPTHREAD NAMES pthread) if(NOT HAVE_LIBPTHREAD) message(FATAL_ERROR "Could not find libpthread") endif() + +# The XSI version of strerror_r return an int and the GNU version a char* +check_cxx_source_compiles(" + #define _GNU_SOURCE 1 + #include \n + int main(){\n + char errbuf[200];\n + return strerror_r(13, errbuf, sizeof(errbuf)) == errbuf;\n + }\n" + HAVE_GLIBC) + +if(HAVE_GLIBC) + add_definitions(-DHAVE_GLIBC=1) +endif() diff --git a/include/maxscale/config.h b/include/maxscale/config.h index 26a12f79f..ba421ecb1 100644 --- a/include/maxscale/config.h +++ b/include/maxscale/config.h @@ -33,7 +33,8 @@ MXS_BEGIN_DECLS #define DEFAULT_ADMIN_HTTP_PORT 8989 #define DEFAULT_ADMIN_HOST "::" -#define _RELEASE_STR_LENGTH 256 /**< release len */ +#define RELEASE_STR_LENGTH 256 +#define SYSNAME_LEN 256 #define MAX_ADMIN_USER_LEN 1024 #define MAX_ADMIN_PW_LEN 1024 #define MAX_ADMIN_HOST_LEN 1024 @@ -189,8 +190,8 @@ typedef struct bool config_check; /**< Only check config */ int n_threads; /**< Number of polling threads */ char *version_string; /**< The version string of embedded db library */ - char release_string[_RELEASE_STR_LENGTH]; /**< The release name string of the system */ - char sysname[_UTSNAME_SYSNAME_LENGTH]; /**< The OS name of the system */ + char release_string[RELEASE_STR_LENGTH]; /**< The release name string of the system */ + char sysname[SYSNAME_LEN]; /**< The OS name of the system */ uint8_t mac_sha1[SHA_DIGEST_LENGTH]; /**< The SHA1 digest of an interface MAC address */ unsigned long id; /**< MaxScale ID */ unsigned int n_nbpoll; /**< Tune number of non-blocking polls */ diff --git a/include/maxscale/utils.h b/include/maxscale/utils.h index 2e32ae6e1..730a84636 100644 --- a/include/maxscale/utils.h +++ b/include/maxscale/utils.h @@ -21,6 +21,7 @@ #include #include #include +#include MXS_BEGIN_DECLS diff --git a/query_classifier/qc_sqlite/sqlite-src-3110100/configure b/query_classifier/qc_sqlite/sqlite-src-3110100/configure index 32cce1429..224f6d368 100755 --- a/query_classifier/qc_sqlite/sqlite-src-3110100/configure +++ b/query_classifier/qc_sqlite/sqlite-src-3110100/configure @@ -11506,7 +11506,7 @@ else fi if test "${enable_maxscale}" = "yes" ; then - OPT_FEATURE_FLAGS+=" -DMAXSCALE -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT -DSQLITE_OMIT_ATTACH -DSQLITE_OMIT_REINDEX -DSQLITE_OMIT_AUTOVACUUM -DSQLITE_OMIT_PRAGMA" + OPT_FEATURE_FLAGS="$OPT_FEATURE_FLAGS -DMAXSCALE -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT -DSQLITE_OMIT_ATTACH -DSQLITE_OMIT_REINDEX -DSQLITE_OMIT_AUTOVACUUM -DSQLITE_OMIT_PRAGMA" fi ######### diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index 1d80cddbb..3c27a7461 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -69,7 +69,6 @@ target_link_libraries(maxscale-common ssl pthread crypt - dl crypto inih z @@ -81,6 +80,13 @@ target_link_libraries(maxscale-common ${MICROHTTPD_LIBRARIES} ) +find_library(HAVE_LIBDL NAMES dl) +if (HAVE_LIBDL) + # libdl just exposes libc functionality on most systems. This means that if + # we can't find it, it's likely that libc already exposes the symbols. + target_link_libraries(maxscale-common dl) +endif() + add_dependencies(maxscale-common pcre2 connector-c) set_target_properties(maxscale-common PROPERTIES VERSION "1.0.0") install_module(maxscale-common core) diff --git a/server/core/adminusers.cc b/server/core/adminusers.cc index 9b6efe9ea..2fc09a03f 100644 --- a/server/core/adminusers.cc +++ b/server/core/adminusers.cc @@ -513,6 +513,24 @@ bool admin_linux_account_enabled(const char *uname) return rv; } +#define MXS_CRYPT_SIZE 60 + +void mxs_crypt(const char* password, const char* salt, char* output) +{ +#if HAVE_GLIBC + thread_local struct crypt_data cdata; + cdata.initialized = 0; + char* pw = crypt_r(password, salt, &cdata); + snprintf(output, MXS_CRYPT_SIZE, "%s", pw); +#else + static SPINLOCK mxs_crypt_lock = SPINLOCK_INIT; + spinlock_acquire(&mxs_crypt_lock); + char* pw = crypt(password, salt); + snprintf(output, MXS_CRYPT_SIZE, "%s", pw); + spinlock_release(&mxs_crypt_lock); +#endif +} + /** * Add insecure remote (network) user. * @@ -523,9 +541,8 @@ bool admin_linux_account_enabled(const char *uname) */ const char *admin_add_inet_user(const char *uname, const char* password) { - struct crypt_data cdata; - cdata.initialized = 0; - char *cpassword = crypt_r(password, ADMIN_SALT, &cdata); + char cpassword[MXS_CRYPT_SIZE]; + mxs_crypt(password, ADMIN_SALT, cpassword); return admin_add_user(&inet_users, INET_USERS_FILE_NAME, uname, cpassword); } @@ -581,9 +598,10 @@ admin_verify_inet_user(const char *username, const char *password) if (pw) { - struct crypt_data cdata; - cdata.initialized = 0; - if (strcmp(pw, crypt_r(password, ADMIN_SALT, &cdata)) == 0) + char cpassword[MXS_CRYPT_SIZE]; + mxs_crypt(password, ADMIN_SALT, cpassword); + + if (strcmp(pw, cpassword) == 0) { rv = true; } diff --git a/server/core/config.cc b/server/core/config.cc index 0ec262cfb..1b0f89d2d 100644 --- a/server/core/config.cc +++ b/server/core/config.cc @@ -2251,7 +2251,7 @@ config_get_release_string(char* release) }; bool have_distribution; - char distribution[_RELEASE_STR_LENGTH] = ""; + char distribution[RELEASE_STR_LENGTH] = ""; int fd; have_distribution = false; @@ -2328,7 +2328,7 @@ config_get_release_string(char* release) +5 and -8 below cut the file name part out of the full pathname that corresponds to the mask as above. */ - new_to = strncpy(distribution, found.gl_pathv[0] + 5, _RELEASE_STR_LENGTH - 1); + new_to = strncpy(distribution, found.gl_pathv[0] + 5, RELEASE_STR_LENGTH - 1); new_to += 8; *new_to++ = ':'; *new_to++ = ' '; @@ -2348,7 +2348,7 @@ config_get_release_string(char* release) } have_distribution = true; - strncpy(release, new_to, _RELEASE_STR_LENGTH); + strncpy(release, new_to, RELEASE_STR_LENGTH); } } } diff --git a/server/core/gateway.cc b/server/core/gateway.cc index 63f01568a..362d78b1f 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -17,7 +17,9 @@ #include +#ifdef HAVE_GLIBC #include +#endif #include #include #include @@ -100,6 +102,9 @@ static bool daemon_mode = true; static const char* maxscale_commit = MAXSCALE_COMMIT; const char *progname = NULL; + +#ifdef HAVE_GLIBC +// getopt_long is a GNU extension static struct option long_options[] = { {"config-check", no_argument, 0, 'c'}, @@ -128,6 +133,7 @@ static struct option long_options[] = {"debug", required_argument, 0, 'g'}, {0, 0, 0, 0} }; +#endif static bool syslog_configured = false; static bool maxlog_configured = false; @@ -419,6 +425,7 @@ sigfatal_handler(int i) "Release string: %s", maxscale_commit, cnf->sysname, cnf->release_string); +#ifdef HAVE_GLIBC { void *addrs[128]; int count = backtrace(addrs, 128); @@ -438,6 +445,7 @@ sigfatal_handler(int i) backtrace_symbols_fd(addrs, count, fileno(stderr)); } } +#endif mxs_log_flush_sync(); @@ -1338,8 +1346,12 @@ int main(int argc, char **argv) } } +#ifdef HAVE_GLIBC while ((opt = getopt_long(argc, argv, "dcf:g:l:vVs:S:?L:D:C:B:U:A:P:G:N:E:F:M:H:", long_options, &option_index)) != -1) +#else + while ((opt = getopt(argc, argv, "dcf:g:l:vVs:S:?L:D:C:B:U:A:P:G:N:E:F:M:H:")) != -1) +#endif { bool succp = true; diff --git a/server/core/log_manager.cc b/server/core/log_manager.cc index 4e0ca9fd2..e5169f74c 100644 --- a/server/core/log_manager.cc +++ b/server/core/log_manager.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -705,7 +706,7 @@ void mxs_log_finish(void) while (lm != NULL && lm->lm_nlinks != 0) { release_lock(&lmlock); - pthread_yield(); + sched_yield(); acquire_lock(&lmlock); } @@ -1354,7 +1355,7 @@ static bool logmanager_register(bool writep) while (lm != NULL && !lm->lm_enabled) { release_lock(&lmlock); - pthread_yield(); + sched_yield(); acquire_lock(&lmlock); } @@ -3013,8 +3014,12 @@ int mxs_log_message(int priority, const char* mxs_strerror(int error) { static thread_local char errbuf[MXS_STRERROR_BUFLEN]; - +#ifdef HAVE_GLIBC return strerror_r(error, errbuf, sizeof(errbuf)); +#else + strerror_r(error, errbuf, sizeof(errbuf)); + return errbuf; +#endif } json_t* get_log_priorities() diff --git a/server/core/maxkeys.c b/server/core/maxkeys.c index ad928099b..7a8c92fae 100644 --- a/server/core/maxkeys.c +++ b/server/core/maxkeys.c @@ -31,6 +31,7 @@ #include #include +#ifdef HAVE_GLIBC struct option options[] = { { @@ -41,6 +42,7 @@ struct option options[] = }, { NULL, 0, NULL, 0 } }; +#endif void print_usage(const char* executable, const char* directory) { @@ -67,7 +69,11 @@ int main(int argc, char **argv) const char* directory = get_datadir(); int c; +#ifdef HAVE_GLIBC while ((c = getopt_long(argc, argv, "h", options, NULL)) != -1) +#else + while ((c = getopt(argc, argv, "h")) != -1) +#endif { switch (c) { diff --git a/server/core/maxpasswd.c b/server/core/maxpasswd.c index 652925157..460d410aa 100644 --- a/server/core/maxpasswd.c +++ b/server/core/maxpasswd.c @@ -35,6 +35,7 @@ #include "maxscale/secrets.h" +#ifdef HAVE_GLIBC struct option options[] = { { @@ -45,6 +46,7 @@ struct option options[] = }, { NULL, 0, NULL, 0 } }; +#endif void print_usage(const char* executable, const char* directory) { @@ -107,7 +109,11 @@ int main(int argc, char **argv) const char* path = get_datadir(); int c; +#ifdef HAVE_GLIBC while ((c = getopt_long(argc, argv, "h", options, NULL)) != -1) +#else + while ((c = getopt(argc, argv, "h")) != -1) +#endif { switch (c) { diff --git a/server/core/messagequeue.cc b/server/core/messagequeue.cc index 1da2b142d..7ac0d5b28 100644 --- a/server/core/messagequeue.cc +++ b/server/core/messagequeue.cc @@ -12,7 +12,6 @@ */ #include "maxscale/messagequeue.hh" -#include #include #include #include diff --git a/server/core/test/testlogthrottling.cc b/server/core/test/testlogthrottling.cc index 1d6faf6ee..cb399c834 100644 --- a/server/core/test/testlogthrottling.cc +++ b/server/core/test/testlogthrottling.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,7 @@ void log_messages(uint32_t id, size_t n_generate, int priority) { MXS_LOG_MESSAGE(priority, "[%u] Message %lu.", id, i); - pthread_yield(); + sched_yield(); } } diff --git a/server/core/utils.cc b/server/core/utils.cc index e80d2b82a..5a4381746 100644 --- a/server/core/utils.cc +++ b/server/core/utils.cc @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -989,7 +988,6 @@ static void set_port(struct sockaddr_storage *addr, uint16_t port) int open_network_socket(enum mxs_socket_type type, struct sockaddr_storage *addr, const char *host, uint16_t port) { ss_dassert(type == MXS_SOCKET_NETWORK || type == MXS_SOCKET_LISTENER); -#ifdef __USE_POSIX struct addrinfo *ai = NULL, hint = {}; int so, rc; hint.ai_socktype = SOCK_STREAM; @@ -1032,10 +1030,6 @@ int open_network_socket(enum mxs_socket_type type, struct sockaddr_storage *addr freeaddrinfo(ai); } -#else -#error Only the POSIX networking interface is supported -#endif - return so; } diff --git a/server/modules/routing/binlogrouter/blr_master.c b/server/modules/routing/binlogrouter/blr_master.c index 6b5579f28..196934deb 100644 --- a/server/modules/routing/binlogrouter/blr_master.c +++ b/server/modules/routing/binlogrouter/blr_master.c @@ -2020,9 +2020,9 @@ bool blr_send_event(blr_thread_role_t role, slave->serverid, binlog_name, binlog_pos, - thread_self(), + (uint64_t)thread_self(), ROLETOSTR(role), - slave->lsi_sender_tid, + (uint64_t)slave->lsi_sender_tid, ROLETOSTR(slave->lsi_sender_role), gwbuf_length(slave->dcb->writeq), slave->dcb, slave->router->stats.n_binlogs); diff --git a/server/modules/routing/binlogrouter/maxbinlogcheck.c b/server/modules/routing/binlogrouter/maxbinlogcheck.c index e1ebe6ff8..328eb6e22 100644 --- a/server/modules/routing/binlogrouter/maxbinlogcheck.c +++ b/server/modules/routing/binlogrouter/maxbinlogcheck.c @@ -56,6 +56,7 @@ static void printVersion(const char *progname); static void printUsage(const char *progname); static int set_encryption_options(ROUTER_INSTANCE *inst, char *key_file, char *aes_algo); +#ifdef HAVE_GLIBC static struct option long_options[] = { {"debug", no_argument, 0, 'd'}, @@ -70,7 +71,7 @@ static struct option long_options[] = {"help", no_argument, 0, '?'}, {0, 0, 0, 0} }; - +#endif char *binlog_check_version = "2.2.1"; int @@ -90,7 +91,11 @@ int main(int argc, char **argv) char c; BINLOG_FILE_FIX binlog_file = {0, false, false}; +#ifdef HAVE_GLIBC while ((c = getopt_long(argc, argv, "dVfMHK:A:R:T:?", long_options, &option_index)) >= 0) +#else + while ((c = getopt(argc, argv, "dVfMHK:A:R:T:?")) >= 0) +#endif { switch (c) {