getSettings();$db=$base->connect(); $engines=$db->query("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_TYPE='BASE TABLE'")->fetchAll(PDO::FETCH_COLUMN); if(array_filter($engines,static fn($v)=>$v!=='InnoDB'))throw new RuntimeException('Nontransactional tables require a maintenance-window locked backup.'); $file=$directory.DIRECTORY_SEPARATOR.'hcr-'.gmdate('Ymd-His').'-'.bin2hex(random_bytes(3)).'.sql'; $partial=$file.'.partial';$config=null; $quote=static fn($value)=>'"'.str_replace(["\\",'"',"\r","\n"],["\\\\",'\\"','\\r','\\n'],(string)$value).'"'; $options="[client]\nhost=".$quote($settings->DatabaseServer)."\nport=".(int)($settings->DatabasePort??3306)."\nuser=".$quote($settings->DatabaseUser)."\npassword=".$quote($settings->DatabasePassword)."\n"; $ca=getenv('HCR_DB_TLS_CA');if($ca)$options.='ssl-ca='.$quote($ca)."\nssl-verify-server-cert\n"; try{ $handle=fopen($partial,'x');if(!$handle)throw new RuntimeException('Cannot create protected backup output.');fclose($handle);chmod($partial,0600); $config=tempnam($directory,'hcr-connection-');if($config===false)throw new RuntimeException('Cannot create protected connection configuration.');chmod($config,0600); file_put_contents($config,$options); $command=[getenv('HCR_DUMP_BINARY')?:'mariadb-dump','--defaults-extra-file='.$config,'--single-transaction','--quick','--routines','--events','--triggers','--hex-blob','--databases',(string)$settings->DatabaseName,'--result-file='.$partial]; $process=proc_open($command,[0=>['pipe','r'],1=>['pipe','w'],2=>['pipe','w']],$pipes); if(!is_resource($process))throw new RuntimeException('Backup process could not start.'); fclose($pipes[0]);$out=stream_get_contents($pipes[1]);$error=stream_get_contents($pipes[2]);fclose($pipes[1]);fclose($pipes[2]); if(proc_close($process)!==0){error_log('Backup process failed: '.$error);throw new RuntimeException('Backup failed; inspect the protected backup error log.');} if(!BackupValidation::complete($partial))throw new RuntimeException('Backup completion could not be confirmed.'); if(!rename($partial,$file))throw new RuntimeException('Cannot finalize completed backup.'); chmod($file,0600); $metadata=['created_utc'=>gmdate(DATE_ATOM),'bytes'=>filesize($file),'sha256'=>hash_file('sha256',$file)];file_put_contents($file.'.json',json_encode($metadata,JSON_PRETTY_PRINT));chmod($file.'.json',0600); echo json_encode(['backup'=>$file]+$metadata),"\n"; }finally{if(is_string($config)&&is_file($config))unlink($config);if(is_file($partial))unlink($partial);}