1# Create a log file on a file system that can be easily filled.
2# The client writes messages to Sys::Syslog native method.
3# While writing messages, the client fills the log file system.
4# After the file system has been filled, remove the big file and recover.
5# The syslogd writes it into a file and through a pipe and to tty.
6# The syslogd passes it via UDP to the loghost.
7# The server receives the message on its UDP socket.
8# Find the message in client, file, pipe, console, user, syslogd, server log.
9# Check that syslogd error 'No space left on device' error is logged to server.
10# Check that kernel error 'file system full' error is logged.
11# Check that 'dropped messages to file' is logged by server and file.
12
13use strict;
14use warnings;
15use Errno ':POSIX';
16use File::Path qw(remove_tree);
17use Time::HiRes;
18
19my @errors = (ENOSPC);
20my $errors = "(". join("|", map { $! = $_ } @errors). ")";
21
22my $fspath = "/mnt/regress-syslogd";
23my $fslog = "$fspath/file.log";
24my $fsbig = "$fspath/big";
25
26remove_tree($fspath, { safe => 1, keep_root => 1 });
27open(my $log, '>', $fslog)
28    or die "Create $fslog failed: $!";
29
30our %args = (
31    client => {
32	func => sub { write_between2logs(shift, sub {
33	    my $self = shift;
34	    open(my $big, '>', $fsbig)
35		or die ref($self), " create $fsbig failed: $!";
36	    ${$self->{syslogd}}->loggrep(get_firstlog(), 5)
37		or die ref($self), " first log not in syslogd log";
38	    undef $!;
39	    for (my $i = 0; $i < 100000; $i++) {
40		syswrite($big, "regress syslogd file system full\n", 33)
41		    or last;
42	    }
43	    $!{ENOSPC}
44		or die ref($self), " fill $fsbig failed: $!";
45	    ${$self->{syslogd}}->loggrep(qr/file system full/, 5)
46		or die ref($self), " file system full not in syslogd log";
47	    # a single message still fits, write 4 KB logs to reach next block
48	    write_lines($self, 50, 70);
49	    ${$self->{syslogd}}->loggrep(qr/write to file .* $errors/, 10)
50		or die ref($self), " write to file error not in syslogd log";
51	    close($big);
52	    unlink($fsbig)
53		or die ref($self), " remove $fsbig failed: $!";
54	    # wait until syslogd has processed everything
55	    write_message($self, get_secondlog());
56	    ${$self->{server}}->loggrep(get_secondlog(), 8)
57		or die ref($self), " second log not in server log";
58	})},
59    },
60    syslogd => {
61	outfile => $fslog,
62	loggrep => {
63	    get_testgrep() => 1,
64	    get_charlog() => 50,
65	},
66    },
67    server => {
68	loggrep => {
69	    get_firstlog() => 1,
70	    get_secondlog() => 1,
71	    get_testgrep() => 1,
72	    qr/syslogd\[\d+\]: write to file "$fslog": /.
73		qr/No space left on device/ => '>=1',
74	    qr/bsd: .* on $fspath: file system full/ => '>=1',
75	    qr/syslogd\[\d+\]: dropped \d+ messages to file "$fslog"/ => '>=1',
76	},
77    },
78    file => {
79	loggrep => {
80	    get_firstlog() => 1,
81	    get_testgrep() => 1,
82	    qr/syslogd\[\d+\]: write to file "$fslog": /.
83		qr/No space left on device/ => 0,
84	    qr/syslogd\[\d+\]: dropped \d+ messages to file "$fslog"/ => '>=1',
85	},
86    },
87);
88
891;
90