Files
webmin/logrotate/edit_sched.cgi
Ilia Ross 466f499e65 Fix openSUSE logrotate vendor overlay handling
This PR updates the Log File Rotation module for openSUSE Leap 16's split `/usr/etc` and `/etc` configuration model.

- Select the local main configuration when present, otherwise use the vendor configuration.

- Recursively merge vendor and local drop-ins using the same precedence as `logrotate-all`.

- Display vendor configurations while keeping `/usr/etc` read-only.

- Copy vendor files into matching `/etc` overrides before editing or deleting them.

- Preserve empty overrides so deleted vendor rotations remain disabled.

- Use the openSUSE wrapper for scheduled rotation and the effective configuration set for forced rotation.

- Keep behavior unchanged on distributions that do not enable the vendor overlay.

Includes regression coverage for selection, precedence, copy-on-write, deletion, scheduling, backups, and protection against direct vendor writes.

Closes [#2682](https://github.com/webmin/webmin/issues/2682).
2026-08-03 02:36:05 +02:00

61 lines
1.7 KiB
Perl
Executable File

#!/usr/local/bin/perl
# edit_sched.cgi
# Find the logrotate cron job, or offer to create one
require './logrotate-lib.pl';
&ui_print_header(undef, $text{'sched_title'}, "");
# Show the wrapper or fallback command on vendor-overlay systems, while
# retaining the original short program name everywhere else.
my $sched_command = ($config{'logrotate_all'} ||
$config{'vendor_logrotate_conf'} || $config{'vendor_add_file'}) ?
&get_scheduled_logrotate_command() : $config{'logrotate'};
print "<p>",&text('sched_desc', "<tt>".
&html_escape($sched_command)."</tt>"),"<p>\n";
# Find the job, looking in daily directories too
&foreign_require("cron", "cron-lib.pl");
@jobs = &cron::list_cron_jobs();
JOB: foreach $j (@jobs) {
if ($j->{'command'} =~ /logrotate/i) {
$job = $j;
last JOB;
}
local $rpd = &cron::is_run_parts($j->{'command'});
if ($rpd) {
local @exp = &cron::expand_run_parts($rpd);
foreach $e (@exp) {
if ($e =~ /logrotate/i && -r $e) {
$job = $j;
$runparts = $e;
last JOB;
}
}
}
}
if ($runparts) {
# Run from run-parts command, cannot touch
print &text('sched_runparts', "<tt>$runparts</tt>",
&cron::when_text($job)),"<p>\n";
}
else {
# Offer to enable/change/delete
print &ui_form_start("save_sched.cgi", "post");
print &ui_hidden("idx", $job ? $job->{'index'} : "");
print &ui_table_start(undef, undef, 2);
print &ui_table_row($text{'sched_sched'},
&ui_radio("sched", $job ? 1 : 0,
[ [ 0, $text{'sched_disabled'} ],
[ 1, $text{'sched_enabled'} ] ]));
$job ||= { 'special' => 'daily' };
print &cron::get_times_input($job, 0, 2, $text{'sched_when'});
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'sched_save'} ] ]);
}
&ui_print_footer("", $text{'index_return'});