From d66a3525bd7dd20eb81dea4cdc188074dd77f385 Mon Sep 17 00:00:00 2001 From: Nic Boet Date: Sun, 8 Feb 2026 13:19:32 -0600 Subject: [PATCH] feat: detect MariaDB-native command names with fallback to MySQL legacy names MariaDB is deprecating mysql-prefixed utility names (mysqldump, mysql) in favour of its own (mariadb-dump, mariadb). Add findDbCommand() to ZoneMinder::General that probes for the MariaDB-native binary first and falls back to the legacy name. Results are cached per-process. Update the three call sites in zmupdate.pl.in and zmcamtool.pl.in. Co-Authored-By: Claude Opus 4.6 --- scripts/ZoneMinder/lib/ZoneMinder/General.pm | 32 +++++++++++++++++++- scripts/zmcamtool.pl.in | 3 +- scripts/zmupdate.pl.in | 4 +-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/lib/ZoneMinder/General.pm index 94f97a32b..ecc33912c 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/General.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/General.pm @@ -20,6 +20,7 @@ our @ISA = qw(Exporter ZoneMinder::Base); our %EXPORT_TAGS = ( functions => [ qw( executeShellCommand + findDbCommand getCmdFormat runCommand setFileOwner @@ -71,6 +72,34 @@ sub executeShellCommand { return $status; } +# Map legacy MySQL command names to MariaDB-native equivalents. +# MariaDB is deprecating the mysql-prefixed names in favour of its own. +my %DB_COMMAND_MAP = ( + 'mysql' => 'mariadb', + 'mysqldump' => 'mariadb-dump', +); +my %_db_command_cache; + +sub findDbCommand { + my $legacy_name = shift; + return $_db_command_cache{$legacy_name} if exists $_db_command_cache{$legacy_name}; + + my $maria_name = $DB_COMMAND_MAP{$legacy_name}; + if ($maria_name) { + my $path = qx(command -v $maria_name 2>/dev/null); + chomp($path); + if ($path) { + Debug("Using '$maria_name' for database command '$legacy_name'"); + $_db_command_cache{$legacy_name} = $maria_name; + return $maria_name; + } + } + + Debug("Using legacy '$legacy_name' for database command"); + $_db_command_cache{$legacy_name} = $legacy_name; + return $legacy_name; +} + sub getCmdFormat { Debug('Testing valid shell syntax'); @@ -663,6 +692,7 @@ of the ZoneMinder scripts functions => [ qw( executeShellCommand + findDbCommand getCmdFormat runCommand setFileOwner @@ -674,7 +704,7 @@ of the ZoneMinder scripts packageControl daemonControl systemStatus - parseNameEqualsValueToHash + parseNameEqualsValueToHash hash_diff ) ] diff --git a/scripts/zmcamtool.pl.in b/scripts/zmcamtool.pl.in index 4f195f4a4..a733378b4 100644 --- a/scripts/zmcamtool.pl.in +++ b/scripts/zmcamtool.pl.in @@ -64,6 +64,7 @@ use bytes; @EXTRA_PERL_LIB@ use ZoneMinder::Config qw(:all); use ZoneMinder::Logger qw(:all); +use ZoneMinder::General qw(:all); use ZoneMinder::Database qw(:all); use DBI; use Getopt::Long; @@ -344,7 +345,7 @@ sub importsql { sub exportsql { my ( $host, $port ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); - my $command = 'mysqldump -t --skip-opt --compact -h'.$host; + my $command = findDbCommand('mysqldump').' -t --skip-opt --compact -h'.$host; $command .= ' -P'.$port if defined($port); if ( $dbUser ) { $command .= ' -u\''.$dbUser.'\''; diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in index 86f416928..b90705707 100644 --- a/scripts/zmupdate.pl.in +++ b/scripts/zmupdate.pl.in @@ -416,7 +416,7 @@ if ( $version ) { if ( $response =~ /^[yY]$/ ) { my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); - my $command = 'mysqldump'; + my $command = findDbCommand('mysqldump'); if ($super) { $command .= ' --defaults-file=/etc/mysql/debian.cnf'; } elsif ($dbUser) { @@ -1007,7 +1007,7 @@ sub patchDB { my $version = shift; my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ) if $Config{ZM_DB_HOST}; - my $command = 'mysql'; + my $command = findDbCommand('mysql'); if ($super) { $command .= ' --defaults-file=/etc/mysql/debian.cnf'; } elsif ($dbUser) {