in reply to Re^5: File::Spec::Win32 returning different result than File::Spec when doing catfile with empty string
in thread File::Spec::Win32 returning different result than File::Spec when doing catfile with empty string

Fun...

Not fun, broken design.

does $File::Spec::ISA[0] eq 'File::Spec::Unix' work reliably, then?

Have a look at the source code:

package File::Spec; use strict; our $VERSION = '3.75'; $VERSION =~ tr/_//d; my %module = ( MSWin32 => 'Win32', os2 => 'OS2', VMS => 'VMS', NetWare => 'Win32', # Yes, File::Spec::Win32 works on Ne +tWare. symbian => 'Win32', # Yes, File::Spec::Win32 works on sy +mbian. dos => 'OS2', # Yes, File::Spec::OS2 works on DJGP +P. cygwin => 'Cygwin', amigaos => 'AmigaOS'); my $module = $module{$^O} || 'Unix'; require "File/Spec/$module.pm"; our @ISA = ("File::Spec::$module"); 1;

On all operating systems not listed in %module, File::Spec will inherit from File::Spec::Unix.

Should be right very often. But are all non-Unix operating systems perl runs on listed in %modules? If not, File::Spec is even more broken than I tought.

If you run Cygwin, you should be able to use case sensitive Unix-style paths. But if you run Cygwin, File::Spec will inherit from File::Spec::Cygwin (which inherits from File::Spec::Unix). At this point, $File::Spec::ISA[0] ne 'File::Spec::Unix'. Fail.

And exactly at this point, it depends on the path that you use if the path is case sensitive or not. See File::Spec->case_tolerant() is broken, especially the Cygwin part.

Apart from that, you should not mess with other modules' interna. Perl will let you do that, but you should not:

Perl does not enforce private and public parts of its modules as you may have been used to in other languages like C++, Ada, or Modula-17. Perl doesn't have an infatuation with enforced privacy. It would prefer that you stayed out of its living room because you weren't invited, not because it has a shotgun.

The module and its user have a contract, part of which is common law, and part of which is "written". Part of the common law contract is that a module doesn't pollute any namespace it wasn't asked to. The written contract for the module (A.K.A. documentation) may make other provisions. But then you know when you use RedefineTheWorld that you're redefining the world and willing to take the consequences.

(perlmodlib)

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
  • Comment on Re^6: File::Spec::Win32 returning different result than File::Spec when doing catfile with empty string
  • Select or Download Code

Replies are listed 'Best First'.
Re^7: File::Spec::Win32 returning different result than File::Spec when doing catfile with empty string
by jcb (Parson) on Sep 09, 2019 at 23:06 UTC

    In my case, the concern is detecting whether inode numbers are valid (and hardlinks might exist) or not (and filenames are assumed to map 1:1 to files) rather than vagaries like case-sensitivity that can only really be verified by specific testing in the directory you want to know about.

    I asked this at Portable way to determine if two names refer to the same file? and arrived at the "check which implementation of File::Spec is in use" solution there.

    If inode numbers are not valid, will plainly different files appear to have the same inode number according to stat? In that case, how do I find the path a module was loaded from? I could stat two modules from the library and make sure they have different inodes...

Re^7: File::Spec::Win32 returning different result than File::Spec when doing catfile with empty string
by jcb (Parson) on Sep 11, 2019 at 03:18 UTC

    While I would argue that the inheritance tree of File::Spec is not an internal detail because it is documented, you are right: File::Spec is intended for filename handling, and checking the style of filenames in use does not reliably identify *nix systems because several Perl ports translate Unix-style filenames to the native format.

    For the release that I am calling "alpha-5" for short, I am using this code:

    BEGIN { use constant (); my $have_valid_inodes = 0; # We accept DEV:INO as valid if two files in the same directory have + the # same DEV and different INO values. We use two modules from this # library for this test and retrieve their actual locations from %I +NC. my @stat_record = stat $INC{'WARC/Record.pm'}; my @stat_volume = stat $INC{'WARC/Volume.pm'}; $have_valid_inodes = 1 if (scalar @stat_record && scalar @stat_volume # both stat calls w +orked && $stat_record[0] == $stat_volume[0] # both have same DEV && $stat_record[1] != $stat_volume[1]); # different INO valu +es constant->import(HAVE_VALID_INODES => $have_valid_inodes); }

    What makes this particularly "interesting" is that all of the CPAN smoketest boxes seem to be running various *nix systems.

Re^7: File::Spec::Win32 returning different result than File::Spec when doing catfile with empty string
by Your Mother (Archbishop) on Sep 09, 2019 at 20:05 UTC

    Side bar: “Fun” in this usage/context is meant ironically/facetiously and as an idiom is more equivalent to “that’s fscking awful.”