You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
417 lines
13 KiB
C
417 lines
13 KiB
C
/*
|
|
* mysql.c
|
|
*
|
|
* Copyright (C) 2014 bwq518, Hyzoom
|
|
* Fixes/updates (C) 2018 - 2022 pedro
|
|
*
|
|
*/
|
|
|
|
|
|
#include "rc.h"
|
|
|
|
#define mysql_etc_dir "/etc/mysql"
|
|
#define mysql_conf_link "/etc/my.cnf"
|
|
#define mysql_conf mysql_etc_dir"/my.cnf"
|
|
#define mysql_start_script mysql_etc_dir"/start_mysql.sh"
|
|
#define mysql_stop_script mysql_etc_dir"/stop_mysql.sh"
|
|
#define mysql_passwd mysql_etc_dir"/setpasswd.sql"
|
|
#define mysql_anyhost mysql_etc_dir"/setanyhost.sql"
|
|
#define mysql_child_pid mysql_etc_dir"/child.pid"
|
|
#define mysql_pid "/var/run/mysqld.pid"
|
|
#define mysql_log "/var/log/mysql.log"
|
|
#define mysql_dflt_dir "/tmp/mysql"
|
|
|
|
/* needed by logmsg() */
|
|
#define LOGMSG_DISABLE DISABLE_SYSLOG_OSM
|
|
#define LOGMSG_NVDEBUG "mysql_debug"
|
|
|
|
|
|
static void setup_mysql_watchdog(void)
|
|
{
|
|
FILE *fp;
|
|
char buffer[64], buffer2[64];
|
|
int nvi;
|
|
|
|
if ((nvi = nvram_get_int("mysql_check_time")) > 0) {
|
|
memset(buffer, 0, sizeof(buffer));
|
|
snprintf(buffer, sizeof(buffer), mysql_etc_dir"/watchdog.sh");
|
|
|
|
if ((fp = fopen(buffer, "w"))) {
|
|
fprintf(fp, "#!/bin/sh\n"
|
|
"[ -z \"$(pidof mysqld)\" -a \"$(nvram get g_upgrade)\" != \"1\" -a \"$(nvram get g_reboot)\" != \"1\" ] && {\n"
|
|
" logger -t mysql-watchdog mysqld stopped? Starting...\n"
|
|
" service mysql restart\n"
|
|
"}\n");
|
|
fclose(fp);
|
|
chmod(buffer, (S_IRUSR | S_IWUSR | S_IXUSR));
|
|
|
|
memset(buffer2, 0, sizeof(buffer2));
|
|
snprintf(buffer2, sizeof(buffer2), "*/%d * * * * %s", nvi, buffer);
|
|
eval("cru", "a", "CheckMySQL", buffer2);
|
|
}
|
|
}
|
|
}
|
|
|
|
void start_mysql(int force)
|
|
{
|
|
FILE *fp;
|
|
char pbi[128];
|
|
char ppr[64];
|
|
char pdatadir[256], ptmpdir[256];
|
|
char full_datadir[256], full_tmpdir[256], basedir[256];
|
|
char tmp1[256], tmp2[256];
|
|
int n;
|
|
pid_t pidof_child = 0;
|
|
unsigned int new_install = 0;
|
|
char *nginx_docroot = nvram_safe_get("nginx_docroot");
|
|
unsigned int anyhost = nvram_get_int("mysql_allow_anyhost");
|
|
|
|
|
|
/* only if enabled or forced */
|
|
if (!nvram_get_int("mysql_enable") && force == 0)
|
|
return;
|
|
|
|
if (serialize_restart("mysqld", 1))
|
|
return;
|
|
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
if (f_read_string(mysql_child_pid, tmp1, sizeof(tmp1)) > 0 && atoi(tmp1) > 0 && ppid(atoi(tmp1)) > 0) { /* fork is still up */
|
|
logmsg(LOG_WARNING, "%s: another process (PID: %s) still up, aborting ...", __FUNCTION__, tmp1);
|
|
return;
|
|
}
|
|
|
|
logmsg(LOG_INFO, "starting mysqld ...");
|
|
|
|
if (nvram_match("mysql_binary", "internal"))
|
|
strlcpy(pbi, "/usr/bin", sizeof(pbi));
|
|
else if (nvram_match("mysql_binary", "optware"))
|
|
strlcpy(pbi, "/opt/bin", sizeof(pbi));
|
|
else
|
|
strlcpy(pbi, nvram_safe_get("mysql_binary_custom"), sizeof(pbi));
|
|
|
|
if (pbi[strlen(pbi) - 1] == '/')
|
|
pbi[strlen(pbi) - 1] = '\0';
|
|
|
|
splitpath(pbi, basedir, tmp1);
|
|
|
|
/* generate download saved path based on USB partition (mysql_dlroot) and directory name (mysql_datadir) */
|
|
if (nvram_get_int("mysql_usb_enable")) {
|
|
tmp1[0] = 0;
|
|
tmp2[0] = 0;
|
|
strlcpy(tmp1, nvram_safe_get("mysql_dlroot"), sizeof(tmp1));
|
|
trimstr(tmp1);
|
|
if (tmp1[0] != '/') {
|
|
memset(tmp2, 0, sizeof(tmp2));
|
|
snprintf(tmp2, sizeof(tmp2), "/%s", tmp1);
|
|
strlcpy(tmp1, tmp2, sizeof(tmp1));
|
|
}
|
|
strlcpy(ppr, tmp1, sizeof(ppr));
|
|
if (ppr[strlen(ppr) - 1] == '/')
|
|
ppr[strlen(ppr) - 1] = 0;
|
|
|
|
if (strlen(ppr) == 0) {
|
|
logmsg(LOG_ERR, "No mounted USB partition found. You need to mount the USB drive first");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
strlcpy(ppr, mysql_dflt_dir, sizeof(ppr));
|
|
|
|
strlcpy(pdatadir, nvram_safe_get("mysql_datadir"), sizeof(pdatadir));
|
|
trimstr(pdatadir);
|
|
if (pdatadir[strlen(pdatadir) - 1] == '/')
|
|
pdatadir[strlen(pdatadir) - 1] = 0;
|
|
|
|
if (strlen(pdatadir) == 0) {
|
|
strlcpy(pdatadir, "data", sizeof(pdatadir));
|
|
nvram_set("mysql_dir", "data");
|
|
}
|
|
memset(full_datadir, 0, sizeof(full_datadir));
|
|
if (pdatadir[0] == '/')
|
|
snprintf(full_datadir, sizeof(full_datadir), "%s%s", ppr, pdatadir);
|
|
else
|
|
snprintf(full_datadir, sizeof(full_datadir), "%s/%s", ppr, pdatadir);
|
|
|
|
strlcpy(ptmpdir, nvram_safe_get("mysql_tmpdir"), sizeof(ptmpdir));
|
|
trimstr(ptmpdir);
|
|
if (ptmpdir[strlen(ptmpdir) - 1] == '/')
|
|
ptmpdir[strlen(ptmpdir) - 1] = 0;
|
|
|
|
if (strlen(ptmpdir) == 0) {
|
|
strlcpy (ptmpdir, "tmp", sizeof(ptmpdir));
|
|
nvram_set("mysql_tmpdir", "tmp");
|
|
}
|
|
memset(full_tmpdir, 0, sizeof(full_tmpdir));
|
|
if (ptmpdir[0] == '/')
|
|
snprintf(full_tmpdir, sizeof(full_tmpdir), "%s%s", ppr, ptmpdir);
|
|
else
|
|
snprintf(full_tmpdir, sizeof(full_tmpdir), "%s/%s", ppr, ptmpdir);
|
|
|
|
mkdir_if_none(mysql_etc_dir);
|
|
|
|
/* config file */
|
|
if (!(fp = fopen(mysql_conf, "w"))) {
|
|
logerr(__FUNCTION__, __LINE__, mysql_conf);
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "[client]\n"
|
|
"port = %s\n"
|
|
"socket = /var/run/mysqld.sock\n\n"
|
|
"[mysqld]\n"
|
|
"user = root\n"
|
|
"socket = /var/run/mysqld.sock\n"
|
|
"port = %s\n"
|
|
"basedir = %s\n\n"
|
|
"datadir = %s\n"
|
|
"tmpdir = %s\n\n"
|
|
"skip-external-locking\n",
|
|
nvram_safe_get("mysql_port"),
|
|
nvram_safe_get("mysql_port"),
|
|
basedir,
|
|
full_datadir,
|
|
full_tmpdir);
|
|
|
|
if (nvram_get_int("mysql_allow_anyhost"))
|
|
fprintf(fp, "bind-address = 0.0.0.0\n");
|
|
else
|
|
fprintf(fp, "bind-address = 127.0.0.1\n");
|
|
|
|
/* disable innodb engine */
|
|
fprintf(fp, "default-storage-engine=MYISAM\n"
|
|
"innodb=OFF\n");
|
|
|
|
fprintf(fp, "key_buffer_size = %sM\n"
|
|
"max_allowed_packet = %sM\n"
|
|
"thread_stack = %sK\n"
|
|
"thread_cache_size = %s\n\n"
|
|
"table_open_cache = %s\n"
|
|
"sort_buffer_size = %sK\n"
|
|
"read_buffer_size = %sK\n"
|
|
"read_rnd_buffer_size = %sK\n"
|
|
"query_cache_size = %sM\n"
|
|
"max_connections = %s\n\n"
|
|
"#The following items are from mysql_server_custom\n"
|
|
"%s\n"
|
|
"#end of mysql_server_custom\n\n"
|
|
"[mysqldump]\n"
|
|
"quick\nquote-names\n"
|
|
"max_allowed_packet = 16M\n"
|
|
"[mysql]\n\n"
|
|
"[isamchk]\n"
|
|
"key_buffer_size = 8M\n"
|
|
"sort_buffer_size = 8M\n\n",
|
|
nvram_safe_get("mysql_key_buffer"),
|
|
nvram_safe_get("mysql_max_allowed_packet"),
|
|
nvram_safe_get("mysql_thread_stack"),
|
|
nvram_safe_get("mysql_thread_cache_size"),
|
|
nvram_safe_get("mysql_table_open_cache"),
|
|
nvram_safe_get("mysql_sort_buffer_size"),
|
|
nvram_safe_get("mysql_read_buffer_size"),
|
|
nvram_safe_get("mysql_read_rnd_buffer_size"),
|
|
nvram_safe_get("mysql_query_cache_size"),
|
|
nvram_safe_get("mysql_max_connections"),
|
|
nvram_safe_get("mysql_server_custom"));
|
|
|
|
fclose(fp);
|
|
|
|
chmod(mysql_conf, 0644);
|
|
|
|
unlink(mysql_conf_link);
|
|
symlink(mysql_conf, mysql_conf_link);
|
|
|
|
/* fork new process */
|
|
if (fork() != 0) /* foreground process */
|
|
return;
|
|
|
|
pidof_child = getpid();
|
|
|
|
/* write child pid to a file */
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%d", pidof_child);
|
|
f_write_string(mysql_child_pid, tmp1, 0, 0);
|
|
|
|
/* wait a given time for partition to be mounted, etc */
|
|
n = atoi(nvram_safe_get("mysql_sleep"));
|
|
if (n > 0)
|
|
sleep(n);
|
|
|
|
/* clean mysql_log */
|
|
system("/bin/rm -f "mysql_log);
|
|
f_write(mysql_log, NULL, 0, 0, 0644);
|
|
|
|
/* check for datadir */
|
|
if (!d_exists(full_datadir)) {
|
|
logmsg(LOG_INFO, "datadir in %s doesn't exist, creating ...", ppr);
|
|
if (mkdir(full_datadir, 0755) == 0)
|
|
logmsg(LOG_INFO, "created successfully");
|
|
else {
|
|
logmsg(LOG_ERR, "create failed, aborting ...");
|
|
goto END;
|
|
}
|
|
}
|
|
|
|
/* check for tmpdir */
|
|
if (!d_exists(full_tmpdir)) {
|
|
logmsg(LOG_INFO, "tmpdir in %s doesn't exist, creating ...", ppr);
|
|
if (mkdir(full_tmpdir, 0755) == 0)
|
|
logmsg(LOG_INFO, "created successfully");
|
|
else {
|
|
logmsg(LOG_ERR, "create failed, aborting ...");
|
|
goto END;
|
|
}
|
|
}
|
|
|
|
/* check for tables_priv.MYD */
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysql/tables_priv.MYD", full_datadir);
|
|
if (!f_exists(tmp1)) {
|
|
new_install = 1;
|
|
logmsg(LOG_INFO, "tables_priv.MYD not found - it's a new MySQL installation");
|
|
f_write_string(mysql_log, "=========Found NO tables_priv.MYD====================", FW_APPEND | FW_NEWLINE, 0);
|
|
f_write_string(mysql_log, "This is new installed MySQL.", FW_APPEND | FW_NEWLINE, 0);
|
|
}
|
|
|
|
/* initialize DB? */
|
|
if (nvram_get_int("mysql_init_priv") || new_install == 1) {
|
|
logmsg(LOG_INFO, "initializing privileges table ...");
|
|
f_write_string(mysql_log, "=========mysql_install_db====================", FW_APPEND | FW_NEWLINE, 0);
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysql_install_db --user=root --force >> %s 2>&1", pbi, mysql_log);
|
|
system(tmp1);
|
|
|
|
logmsg(LOG_DEBUG, "*** %s: privileges table successfully initialized", __FUNCTION__);
|
|
nvram_set("mysql_init_priv", "0");
|
|
nvram_commit();
|
|
}
|
|
|
|
/* initialize root password? */
|
|
if (nvram_get_int("mysql_init_rootpass") || new_install == 1) {
|
|
logmsg(LOG_INFO, "(re-)initializing root password ...");
|
|
f_write_string(mysql_log, "=========mysqld skip-grant-tables==================", FW_APPEND | FW_NEWLINE, 0);
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysqld --skip-grant-tables --skip-networking --pid-file=%s >> %s 2>&1 &", pbi, mysql_pid, mysql_log);
|
|
system(tmp1);
|
|
sleep(2);
|
|
|
|
if (f_exists(mysql_passwd))
|
|
unlink(mysql_passwd);
|
|
|
|
f_write_string(mysql_passwd, "use mysql;", FW_CREATE | FW_NEWLINE, 0644);
|
|
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "update user set password=password('%s') where user='root';", nvram_safe_get("mysql_passwd"));
|
|
f_write_string(mysql_passwd, tmp1, FW_APPEND | FW_NEWLINE, 0);
|
|
|
|
f_write_string(mysql_passwd, "flush privileges;", FW_APPEND | FW_NEWLINE, 0);
|
|
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "=========mysql < %s====================", mysql_passwd);
|
|
f_write_string(mysql_log, tmp1, FW_APPEND | FW_NEWLINE, 0);
|
|
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysql < %s >> %s", pbi, mysql_passwd, mysql_log);
|
|
system(tmp1);
|
|
|
|
f_write_string(mysql_log, "=========mysqldadmin shutdown====================", FW_APPEND | FW_NEWLINE, 0);
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysqladmin -uroot -p\"%s\" --shutdown_timeout=3 shutdown >> %s 2>&1", pbi, nvram_safe_get("mysql_passwd"), mysql_log);
|
|
system(tmp1);
|
|
|
|
killall_tk_period_wait("mysqld", 50);
|
|
sleep(1);
|
|
system("/bin/rm -f "mysql_pid" "mysql_passwd);
|
|
|
|
logmsg(LOG_DEBUG, "*** %s: root password successfully (re-)initialized", __FUNCTION__);
|
|
nvram_set("mysql_init_rootpass", "0");
|
|
nvram_commit();
|
|
}
|
|
|
|
f_write_string(mysql_log, "=========mysqld startup====================", FW_APPEND | FW_NEWLINE, 0);
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysqld --pid-file=%s >> %s 2>&1 &", pbi, mysql_pid, mysql_log);
|
|
system(tmp1);
|
|
|
|
if (anyhost == 1) {
|
|
sleep(3);
|
|
if (f_exists(mysql_anyhost))
|
|
unlink(mysql_anyhost);
|
|
|
|
f_write_string(mysql_anyhost, "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%%' WITH GRANT OPTION;", FW_CREATE | FW_NEWLINE, 0644);
|
|
f_write_string(mysql_anyhost, "flush privileges;", FW_APPEND | FW_NEWLINE, 0);
|
|
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "=========mysql < %s==================== >> %s", mysql_anyhost, mysql_log);
|
|
f_write_string(mysql_log, tmp1, FW_APPEND | FW_NEWLINE, 0);
|
|
|
|
memset(tmp1, 0, sizeof(tmp1));
|
|
snprintf(tmp1, sizeof(tmp1), "%s/mysql -uroot -p\"%s\" < %s >> %s 2>&1", pbi, nvram_safe_get("mysql_passwd"), mysql_anyhost, mysql_log);
|
|
system(tmp1);
|
|
system("/bin/rm -f "mysql_anyhost);
|
|
}
|
|
|
|
eval("mkdir", "-p", nginx_docroot);
|
|
eval("cp", "-p", "/www/adminer.php", nginx_docroot);
|
|
sleep(1);
|
|
|
|
END:
|
|
if (pidof("mysqld") > 0) {
|
|
logmsg(LOG_INFO, "mysqld started");
|
|
setup_mysql_watchdog();
|
|
unlink(mysql_child_pid);
|
|
}
|
|
else {
|
|
logmsg(LOG_ERR, "starting mysqld failed - check configuration ...");
|
|
unlink(mysql_child_pid);
|
|
stop_mysql();
|
|
}
|
|
|
|
/* terminate the child */
|
|
exit(0);
|
|
}
|
|
|
|
void stop_mysql(void)
|
|
{
|
|
pid_t pid;
|
|
char pbi[128], buf[512];
|
|
int m = atoi(nvram_safe_get("mysql_sleep")) + 70;
|
|
|
|
if (serialize_restart("mysqld", 0))
|
|
return;
|
|
|
|
if ((pid = pidof("mysqld")) > 0)
|
|
logmsg(LOG_INFO, "terminating mysqld ...");
|
|
else
|
|
return;
|
|
|
|
eval("cru", "d", "CheckMySQL");
|
|
|
|
/* wait for child of start_mysql to finish (if any) */
|
|
memset(buf, 0, sizeof(buf));
|
|
while (f_read_string(mysql_child_pid, buf, sizeof(buf)) > 0 && atoi(buf) > 0 && ppid(atoi(buf)) > 0 && (m-- > 0)) {
|
|
logmsg(LOG_DEBUG, "*** %s: waiting for child process of start_mysql to end, %d secs left ...", __FUNCTION__, m);
|
|
sleep(1);
|
|
}
|
|
|
|
if (nvram_match("mysql_binary", "internal"))
|
|
strlcpy(pbi, "/usr/bin", sizeof(pbi));
|
|
else if (nvram_match("mysql_binary", "optware"))
|
|
strlcpy(pbi, "/opt/bin", sizeof(pbi));
|
|
else
|
|
strlcpy(pbi, nvram_safe_get("mysql_binary_custom"), sizeof(pbi));
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
snprintf(buf, sizeof(buf), "%s/mysqladmin -uroot -p\"%s\" --shutdown_timeout=3 shutdown", pbi, nvram_safe_get("mysql_passwd"));
|
|
system(buf);
|
|
|
|
killall_and_waitfor("mysqld", 10, 80);
|
|
|
|
if (pid > 0)
|
|
logmsg(LOG_INFO, "mysqld stopped");
|
|
|
|
/* clean-up */
|
|
system("/bin/rm -f "mysql_pid);
|
|
unlink(mysql_conf_link);
|
|
system("/bin/rm -rf "mysql_etc_dir);
|
|
}
|