Commit | Line | Data |
---|---|---|
8d063cd8 LW |
1 | #!./perl |
2 | ||
ea368a7c CS |
3 | BEGIN { |
4 | chdir 't' if -d 't'; | |
20822f61 | 5 | @INC = '../lib'; |
0c5d4ba3 | 6 | require "./test.pl"; |
ea368a7c CS |
7 | } |
8 | ||
9 | use Config; | |
dc459aad | 10 | use File::Spec::Functions; |
ea368a7c | 11 | |
dc459aad | 12 | my $Is_MacOS = ($^O eq 'MacOS'); |
6d738113 | 13 | my $Is_VMSish = ($^O eq 'VMS'); |
0c5d4ba3 | 14 | |
20dd405c MS |
15 | if (($^O eq 'MSWin32') || ($^O eq 'NetWare')) { |
16 | $wd = `cd`; | |
17 | } elsif ($^O eq 'VMS') { | |
18 | $wd = `show default`; | |
19 | } else { | |
20 | $wd = `pwd`; | |
21 | } | |
22 | chomp($wd); | |
23 | ||
0c5d4ba3 JH |
24 | my $has_link = $Config{d_link}; |
25 | my $accurate_timestamps = | |
26 | !($^O eq 'MSWin32' || $^O eq 'NetWare' || | |
27 | $^O eq 'dos' || $^O eq 'os2' || | |
20dd405c | 28 | $^O eq 'mint' || $^O eq 'cygwin' || |
dc459aad JH |
29 | $^O eq 'amigaos' || $wd =~ m#$Config{afsroot}/# || |
30 | $Is_MacOS | |
20dd405c | 31 | ); |
39e571d4 | 32 | |
6b980173 | 33 | if (defined &Win32::IsWinNT && Win32::IsWinNT()) { |
0c5d4ba3 | 34 | if (Win32::FsType() eq 'NTFS') { |
20dd405c MS |
35 | $has_link = 1; |
36 | $accurate_timestamps = 1; | |
0c5d4ba3 | 37 | } |
6b980173 JD |
38 | } |
39 | ||
0c5d4ba3 JH |
40 | my $needs_fh_reopen = |
41 | $^O eq 'dos' | |
42 | # Not needed on HPFS, but needed on HPFS386 ?! | |
43 | || $^O eq 'os2'; | |
44 | ||
7a2cf369 NK |
45 | $needs_fh_reopen = 1 if (defined &Win32::IsWin95 && Win32::IsWin95()); |
46 | ||
4e51f8e4 SR |
47 | my $skip_mode_checks = |
48 | $^O eq 'cygwin' && $ENV{CYGWIN} !~ /ntsec/; | |
49 | ||
c4aca7d0 | 50 | plan tests => 42; |
8d063cd8 | 51 | |
378cc40b | 52 | |
6d738113 PP |
53 | if (($^O eq 'MSWin32') || ($^O eq 'NetWare')) { |
54 | `rmdir /s /q tmp 2>nul`; | |
55 | `mkdir tmp`; | |
dc459aad JH |
56 | } |
57 | elsif ($^O eq 'VMS') { | |
6d738113 PP |
58 | `if f\$search("[.tmp]*.*") .nes. "" then delete/nolog/noconfirm [.tmp]*.*.*`; |
59 | `if f\$search("tmp.dir") .nes. "" then delete/nolog/noconfirm tmp.dir;`; | |
60 | `create/directory [.tmp]`; | |
61 | } | |
dc459aad JH |
62 | elsif ($Is_MacOS) { |
63 | rmdir "tmp"; mkdir "tmp"; | |
64 | } | |
6d738113 PP |
65 | else { |
66 | `rm -f tmp 2>/dev/null; mkdir tmp 2>/dev/null`; | |
67 | } | |
0c5d4ba3 | 68 | |
dc459aad | 69 | chdir catdir(curdir(), 'tmp'); |
0c5d4ba3 | 70 | |
b8440792 | 71 | `/bin/rm -rf a b c x` if -x '/bin/rm'; |
8d063cd8 LW |
72 | |
73 | umask(022); | |
74 | ||
20dd405c | 75 | SKIP: { |
dc459aad | 76 | skip "bogus umask", 1 if ($^O eq 'MSWin32') || ($^O eq 'NetWare') || ($^O eq 'epoc') || $Is_MacOS; |
20dd405c MS |
77 | |
78 | is((umask(0)&0777), 022, 'umask'), | |
0c5d4ba3 JH |
79 | } |
80 | ||
8d063cd8 LW |
81 | open(fh,'>x') || die "Can't create x"; |
82 | close(fh); | |
83 | open(fh,'>a') || die "Can't create a"; | |
84 | close(fh); | |
85 | ||
8268670f JH |
86 | my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
87 | $blksize,$blocks); | |
88 | ||
3ed9f8f7 | 89 | SKIP: { |
0c5d4ba3 | 90 | skip("no link", 4) unless $has_link; |
8d063cd8 | 91 | |
0c5d4ba3 JH |
92 | ok(link('a','b'), "link a b"); |
93 | ok(link('b','c'), "link b c"); | |
8d063cd8 | 94 | |
8268670f JH |
95 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
96 | $blksize,$blocks) = stat('c'); | |
8d063cd8 | 97 | |
20dd405c MS |
98 | SKIP: { |
99 | skip "no nlink", 1 if $Config{dont_use_nlink}; | |
100 | ||
101 | is($nlink, 3, "link count of triply-linked file"); | |
0c5d4ba3 | 102 | } |
ea368a7c | 103 | |
20dd405c MS |
104 | SKIP: { |
105 | skip "hard links not that hard in $^O", 1 if $^O eq 'amigaos'; | |
4e51f8e4 | 106 | skip "no mode checks", 1 if $skip_mode_checks; |
20dd405c | 107 | |
bbf171ae GH |
108 | # if ($^O eq 'cygwin') { # new files on cygwin get rwx instead of rw- |
109 | # is($mode & 0777, 0777, "mode of triply-linked file"); | |
110 | # } else { | |
4e51f8e4 | 111 | is($mode & 0777, 0666, "mode of triply-linked file"); |
bbf171ae | 112 | # } |
0c5d4ba3 JH |
113 | } |
114 | } | |
8d063cd8 | 115 | |
2986a63f | 116 | $newmode = (($^O eq 'MSWin32') || ($^O eq 'NetWare')) ? 0444 : 0777; |
8d063cd8 | 117 | |
0c5d4ba3 | 118 | is(chmod($newmode,'a'), 1, "chmod succeeding"); |
8d063cd8 | 119 | |
0c5d4ba3 | 120 | SKIP: { |
2f3b333f | 121 | skip("no link", 7) unless $has_link; |
0c5d4ba3 | 122 | |
8268670f JH |
123 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
124 | $blksize,$blocks) = stat('c'); | |
0c5d4ba3 | 125 | |
4e51f8e4 SR |
126 | SKIP: { |
127 | skip "no mode checks", 1 if $skip_mode_checks; | |
128 | ||
129 | is($mode & 0777, $newmode, "chmod going through"); | |
130 | } | |
0c5d4ba3 JH |
131 | |
132 | $newmode = 0700; | |
6b980173 JD |
133 | chmod 0444, 'x'; |
134 | $newmode = 0666; | |
6b980173 | 135 | |
0c5d4ba3 | 136 | is(chmod($newmode,'c','x'), 2, "chmod two files"); |
3ed9f8f7 | 137 | |
0c5d4ba3 JH |
138 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
139 | $blksize,$blocks) = stat('c'); | |
8d063cd8 | 140 | |
4e51f8e4 SR |
141 | SKIP: { |
142 | skip "no mode checks", 1 if $skip_mode_checks; | |
143 | ||
144 | is($mode & 0777, $newmode, "chmod going through to c"); | |
145 | } | |
a245ea2d | 146 | |
0c5d4ba3 JH |
147 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
148 | $blksize,$blocks) = stat('x'); | |
8d063cd8 | 149 | |
4e51f8e4 SR |
150 | SKIP: { |
151 | skip "no mode checks", 1 if $skip_mode_checks; | |
152 | ||
153 | is($mode & 0777, $newmode, "chmod going through to x"); | |
154 | } | |
0c5d4ba3 JH |
155 | |
156 | is(unlink('b','x'), 2, "unlink two files"); | |
157 | ||
158 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, | |
159 | $blksize,$blocks) = stat('b'); | |
160 | ||
161 | is($ino, undef, "ino of removed file b should be undef"); | |
162 | ||
163 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, | |
164 | $blksize,$blocks) = stat('x'); | |
165 | ||
166 | is($ino, undef, "ino of removed file x should be undef"); | |
8268670f | 167 | } |
0c5d4ba3 | 168 | |
c4aca7d0 GA |
169 | SKIP: { |
170 | skip "no fchmod", 5 unless ($Config{d_fchmod} || "") eq "define"; | |
171 | ok(open(my $fh, "<", "a"), "open a"); | |
172 | is(chmod(0, $fh), 1, "fchmod"); | |
173 | $mode = (stat "a")[2]; | |
174 | is($mode & 0777, 0, "perm reset"); | |
175 | is(chmod($newmode, "a"), 1, "fchmod"); | |
176 | $mode = (stat $fh)[2]; | |
177 | is($mode & 0777, $newmode, "perm restored"); | |
178 | } | |
179 | ||
180 | SKIP: { | |
181 | skip "no fchown", 1 unless ($Config{d_fchown} || "") eq "define"; | |
182 | open(my $fh, "<", "a"); | |
183 | is(chown(-1, -1, $fh), 1, "fchown"); | |
184 | } | |
185 | ||
186 | SKIP: { | |
187 | skip "has fchmod", 1 if ($Config{d_fchmod} || "") eq "define"; | |
188 | open(my $fh, "<", "a"); | |
189 | eval { chmod(0777, $fh); }; | |
190 | like($@, qr/^The fchmod function is unimplemented at/, "fchmod is unimplemented"); | |
191 | } | |
192 | ||
193 | SKIP: { | |
194 | skip "has fchown", 1 if ($Config{d_fchown} || "") eq "define"; | |
195 | open(my $fh, "<", "a"); | |
196 | eval { chown(0, 0, $fh); }; | |
197 | like($@, qr/^The fchown function is unimplemented at/, "fchown is unimplemented"); | |
198 | } | |
199 | ||
8268670f | 200 | is(rename('a','b'), 1, "rename a b"); |
0c5d4ba3 | 201 | |
8268670f JH |
202 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
203 | $blksize,$blocks) = stat('a'); | |
0c5d4ba3 | 204 | |
8268670f | 205 | is($ino, undef, "ino of renamed file a should be undef"); |
0c5d4ba3 JH |
206 | |
207 | $delta = $accurate_timestamps ? 1 : 2; # Granularity of time on the filesystem | |
1d825fcc | 208 | chmod 0777, 'b'; |
a245ea2d | 209 | $foo = (utime 500000000,500000000 + $delta,'b'); |
0c5d4ba3 JH |
210 | |
211 | is($foo, 1, "utime"); | |
212 | ||
8d063cd8 LW |
213 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
214 | $blksize,$blocks) = stat('b'); | |
0c5d4ba3 | 215 | |
20dd405c MS |
216 | SKIP: { |
217 | skip "bogus inode num", 1 if ($^O eq 'MSWin32') || ($^O eq 'NetWare'); | |
218 | ||
219 | ok($ino, 'non-zero inode num'); | |
0c5d4ba3 JH |
220 | } |
221 | ||
20dd405c | 222 | SKIP: { |
3ed9f8f7 | 223 | skip "filesystem atime/mtime granularity too low", 2 |
20dd405c MS |
224 | unless $accurate_timestamps; |
225 | ||
226 | print "# atime - $atime mtime - $mtime delta - $delta\n"; | |
227 | if($atime == 500000000 && $mtime == 500000000 + $delta) { | |
228 | pass('atime'); | |
229 | pass('mtime'); | |
0c5d4ba3 | 230 | } |
20dd405c MS |
231 | else { |
232 | if ($^O =~ /\blinux\b/i) { | |
233 | print "# Maybe stat() cannot get the correct atime, ". | |
234 | "as happens via NFS on linux?\n"; | |
235 | $foo = (utime 400000000,500000000 + 2*$delta,'b'); | |
236 | my ($new_atime, $new_mtime) = (stat('b'))[8,9]; | |
237 | print "# newatime - $new_atime nemtime - $new_mtime\n"; | |
238 | if ($new_atime == $atime && $new_mtime - $mtime == $delta) { | |
3ed9f8f7 NIS |
239 | pass("atime - accounted for possible NFS/glibc2.2 bug on linux"); |
240 | pass("mtime - accounted for possible NFS/glibc2.2 bug on linux"); | |
241 | } | |
20dd405c | 242 | else { |
3ed9f8f7 NIS |
243 | fail("atime - $atime/$new_atime $mtime/$new_mtime"); |
244 | fail("mtime - $atime/$new_atime $mtime/$new_mtime"); | |
20dd405c | 245 | } |
3ed9f8f7 | 246 | } |
20dd405c MS |
247 | elsif ($^O eq 'VMS') { |
248 | # why is this 1 second off? | |
249 | is( $atime, 500000001, 'atime' ); | |
250 | is( $mtime, 500000000 + $delta, 'mtime' ); | |
3ed9f8f7 | 251 | } |
20dd405c MS |
252 | elsif ($^O eq 'beos') { |
253 | SKIP: { skip "atime not updated", 1; } | |
254 | is($mtime, 500000001, 'mtime'); | |
3ed9f8f7 | 255 | } |
20dd405c MS |
256 | else { |
257 | fail("atime"); | |
258 | fail("mtime"); | |
259 | } | |
0c5d4ba3 | 260 | } |
6d738113 | 261 | } |
0c5d4ba3 JH |
262 | |
263 | is(unlink('b'), 1, "unlink b"); | |
264 | ||
8d063cd8 LW |
265 | ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, |
266 | $blksize,$blocks) = stat('b'); | |
0c5d4ba3 | 267 | is($ino, undef, "ino of unlinked file b should be undef"); |
378cc40b LW |
268 | unlink 'c'; |
269 | ||
270 | chdir $wd || die "Can't cd back to $wd"; | |
271 | ||
0c5d4ba3 JH |
272 | # Yet another way to look for links (perhaps those that cannot be |
273 | # created by perl?). Hopefully there is an ls utility in your | |
274 | # %PATH%. N.B. that $^O is 'cygwin' on Cygwin. | |
275 | ||
20dd405c MS |
276 | SKIP: { |
277 | skip "Win32/Netware specific test", 2 | |
278 | unless ($^O eq 'MSWin32') || ($^O eq 'NetWare'); | |
3ed9f8f7 | 279 | skip "No symbolic links found to test with", 2 |
20dd405c MS |
280 | unless `ls -l perl 2>nul` =~ /^l.*->/; |
281 | ||
4ba7095c JH |
282 | system("cp TEST TEST$$"); |
283 | # we have to copy because e.g. GNU grep gets huffy if we have | |
284 | # a symlink forest to another disk (it complains about too many | |
285 | # levels of symbolic links, even if we have only two) | |
0c5d4ba3 | 286 | is(symlink("TEST$$","c"), 1, "symlink"); |
4ba7095c | 287 | $foo = `grep perl c 2>&1`; |
0c5d4ba3 | 288 | ok($foo, "found perl in c"); |
44a8e56a | 289 | unlink 'c'; |
4ba7095c | 290 | unlink("TEST$$"); |
378cc40b | 291 | } |
f783569b | 292 | |
f783569b | 293 | unlink "Iofs.tmp"; |
0c5d4ba3 JH |
294 | open IOFSCOM, ">Iofs.tmp" or die "Could not write IOfs.tmp: $!"; |
295 | print IOFSCOM 'helloworld'; | |
296 | close(IOFSCOM); | |
297 | ||
298 | # TODO: pp_truncate needs to be taught about F_CHSIZE and F_FREESP, | |
299 | # as per UNIX FAQ. | |
300 | ||
301 | SKIP: { | |
63720136 | 302 | # Check truncating a closed file. |
0c5d4ba3 | 303 | eval { truncate "Iofs.tmp", 5; }; |
90ddc76f | 304 | |
090bf15b | 305 | skip("no truncate - $@", 8) if $@; |
0c5d4ba3 JH |
306 | |
307 | is(-s "Iofs.tmp", 5, "truncation to five bytes"); | |
308 | ||
309 | truncate "Iofs.tmp", 0; | |
310 | ||
311 | ok(-z "Iofs.tmp", "truncation to zero bytes"); | |
312 | ||
7a2cf369 NK |
313 | #these steps are necessary to check if file is really truncated |
314 | #On Win95, FH is updated, but file properties aren't | |
0c5d4ba3 | 315 | open(FH, ">Iofs.tmp") or die "Can't create Iofs.tmp"; |
7a2cf369 NK |
316 | print FH "x\n" x 200; |
317 | close FH; | |
318 | ||
63720136 PG |
319 | # Check truncating an open file. |
320 | open(FH, ">>Iofs.tmp") or die "Can't open Iofs.tmp for appending"; | |
0c5d4ba3 JH |
321 | |
322 | binmode FH; | |
323 | select FH; | |
324 | $| = 1; | |
325 | select STDOUT; | |
326 | ||
327 | { | |
328 | use strict; | |
329 | print FH "x\n" x 200; | |
330 | ok(truncate(FH, 200), "fh resize to 200"); | |
62b86938 | 331 | } |
0c5d4ba3 JH |
332 | |
333 | if ($needs_fh_reopen) { | |
334 | close (FH); open (FH, ">>Iofs.tmp") or die "Can't reopen Iofs.tmp"; | |
335 | } | |
90ddc76f | 336 | |
090bf15b SR |
337 | SKIP: { |
338 | if ($^O eq 'vos') { | |
339 | skip ("# TODO - hit VOS bug posix-973 - cannot resize an open file below the current file pos.", 5); | |
340 | } | |
0c5d4ba3 | 341 | |
090bf15b | 342 | is(-s "Iofs.tmp", 200, "fh resize to 200 working (filename check)"); |
63720136 | 343 | |
090bf15b | 344 | ok(truncate(FH, 0), "fh resize to zero"); |
0c5d4ba3 | 345 | |
090bf15b SR |
346 | if ($needs_fh_reopen) { |
347 | close (FH); open (FH, ">>Iofs.tmp") or die "Can't reopen Iofs.tmp"; | |
348 | } | |
0c5d4ba3 | 349 | |
090bf15b | 350 | ok(-z "Iofs.tmp", "fh resize to zero working (filename check)"); |
7a2cf369 | 351 | |
090bf15b SR |
352 | close FH; |
353 | ||
354 | open(FH, ">>Iofs.tmp") or die "Can't open Iofs.tmp for appending"; | |
355 | ||
356 | binmode FH; | |
357 | select FH; | |
358 | $| = 1; | |
359 | select STDOUT; | |
360 | ||
361 | { | |
362 | use strict; | |
363 | print FH "x\n" x 200; | |
364 | ok(truncate(*FH{IO}, 100), "fh resize by IO slot"); | |
365 | } | |
366 | ||
367 | if ($needs_fh_reopen) { | |
368 | close (FH); open (FH, ">>Iofs.tmp") or die "Can't reopen Iofs.tmp"; | |
369 | } | |
370 | ||
371 | is(-s "Iofs.tmp", 100, "fh resize by IO slot working"); | |
372 | ||
373 | close FH; | |
374 | } | |
f783569b | 375 | } |
80252599 | 376 | |
65cb15a1 | 377 | # check if rename() can be used to just change case of filename |
20dd405c MS |
378 | SKIP: { |
379 | skip "Works in Cygwin only if check_case is set to relaxed", 1 | |
380 | if $^O eq 'cygwin'; | |
381 | ||
0c5d4ba3 JH |
382 | chdir './tmp'; |
383 | open(fh,'>x') || die "Can't create x"; | |
384 | close(fh); | |
385 | rename('x', 'X'); | |
3ed9f8f7 | 386 | |
0c5d4ba3 JH |
387 | # this works on win32 only, because fs isn't casesensitive |
388 | ok(-e 'X', "rename working"); | |
8268670f | 389 | |
20dd405c | 390 | 1 while unlink 'X'; |
0c5d4ba3 | 391 | chdir $wd || die "Can't cd back to $wd"; |
73077d53 | 392 | } |
65cb15a1 | 393 | |
80252599 | 394 | # check if rename() works on directories |
0c5d4ba3 | 395 | if ($^O eq 'VMS') { |
9df548ee CB |
396 | # must have delete access to rename a directory |
397 | `set file tmp.dir/protection=o:d`; | |
20dd405c MS |
398 | ok(rename('tmp.dir', 'tmp1.dir'), "rename on directories") || |
399 | print "# errno: $!\n"; | |
0c5d4ba3 JH |
400 | } else { |
401 | ok(rename('tmp', 'tmp1'), "rename on directories"); | |
6d738113 | 402 | } |
0c5d4ba3 JH |
403 | |
404 | ok(-d 'tmp1', "rename on directories working"); | |
80252599 | 405 | |
73077d53 | 406 | # need to remove 'tmp' if rename() in test 28 failed! |
4e7ee149 | 407 | END { rmdir 'tmp1'; rmdir 'tmp'; 1 while unlink "Iofs.tmp"; } |