win9x - how to test if a file is open?

P

perl coder

I need to access files in a sane state in a win9x environment, but I
can't control when other processes (not my code!) will open/write to
those files. I guess the only way to be sure is to kill all other
running processes, but that's not an option! I think the next best
thing is to check if the file is open, and if so to wait.

Any modules or nifty hacks for this? I noticed that a lot of the more
interesting Win32 modules are for NT only. :-(
 
M

Matt Garrish

perl coder said:
I need to access files in a sane state in a win9x environment, but I
can't control when other processes (not my code!) will open/write to
those files. I guess the only way to be sure is to kill all other
running processes, but that's not an option! I think the next best
thing is to check if the file is open, and if so to wait.

How's that going to help you, though? There is no file locking capability in
the win9x versions, so waiting until one process is finished with the file
will do nothing to prevent another from accessing it at the same time as
your script.

The only option I can think of off the top of my head is to implement your
own file locking, if that's possible. If you can modify the code in the
other processes (or how they're invoked), you could write a lock file to a
temp directory that the other processes have to wait on before they can
access the file (but even then you may run into a race condition depending
on how many processes are trying to grab that lock when it comes free).

Even on NT there isn't true file locking. Your Perl scripts may all obey a
lock, but there's nothing stopping another process from reading or writing
to the file. Just one of the joys of scripting on Winblows boxes... : )

Matt
 
P

perl coder

Matt Garrish said:
How's that going to help you, though? There is no file locking capability in
the win9x versions, so waiting until one process is finished with the file
will do nothing to prevent another from accessing it at the same time as
your script.

There's no working flock(), but I found a way to lock files using the
Win32::API::prototype module and the win32 CreateFile() function. This
method works on win98 (it also should on NT/2K/XP, but I didn't try):

# lockfile.pl
use strict;
use Win32::API::prototype;

my $file = 'c:/autoexec.bat';

# accessMode flags
my $GENERIC_READ = 0x80000000;
my $GENERIC_WRITE = 0x40000000;
# shareMode flags
my $FILE_SHARE_READ = 0x00000001; # or just use 0 for exclusive lock
# create flags
my $OPEN_EXISTING = 3;

ApiLink( 'kernel32.dll', 'HANDLE CreateFile(
LPCTSTR name,
DWORD accessMode,
DWORD shareMode,
LPSECURITY_ATTRIBUTES securityAttributes,
DWORD create,
DWORD attributes,
HANDLE templateFile)'
) or die $^E;

print "Calling CreateFile to lock $file ... \n";
CreateFile($file, $GENERIC_READ|$GENERIC_WRITE, 0, 0, $OPEN_EXISTING, 0, 0)
or die $^E;
sleep 9999;
# now try:
# 1. "type c:\autoexec.bat" -> it works
# 2. "echo test >> c:\autoexec.bat" -> it fails

Is there any disadvantage to this method? It seems to allow any
combination of shared/exclusive read/write locking at the kernel level.
So if I lock a file with shareMode FILE_SHARED_READ, I can be certain no
other process can write to the file. For my purposes, this is better
protection than flock() offers (which is purely advisory in nature).

There's one thing missing though: I still need to be able to tell if a
file is already open by another process before I try to lock it. I
wouldn't want to (for example) get an exclusive lock on a file someone
is in the process of downloading with I.E. or some FTP program... And
although you might think that's not possible, I trid this:

1. vim c:\autoexec.bat
2. perl lockfile.pl
3. (vim) append a line at the end of the file, and try to save

Step 3 fails, and Vim gives me an error ("Can't open file for writing").
And that's right. But I don't want to lock the file if Vim already has
it open. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,146
Messages
2,570,832
Members
47,374
Latest member
anuragag27

Latest Threads

Top