Files
mysql-bkup/internal/mysql/options.go
T
jkaninda 28de0d7b52 feat: mysql-bkup v2 on bkupkit
MysQL backup and restore built on the shared bkupkit core:
streaming end to end, with no dump held in memory or written to
local disk.
2026-10-28 11:18:56 +01:00

102 lines
2.8 KiB
Go

package mysql
import (
"strconv"
"strings"
)
// quoteOption quotes a value for a MySQL/MariaDB option file. Both client
// families parse option files with the same mysys code: a value wrapped in
// double quotes keeps leading/trailing spaces and '#', and the escapes
// \\ \" \n \r \t are decoded inside it.
func quoteOption(s string) string {
var b strings.Builder
b.Grow(len(s) + 2)
b.WriteByte('"')
for _, r := range s {
switch r {
case '\\':
b.WriteString(`\\`)
case '"':
b.WriteString(`\"`)
case '\n':
b.WriteString(`\n`)
case '\r':
b.WriteString(`\r`)
case '\t':
b.WriteString(`\t`)
default:
b.WriteRune(r)
}
}
b.WriteByte('"')
return b.String()
}
// optionFile returns the [client] option file for c. mariadbClient selects
// the MariaDB client option names (ssl, ssl-verify-server-cert) instead of
// the Oracle MySQL ones (ssl-mode, get-server-public-key).
//
// The file holds the password; it is written 0600 in a private directory and
// passed as --defaults-extra-file, never on the command line.
func optionFile(c Conn, mariadbClient bool) string {
var b strings.Builder
line := func(k, v string) {
b.WriteString(k)
b.WriteByte('=')
b.WriteString(v)
b.WriteByte('\n')
}
b.WriteString("[client]\n")
if strings.HasPrefix(c.Host, "/") {
line("protocol", "SOCKET")
line("socket", quoteOption(c.Host))
} else {
// TCP even for "localhost" (a client would otherwise look for a socket).
line("protocol", "TCP")
line("host", quoteOption(c.Host))
line("port", strconv.Itoa(c.Port))
}
line("user", quoteOption(c.User))
line("password", quoteOption(c.Password))
line("max-allowed-packet", "1G")
verify := c.SSLMode == SSLVerifyCA || c.SSLMode == SSLVerifyIdentity
if mariadbClient {
switch c.SSLMode {
case SSLDisabled:
line("ssl", "0")
case SSLPreferred:
// Leave TLS to the client default, without certificate checks.
line("ssl-verify-server-cert", "0")
case SSLRequired:
line("ssl", "1")
line("ssl-verify-server-cert", "0")
default: // verify_ca, verify_identity: MariaDB always checks the host name too
line("ssl", "1")
line("ssl-verify-server-cert", "1")
}
} else {
line("ssl-mode", strings.ToUpper(c.SSLMode))
if c.SSLMode != SSLVerifyIdentity && c.SSLMode != SSLVerifyCA {
// caching_sha2_password over a non-TLS connection needs the
// server's RSA key (what the MariaDB client does by itself).
line("get-server-public-key", "1")
}
}
if c.SSLMode != SSLDisabled {
// The CA is only used when certificates are verified: with the MySQL
// client, a CA would otherwise silently turn "required" into "verify_ca".
if verify && c.SSLCA != "" {
line("ssl-ca", quoteOption(c.SSLCA))
}
if c.SSLCert != "" {
line("ssl-cert", quoteOption(c.SSLCert))
}
if c.SSLKey != "" {
line("ssl-key", quoteOption(c.SSLKey))
}
}
return b.String()
}