entropy has asked for the wisdom of the Perl Monks concerning the following question:

I am completely stumped on this one...
I am running ActiveState perl (which I guess has a broken flock function, among other problems). I need my program to interface with another, by opening for reading a file that the other program opens for writing. My problem is that when my program tries to open the file, it fails saying the file is already in use. Now, the other program, which is writing to the file, is supposed to be designed in such a way so as to allow other programs to read from the file.
It seems to me that Windoze should allow me to open a file for reading no matter what. It's not like my prog is going to mess it up just reading from it... and there are other programs that are supposed to read that file just fine.
To make matters a nightmare, I don't even have a copy of the program I am trying to interface with (and the company won't send me one). From here, all I can do is make a sample script that opens a file for writing and locks it.
So, I guess my question is:
1. If this program I am interfacing to does not lock the file, then why can't perl open it?
2. If they do lock it, then how do other programs open it?

Replies are listed 'Best First'.
Re: Opening a locked file for reading
by clintp (Curate) on Sep 28, 2001 at 07:08 UTC
    This is from my best recollection, so you'll have to bear with me. Is this Windows NT or Windows 95/98/ME?

    If it's NT, then the behavior is somewhat sane, one writer and multiple readers of a file shouldn't be a problem. Beware of buffering and all that stuff.

    I suspect from your "broken flock" statement that you're not using Windows NT. (Psst! flock() isn't broken, it's just not implemented on Win 95/98/ME, read on for why!)

    With 95/98/ME it's a little different. When you open a file for writing, you've effectively locked everyone else out -- for writing, reading or whatever. That's the OS. This isn't Perl's fault. The flock() function doesn't work there, because it really doesn't need to.

    The solution is, get a real OS. :)

(tye)Re: Opening a locked file for reading
by tye (Sage) on Sep 28, 2001 at 20:42 UTC

    See createFile() and CreateFile() from Win32API::File for more information on much of this.

    In Win32, when you open a file you have to specify what type of sharing you want to allow. For C programs that use open() or fopen(), the default is to allow read- and write-sharing but not delete-sharing (note that delete-sharing is ignored prior to WinNT).

    If you use Win32's CreateFile(), then you have to specify the type of sharing allowed. Unfortunately, it is very easy to go "Um, 'sharing'? What am I supposed to pass in there? Ah, '0' works, so I'll just do that since I don't want to spend time trying to figure that out." And '0' means "no sharing". So a lot of Win32 programs end up not allowing any sharing of the files that they open.

    Now, if you open a file and don't specify that read-sharing is allowed, then any other open against that file that requests read access will fail (and your open will fail if the file is already open for read access). Similar for write-sharing and write access.

    So if you can't read the file, then it (probably) was opened w/o allowing read-sharing (or you could be trying to open it w/o allowing some for of sharing, but that seems unlikely given the C RTL defaults that are also used by Perl). If that is the case, then nothing can open the file for read-sharing.

    I'd had hoped that (under WinNT and later) a program that has a special privilege designated for making backups would be able to override this, but testing shows otherwise:

    #!/usr/bin/perl -w use strict; use Win32API::Registry qw( AllowPriv ); use Win32API::File qw( createFile FILE_FLAG_BACKUP_SEMANTICS OsFHandleOpen ); AllowPriv( "SeBackupPrivilege", 1 ) or warn "Can't enable 'backup' privilege: $^E\n"; my $h= createFile( "lockedFile.txt", "re", "rwd", { Flags => FILE_FLAG_BACKUP_SEMANTICS() } ) or die "Can't read lockedFile.txt: $^E\n"; OsFHandleOpen( \*FILE, $h, "r" ) or die "Can't open FILE handle: $! ($^E)\n"; while(<FILE>) { print; }

    So it looks to me like this program you are using is "broken" in this respect and there is no work-around other than modifying that program. ):

            - tye (but my friends call me "Tye")
Re: Opening a locked file for reading
by dws (Chancellor) on Sep 29, 2001 at 06:04 UTC
    I am running ActiveState perl (which I guess has a broken flock function, among other problems). ... My problem is that when my program tries to open the file, it fails saying the file is already in use.

    If anyone who has read this thread is still unclear on what this has to do with flock, the answer is "nothing", though it's an understandable confusion. File locking via flock is advisory. Programs can cheerfully choice to ignore it (or, more likely, can fail out of ignorance to adhere to the advisory locking protocol). Yes, flock doesn't work on Win9x/WinME, but that, as clintp points out above is a separate issue.

Re: Opening a locked file for reading
by ralphie (Friar) on Sep 28, 2001 at 17:26 UTC
    are you opening the file locally, or across the network?
Re: Opening a locked file for reading
by archen (Pilgrim) on Sep 28, 2001 at 17:31 UTC
    you might also try some other work arounds. I'm no expert, but maybe give this a try: use the system to copy the file to a new file, then read the copy. You might also give command line redirection a try, but that in itself is pretty quirky in DOS.
Re: Opening a locked file for reading
by alien_life_form (Pilgrim) on Sep 28, 2001 at 22:21 UTC
    Greetings.

    If in desperation, you can export the drive where your file is, "net use" the share to some free drive letter (meaning, mount the share on a drive) and then try to have your way with the file.
    This does often work on NT (but reportedly fails on Win2k) - and I have used it often times yo snidely replace locked copies of system dlls (kids, do not try this at home - i thrashed ad least one machine with this trick...)
    Not the cleanest approach, but ehi.

    Cheers, alf

Re: Opening a locked file for reading
by entropy (Sexton) on Sep 29, 2001 at 00:51 UTC
    Thank you everyone!
    I am using Win2k at work, but I don't know the OS of my client (it would have to work on any WinOS though).
    I have just discovered that perhaps there was a different file that we should have opened instead... and that file is shared.
    It still seems strange to me that the OS won't let you open any file for reading, locked or not... The manpages say that caring about locks is voluntary in Unix (for better or for worse...)