diff --git a/logrotate/config-openSUSE-Linux-16.0-ALL b/logrotate/config-openSUSE-Linux-16.0-ALL new file mode 100644 index 000000000..6ddca8e5c --- /dev/null +++ b/logrotate/config-openSUSE-Linux-16.0-ALL @@ -0,0 +1,5 @@ +sort_mode=0 +logrotate_conf=/etc/logrotate.conf +add_file=/etc/logrotate.d +scan_add_file=1 +logrotate=logrotate diff --git a/logrotate/force.cgi b/logrotate/force.cgi index 1717ab8f8..0a8bbf2d1 100755 --- a/logrotate/force.cgi +++ b/logrotate/force.cgi @@ -10,7 +10,10 @@ $SIG{'TERM'} = 'IGNORE'; print $text{'force_doing'},"\n"; &clean_environment(); -$out = &backquote_logged("$config{'logrotate'} -f $config{'logrotate_conf'} 2>&1"); +my (undef, undef, $files) = &get_config($config{'logrotate_conf'}); +my @configs = ($config{'logrotate_conf'}, &get_add_file_configs($files)); +my $configs = join(" ", map { "e_path($_) } @configs); +$out = &backquote_logged("$config{'logrotate'} -f $configs 2>&1"); &reset_environment(); if ($out) { print "
$out"; diff --git a/logrotate/logrotate-lib.pl b/logrotate/logrotate-lib.pl index f211371fb..38a09fa23 100755 --- a/logrotate/logrotate-lib.pl +++ b/logrotate/logrotate-lib.pl @@ -28,6 +28,22 @@ if (!$get_config_parent_cache) { return $get_config_parent_cache; } +# get_add_file_configs([&already-loaded-files]) +# Returns configs loaded externally from the add-file directory +sub get_add_file_configs +{ +my ($files) = @_; +return ( ) if (!$config{'scan_add_file'} || !$config{'add_file'} || + !-d $config{'add_file'}); +my @rv; +foreach my $f (glob("$config{'add_file'}/*")) { + next if (!-f $f || $files && + grep { &same_file($_, $f) } @$files); + push(@rv, $f); + } +return @rv; +} + # get_config([file]) # Returns a list of logrotate config file entries sub get_config @@ -131,6 +147,12 @@ while(<$fh>) { } close($fh); if (!$argfile) { + foreach my $f (&get_add_file_configs(\@files)) { + my ($inc, undef, $ifiles) = &get_config($f); + map { $_->{'index'} += @rv } @$inc; + push(@rv, @$inc); + push(@files, @$ifiles); + } $get_config_cache{$file} = \@rv; $get_config_lnum_cache{$file} = $lnum; $get_config_files_cache{$file} = \@files; @@ -392,4 +414,3 @@ return $config{'logrotate_conf'}; } 1; - diff --git a/logrotate/t/run-tests.t b/logrotate/t/run-tests.t new file mode 100644 index 000000000..e5efba992 --- /dev/null +++ b/logrotate/t/run-tests.t @@ -0,0 +1,97 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Test::More; +use Cwd qw(abs_path); +use File::Basename qw(dirname); +use File::Path qw(make_path); +use File::Temp qw(tempdir); + +my $module_dir = abs_path(dirname(abs_path($0))."/.."); +my $root_dir = abs_path("$module_dir/.."); +my $config_dir = tempdir(CLEANUP => 1); +my $var_dir = tempdir(CLEANUP => 1); +my $fixture_dir = tempdir(CLEANUP => 1); +my $add_dir = "$fixture_dir/logrotate.d"; +my $main_file = "$fixture_dir/logrotate.conf"; +make_path("$config_dir/logrotate", $add_dir); + +sub write_text +{ +my ($file, $text) = @_; +open(my $fh, ">", $file) or die "open $file: $!"; +print $fh $text; +close($fh) or die "close $file: $!"; +} + +write_text("$config_dir/config", "os_type=linux\nos_version=0\n"); +write_text("$config_dir/logrotate/config", + "sort_mode=0\n". + "logrotate_conf=$main_file\n". + "add_file=$add_dir\n". + "scan_add_file=1\n". + "logrotate=logrotate\n"); +write_text($main_file, "weekly\n/var/log/main.log {\n\trotate 4\n}\n"); +write_text("$add_dir/one", "/var/log/one.log {\n\tdaily\n}\n"); +write_text("$add_dir/two", "/var/log/two.log {\n\tmonthly\n}\n"); + +$ENV{'WEBMIN_CONFIG'} = $config_dir; +$ENV{'WEBMIN_VAR'} = $var_dir; +$ENV{'FOREIGN_MODULE_NAME'} = 'logrotate'; +$ENV{'FOREIGN_ROOT_DIRECTORY'} = $root_dir; +chdir($module_dir) or die "chdir $module_dir: $!"; +require "$module_dir/logrotate-lib.pl"; + +sub clear_config_cache +{ +no warnings 'once'; +%main::get_config_cache = ( ); +%main::get_config_lnum_cache = ( ); +%main::get_config_files_cache = ( ); +$main::get_config_parent_cache = undef; +} + +sub log_names +{ +my ($config) = @_; +return [ map { $_->{'name'}->[0] } + grep { $_->{'members'} } @$config ]; +} + +my ($config, undef, $files) = main::get_config(); +is_deeply(log_names($config), + [ '/var/log/main.log', '/var/log/one.log', '/var/log/two.log' ], + 'opt-in scan loads sections from add_file directory'); +is_deeply([ map { $_->{'index'} } grep { $_->{'members'} } @$config ], + [ 1, 2, 3 ], 'scanned sections keep stable top-level indexes'); +is_deeply($files, + [ $main_file, "$add_dir/one", "$add_dir/two" ], + 'file cache contains the primary and scanned configuration files'); +my (undef, undef, $primary_files) = main::get_config($main_file); +is_deeply([ main::get_add_file_configs($primary_files) ], + [ "$add_dir/one", "$add_dir/two" ], + 'force rotation adds externally loaded configuration files'); + +$main::config{'scan_add_file'} = 0; +clear_config_cache(); +($config, undef, $files) = main::get_config(); +is_deeply(log_names($config), [ '/var/log/main.log' ], + 'add_file is not scanned without explicit opt-in'); +is_deeply($files, [ $main_file ], + 'file cache excludes add_file directory when scanning is disabled'); + +$main::config{'scan_add_file'} = 1; +write_text($main_file, + "weekly\ninclude $add_dir\n/var/log/main.log {\n\trotate 4\n}\n"); +clear_config_cache(); +($config, undef, $files) = main::get_config(); +is_deeply(log_names($config), + [ '/var/log/one.log', '/var/log/two.log', '/var/log/main.log' ], + 'explicitly included files are not loaded a second time'); +is(scalar(grep { main::same_file($_, "$add_dir/one") } @$files), 1, + 'explicit include is represented once in the file cache'); +(undef, undef, $primary_files) = main::get_config($main_file); +is_deeply([ main::get_add_file_configs($primary_files) ], [ ], + 'force rotation does not repeat explicitly included files'); + +done_testing();