xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/ext/Fcntl/t/syslfs.t (revision 0:68f95e015346)
1*0Sstevel@tonic-gate# NOTE: this file tests how large files (>2GB) work with raw system IO.
2*0Sstevel@tonic-gate# stdio: open(), tell(), seek(), print(), read() is tested in t/op/lfs.t.
3*0Sstevel@tonic-gate# If you modify/add tests here, remember to update also t/op/lfs.t.
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gateBEGIN {
6*0Sstevel@tonic-gate	chdir 't' if -d 't';
7*0Sstevel@tonic-gate	@INC = '../lib';
8*0Sstevel@tonic-gate	require Config; import Config;
9*0Sstevel@tonic-gate	# Don't bother if there are no quad offsets.
10*0Sstevel@tonic-gate	if ($Config{lseeksize} < 8) {
11*0Sstevel@tonic-gate		print "1..0 # Skip: no 64-bit file offsets\n";
12*0Sstevel@tonic-gate		exit(0);
13*0Sstevel@tonic-gate	}
14*0Sstevel@tonic-gate	require Fcntl; import Fcntl qw(/^O_/ /^SEEK_/);
15*0Sstevel@tonic-gate}
16*0Sstevel@tonic-gate
17*0Sstevel@tonic-gateuse strict;
18*0Sstevel@tonic-gate
19*0Sstevel@tonic-gate$| = 1;
20*0Sstevel@tonic-gate
21*0Sstevel@tonic-gateour @s;
22*0Sstevel@tonic-gateour $fail;
23*0Sstevel@tonic-gate
24*0Sstevel@tonic-gatesub zap {
25*0Sstevel@tonic-gate    close(BIG);
26*0Sstevel@tonic-gate    unlink("big");
27*0Sstevel@tonic-gate    unlink("big1");
28*0Sstevel@tonic-gate    unlink("big2");
29*0Sstevel@tonic-gate}
30*0Sstevel@tonic-gate
31*0Sstevel@tonic-gatesub bye {
32*0Sstevel@tonic-gate    zap();
33*0Sstevel@tonic-gate    exit(0);
34*0Sstevel@tonic-gate}
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gatemy $explained;
37*0Sstevel@tonic-gate
38*0Sstevel@tonic-gatesub explain {
39*0Sstevel@tonic-gate    unless ($explained++) {
40*0Sstevel@tonic-gate	print <<EOM;
41*0Sstevel@tonic-gate#
42*0Sstevel@tonic-gate# If the lfs (large file support: large meaning larger than two
43*0Sstevel@tonic-gate# gigabytes) tests are skipped or fail, it may mean either that your
44*0Sstevel@tonic-gate# process (or process group) is not allowed to write large files
45*0Sstevel@tonic-gate# (resource limits) or that the file system (the network filesystem?)
46*0Sstevel@tonic-gate# you are running the tests on doesn't let your user/group have large
47*0Sstevel@tonic-gate# files (quota) or the filesystem simply doesn't support large files.
48*0Sstevel@tonic-gate# You may even need to reconfigure your kernel.  (This is all very
49*0Sstevel@tonic-gate# operating system and site-dependent.)
50*0Sstevel@tonic-gate#
51*0Sstevel@tonic-gate# Perl may still be able to support large files, once you have
52*0Sstevel@tonic-gate# such a process, enough quota, and such a (file) system.
53*0Sstevel@tonic-gate# It is just that the test failed now.
54*0Sstevel@tonic-gate#
55*0Sstevel@tonic-gateEOM
56*0Sstevel@tonic-gate    }
57*0Sstevel@tonic-gate    print "1..0 # Skip: @_\n" if @_;
58*0Sstevel@tonic-gate}
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gateprint "# checking whether we have sparse files...\n";
61*0Sstevel@tonic-gate
62*0Sstevel@tonic-gate# Known have-nots.
63*0Sstevel@tonic-gateif ($^O eq 'MSWin32' || $^O eq 'NetWare' || $^O eq 'VMS') {
64*0Sstevel@tonic-gate    print "1..0 # Skip: no sparse files in $^O\n";
65*0Sstevel@tonic-gate    bye();
66*0Sstevel@tonic-gate}
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate# Known haves that have problems running this test
69*0Sstevel@tonic-gate# (for example because they do not support sparse files, like UNICOS)
70*0Sstevel@tonic-gateif ($^O eq 'unicos') {
71*0Sstevel@tonic-gate    print "1..0 # Skip: no sparse files in $^0, unable to test large files\n";
72*0Sstevel@tonic-gate    bye();
73*0Sstevel@tonic-gate}
74*0Sstevel@tonic-gate
75*0Sstevel@tonic-gate# Then try heuristically to deduce whether we have sparse files.
76*0Sstevel@tonic-gate
77*0Sstevel@tonic-gate# We'll start off by creating a one megabyte file which has
78*0Sstevel@tonic-gate# only three "true" bytes.  If we have sparseness, we should
79*0Sstevel@tonic-gate# consume less blocks than one megabyte (assuming nobody has
80*0Sstevel@tonic-gate# one megabyte blocks...)
81*0Sstevel@tonic-gate
82*0Sstevel@tonic-gatesysopen(BIG, "big1", O_WRONLY|O_CREAT|O_TRUNC) or
83*0Sstevel@tonic-gate    do { warn "sysopen big1 failed: $!\n"; bye };
84*0Sstevel@tonic-gatesysseek(BIG, 1_000_000, SEEK_SET) or
85*0Sstevel@tonic-gate    do { warn "sysseek big1 failed: $!\n"; bye };
86*0Sstevel@tonic-gatesyswrite(BIG, "big") or
87*0Sstevel@tonic-gate    do { warn "syswrite big1 failed; $!\n"; bye };
88*0Sstevel@tonic-gateclose(BIG) or
89*0Sstevel@tonic-gate    do { warn "close big1 failed: $!\n"; bye };
90*0Sstevel@tonic-gate
91*0Sstevel@tonic-gatemy @s1 = stat("big1");
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gateprint "# s1 = @s1\n";
94*0Sstevel@tonic-gate
95*0Sstevel@tonic-gatesysopen(BIG, "big2", O_WRONLY|O_CREAT|O_TRUNC) or
96*0Sstevel@tonic-gate    do { warn "sysopen big2 failed: $!\n"; bye };
97*0Sstevel@tonic-gatesysseek(BIG, 2_000_000, SEEK_SET) or
98*0Sstevel@tonic-gate    do { warn "sysseek big2 failed: $!\n"; bye };
99*0Sstevel@tonic-gatesyswrite(BIG, "big") or
100*0Sstevel@tonic-gate    do { warn "syswrite big2 failed; $!\n"; bye };
101*0Sstevel@tonic-gateclose(BIG) or
102*0Sstevel@tonic-gate    do { warn "close big2 failed: $!\n"; bye };
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gatemy @s2 = stat("big2");
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gateprint "# s2 = @s2\n";
107*0Sstevel@tonic-gate
108*0Sstevel@tonic-gatezap();
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gateunless ($s1[7] == 1_000_003 && $s2[7] == 2_000_003 &&
111*0Sstevel@tonic-gate	$s1[11] == $s2[11] && $s1[12] == $s2[12]) {
112*0Sstevel@tonic-gate	print "1..0 # Skip: no sparse files?\n";
113*0Sstevel@tonic-gate	bye;
114*0Sstevel@tonic-gate}
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gateprint "# we seem to have sparse files...\n";
117*0Sstevel@tonic-gate
118*0Sstevel@tonic-gate# By now we better be sure that we do have sparse files:
119*0Sstevel@tonic-gate# if we are not, the following will hog 5 gigabytes of disk.  Ooops.
120*0Sstevel@tonic-gate# This may fail by producing some signal; run in a subprocess first for safety
121*0Sstevel@tonic-gate
122*0Sstevel@tonic-gate$ENV{LC_ALL} = "C";
123*0Sstevel@tonic-gate
124*0Sstevel@tonic-gatemy $r = system '../perl', '-I../lib', '-e', <<'EOF';
125*0Sstevel@tonic-gateuse Fcntl qw(/^O_/ /^SEEK_/);
126*0Sstevel@tonic-gatesysopen(BIG, "big", O_WRONLY|O_CREAT|O_TRUNC) or die $!;
127*0Sstevel@tonic-gatemy $sysseek = sysseek(BIG, 5_000_000_000, SEEK_SET);
128*0Sstevel@tonic-gatemy $syswrite = syswrite(BIG, "big");
129*0Sstevel@tonic-gateexit 0;
130*0Sstevel@tonic-gateEOF
131*0Sstevel@tonic-gate
132*0Sstevel@tonic-gatesysopen(BIG, "big", O_WRONLY|O_CREAT|O_TRUNC) or
133*0Sstevel@tonic-gate	do { warn "sysopen 'big' failed: $!\n"; bye };
134*0Sstevel@tonic-gatemy $sysseek = sysseek(BIG, 5_000_000_000, SEEK_SET);
135*0Sstevel@tonic-gateunless (! $r && defined $sysseek && $sysseek == 5_000_000_000) {
136*0Sstevel@tonic-gate    $sysseek = 'undef' unless defined $sysseek;
137*0Sstevel@tonic-gate    explain("seeking past 2GB failed: ",
138*0Sstevel@tonic-gate	    $r ? 'signal '.($r & 0x7f) : "$! (sysseek returned $sysseek)");
139*0Sstevel@tonic-gate    bye();
140*0Sstevel@tonic-gate}
141*0Sstevel@tonic-gate
142*0Sstevel@tonic-gate# The syswrite will fail if there are are filesize limitations (process or fs).
143*0Sstevel@tonic-gatemy $syswrite = syswrite(BIG, "big");
144*0Sstevel@tonic-gateprint "# syswrite failed: $! (syswrite returned ",
145*0Sstevel@tonic-gate      defined $syswrite ? $syswrite : 'undef', ")\n"
146*0Sstevel@tonic-gate    unless defined $syswrite && $syswrite == 3;
147*0Sstevel@tonic-gatemy $close     = close BIG;
148*0Sstevel@tonic-gateprint "# close failed: $!\n" unless $close;
149*0Sstevel@tonic-gateunless($syswrite && $close) {
150*0Sstevel@tonic-gate    if ($! =~/too large/i) {
151*0Sstevel@tonic-gate	explain("writing past 2GB failed: process limits?");
152*0Sstevel@tonic-gate    } elsif ($! =~ /quota/i) {
153*0Sstevel@tonic-gate	explain("filesystem quota limits?");
154*0Sstevel@tonic-gate    } else {
155*0Sstevel@tonic-gate	explain("error: $!");
156*0Sstevel@tonic-gate    }
157*0Sstevel@tonic-gate    bye();
158*0Sstevel@tonic-gate}
159*0Sstevel@tonic-gate
160*0Sstevel@tonic-gate@s = stat("big");
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gateprint "# @s\n";
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gateunless ($s[7] == 5_000_000_003) {
165*0Sstevel@tonic-gate    explain("kernel/fs not configured to use large files?");
166*0Sstevel@tonic-gate    bye();
167*0Sstevel@tonic-gate}
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gatesub fail () {
170*0Sstevel@tonic-gate    print "not ";
171*0Sstevel@tonic-gate    $fail++;
172*0Sstevel@tonic-gate}
173*0Sstevel@tonic-gate
174*0Sstevel@tonic-gatesub offset ($$) {
175*0Sstevel@tonic-gate    my ($offset_will_be, $offset_want) = @_;
176*0Sstevel@tonic-gate    my $offset_is = eval $offset_will_be;
177*0Sstevel@tonic-gate    unless ($offset_is == $offset_want) {
178*0Sstevel@tonic-gate        print "# bad offset $offset_is, want $offset_want\n";
179*0Sstevel@tonic-gate	my ($offset_func) = ($offset_will_be =~ /^(\w+)/);
180*0Sstevel@tonic-gate	if (unpack("L", pack("L", $offset_want)) == $offset_is) {
181*0Sstevel@tonic-gate	    print "# 32-bit wraparound suspected in $offset_func() since\n";
182*0Sstevel@tonic-gate	    print "# $offset_want cast into 32 bits equals $offset_is.\n";
183*0Sstevel@tonic-gate	} elsif ($offset_want - unpack("L", pack("L", $offset_want)) - 1
184*0Sstevel@tonic-gate	         == $offset_is) {
185*0Sstevel@tonic-gate	    print "# 32-bit wraparound suspected in $offset_func() since\n";
186*0Sstevel@tonic-gate	    printf "# %s - unpack('L', pack('L', %s)) - 1 equals %s.\n",
187*0Sstevel@tonic-gate	        $offset_want,
188*0Sstevel@tonic-gate	        $offset_want,
189*0Sstevel@tonic-gate	        $offset_is;
190*0Sstevel@tonic-gate        }
191*0Sstevel@tonic-gate        fail;
192*0Sstevel@tonic-gate    }
193*0Sstevel@tonic-gate}
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gateprint "1..17\n";
196*0Sstevel@tonic-gate
197*0Sstevel@tonic-gate$fail = 0;
198*0Sstevel@tonic-gate
199*0Sstevel@tonic-gatefail unless $s[7] == 5_000_000_003;	# exercizes pp_stat
200*0Sstevel@tonic-gateprint "ok 1\n";
201*0Sstevel@tonic-gate
202*0Sstevel@tonic-gatefail unless -s "big" == 5_000_000_003;	# exercizes pp_ftsize
203*0Sstevel@tonic-gateprint "ok 2\n";
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gatefail unless -e "big";
206*0Sstevel@tonic-gateprint "ok 3\n";
207*0Sstevel@tonic-gate
208*0Sstevel@tonic-gatefail unless -f "big";
209*0Sstevel@tonic-gateprint "ok 4\n";
210*0Sstevel@tonic-gate
211*0Sstevel@tonic-gatesysopen(BIG, "big", O_RDONLY) or do { warn "sysopen failed: $!\n"; bye };
212*0Sstevel@tonic-gate
213*0Sstevel@tonic-gateoffset('sysseek(BIG, 4_500_000_000, SEEK_SET)', 4_500_000_000);
214*0Sstevel@tonic-gateprint "ok 5\n";
215*0Sstevel@tonic-gate
216*0Sstevel@tonic-gateoffset('sysseek(BIG, 0, SEEK_CUR)', 4_500_000_000);
217*0Sstevel@tonic-gateprint "ok 6\n";
218*0Sstevel@tonic-gate
219*0Sstevel@tonic-gateoffset('sysseek(BIG, 1, SEEK_CUR)', 4_500_000_001);
220*0Sstevel@tonic-gateprint "ok 7\n";
221*0Sstevel@tonic-gate
222*0Sstevel@tonic-gateoffset('sysseek(BIG, 0, SEEK_CUR)', 4_500_000_001);
223*0Sstevel@tonic-gateprint "ok 8\n";
224*0Sstevel@tonic-gate
225*0Sstevel@tonic-gateoffset('sysseek(BIG, -1, SEEK_CUR)', 4_500_000_000);
226*0Sstevel@tonic-gateprint "ok 9\n";
227*0Sstevel@tonic-gate
228*0Sstevel@tonic-gateoffset('sysseek(BIG, 0, SEEK_CUR)', 4_500_000_000);
229*0Sstevel@tonic-gateprint "ok 10\n";
230*0Sstevel@tonic-gate
231*0Sstevel@tonic-gateoffset('sysseek(BIG, -3, SEEK_END)', 5_000_000_000);
232*0Sstevel@tonic-gateprint "ok 11\n";
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gateoffset('sysseek(BIG, 0, SEEK_CUR)', 5_000_000_000);
235*0Sstevel@tonic-gateprint "ok 12\n";
236*0Sstevel@tonic-gate
237*0Sstevel@tonic-gatemy $big;
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gatefail unless sysread(BIG, $big, 3) == 3;
240*0Sstevel@tonic-gateprint "ok 13\n";
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gatefail unless $big eq "big";
243*0Sstevel@tonic-gateprint "ok 14\n";
244*0Sstevel@tonic-gate
245*0Sstevel@tonic-gate# 705_032_704 = (I32)5_000_000_000
246*0Sstevel@tonic-gate# See that we don't have "big" in the 705_... spot:
247*0Sstevel@tonic-gate# that would mean that we have a wraparound.
248*0Sstevel@tonic-gatefail unless sysseek(BIG, 705_032_704, SEEK_SET);
249*0Sstevel@tonic-gateprint "ok 15\n";
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gatemy $zero;
252*0Sstevel@tonic-gate
253*0Sstevel@tonic-gatefail unless read(BIG, $zero, 3) == 3;
254*0Sstevel@tonic-gateprint "ok 16\n";
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gatefail unless $zero eq "\0\0\0";
257*0Sstevel@tonic-gateprint "ok 17\n";
258*0Sstevel@tonic-gate
259*0Sstevel@tonic-gateexplain() if $fail;
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gatebye(); # does the necessary cleanup
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gateEND {
264*0Sstevel@tonic-gate    # unlink may fail if applied directly to a large file
265*0Sstevel@tonic-gate    # be paranoid about leaving 5 gig files lying around
266*0Sstevel@tonic-gate    open(BIG, ">big"); # truncate
267*0Sstevel@tonic-gate    close(BIG);
268*0Sstevel@tonic-gate    1 while unlink "big"; # standard portable idiom
269*0Sstevel@tonic-gate}
270*0Sstevel@tonic-gate
271*0Sstevel@tonic-gate# eof
272