NAME

Win32::SharedFileOpen - Open a file for shared reading and/or writing

SYNOPSIS

use Win32::SharedFileOpen;

# Open files for reading, denying write access to other processes.
fsopen(FH1, 'one.txt', 'r', SH_DENYWR) or
		die "Cannot read 'one.txt' and take write-lock: $^E\n";
sopen(FH2, 'two.txt', O_RDONLY, SH_DENYWR) or
		die "Cannot read 'two.txt' and take write-lock: $^E\n";

# Open files for writing, denying read and write access to other processes.
fsopen(FH3, 'three.txt', 'w', SH_DENYRW) or
		die "Cannot write 'three.txt' and take read/write-lock: $^E\n";
sopen(FH4, 'four.txt', O_WRONLY | O_CREAT | O_TRUNC, SH_DENYRW, S_IWRITE) or
		die "Cannot write 'four.txt' and take read/write-lock: $^E\n";

WARNING

*************************************************************************
* The fsopen() function in this module currently has a bug which causes *
* it to waste a filehandle every time it is called. Until this issue is *
* resolved, the sopen() function should generally be used instead.      *
* See the file WARNING-FSOPEN.TXT in the original distribution archive, *
* Win32-SharedFileOpen-2.00.tar.gz, for more details.                   *
*************************************************************************

COMPATIBILITY

Prior to version 2.00 of this module, fsopen() and sopen() both created a filehandle and returned it to the caller. (undef was returned instead on failure.)

As of version 2.00 of this module, the arguments and return values of these two functions now more closely resemble those of the Perl built-in functions open() and sysopen(). Specifically, they now both expect a filehandle or an indirect filehandle as their first argument and they both return a boolean value to indicate success or failure.

THIS IS AN INCOMPATIBLE CHANGE. EXISTING SOFTWARE THAT USES THESE FUNCTIONS WILL NEED TO BE MODIFIED.

DESCRIPTION

This module provides a Perl interface to the Microsoft Visual C functions _fsopen() and _sopen(). These functions are counterparts to the standard C library functions fopen(3) and open(2) respectively (which are already effectively available in Perl as open() and sysopen() respectively), but are intended for use when opening a file for subsequent shared reading and/or writing.

The _fsopen() function, like fopen(3), takes a file and a "mode string" (e.g. 'r' and 'w') as arguments and opens the file as a stream, returning a pointer to a FILE structure, while _sopen(), like open(2), takes an "oflag" (e.g. O_RDONLY and O_WRONLY) instead of the "mode string" and returns an int file descriptor (which the Microsoft documentation confusingly refers to as a C run-time "file handle", not to be confused here with a Perl "filehandle" (or indeed with the operating-system "file handle" returned by the CreateFile() function!)). The _sopen() and open(2) functions also take another, optional, "pmode" argument (e.g. S_IREAD and S_IWRITE) specifying the permission settings of the file if it has just been created.

The difference between the Microsoft-specific functions and their standard counterparts is that the Microsoft-specific functions also take an extra "shflag" argument (e.g. SH_DENYRD and SH_DENYWR) which specifies how to prepare the file for subsequent shared reading and/or writing. This flag can be used to specify that either, both or neither of read access and write access will be denied to other processes sharing the file.

This share access control is thus effectively a form a file-locking which, unlike flock(3) and lockf(3) and their corresponding Perl function flock(), is mandatory rather than just advisory. This means that if, for example, you "deny read access" to the file that you have opened then no other process will be able to read that file while you still have it open, whether or not they are playing the same ball game as you. They cannot gain read access to it by simply not honouring the same file opening/locking scheme as you.

This module provides straightforward Perl "wrapper" functions, fsopen() and sopen(), for both of these Microsoft Visual C functions (with the leading "_" character removed from their names). These Perl functions maintain the same formal parameters as the original C functions, except for the addition of an initial filehandle parameter like the Perl built-in functions open() and sysopen() have. This is used to make the Perl filehandle opened available to the caller (rather than using the functions' return values, which are now simple Booleans to indicate success or failure).

The value passed to the functions in this first parameter can be a straight-forward filehandle (FH) or any of the following: a typeglob (either a named typeglob like *FH, or an anonymous typeglob (e.g. from Symbol::gensym()) in a scalar variable); a reference to a typeglob (either a hard reference like \*FH, or a name like 'FH' to be used as a symbolic reference to a typeglob in the caller's package); or a suitable IO object (e.g. an instance of IO::Handle, IO::File or FileHandle). These functions, however, do not have the ability of open() and sysopen() to auto-vivify the undefined scalar value into something that can be used as a filehandle, so calls like "fsopen(my $fh, ...)" will croak() with a message to this effect.

The "oflags" and "shflags", as well as the "pmode" flags used by _sopen(), are all made available to Perl by this module, and are all exported by default. Clearly this module will only build using Microsoft Visual C, so only the flags known to that system [as of version 6.0] are exported, rather than re-exporting all of the O_* and S_I* flags from the Fcntl module like, for example, IO::File does. In any case, Fcntl does not know about the Microsoft-specific _O_SHORT_LIVED flag, nor any of the _SH_* flags. These Microsoft-specific flags are exported (like the _fsopen() and _sopen() functions themselves) without the leading "_" character.

Functions

fsopen($fh, $file, $mode, $shflag)

Opens the file $file using the filehandle (or indirect filehandle) $fh in the access mode specified by $mode and prepares the file for subsequent shared reading and/or writing as specified by $shflag.

Returns a non-zero value if the file was successfully opened, or returns undef and sets $! and/or $^E if the file could not be opened.

sopen($fh, $file, $oflag, $shflag[, $pmode])

Opens the file $file using the filehandle (or indirect filehandle) $fh in the access mode specified by $oflag and prepares the file for subsequent shared reading and/or writing as specified by $shflag. The optional $pmode argument specifies the file's permission settings if the file has just been created; it is only required when the access mode includes O_CREAT.

Returns a non-zero value if the file was successfully opened, or returns undef and sets $! and/or $^E if the file could not be opened.

Filehandles and Indirect Filehandles

The fsopen() and sopen() functions both expect either a filehandle or an indirect filehandle as their first argument.

Using a filehandle:

fsopen(FH, 'file.txt', 'r', SH_DENYWR) or
	die "Can't read 'file.txt': $!\n";

is the simplest approach, but filehandles have a big drawback: they are global in scope so they are always in danger of clobbering a filehandle of the same name being used elsewhere. For example, consider this:

fsopen(FH, 'file1.txt', 'r', SH_DENYWR) or
	die "Can't read 'file1.txt': $!\n";

while (<FH>) {
	chomp($line = $_);
	my_sub($line);
}

...

close FH;

sub my_sub($) {
	fsopen(FH, 'file2.txt', 'r', SH_DENYWR) or
		die "Can't read 'file2.txt': $!\n";
	...
	close FH;
}

The problem here is that when you open a filehandle that is already open it is closed first, so calling "fsopen(FH, ...)" in my_sub() causes the filehandle FH which is already open in the caller to be closed first so that my_sub() can use it. When my_sub() returns the caller will now find that FH is closed, causing the next read in the while { ... } loop to fail. (Or even worse, the caller would end up mistakenly reading from the wrong file if my_sub() hadn't closed FH before returning!)

One solution to this problem is to localise the typeglob of the filehandle in question within my_sub():

sub my_sub($) {
	local *FH;
	fsopen(FH, 'file2.txt', 'r', SH_DENYWR) or
		die "Can't read 'file2.txt': $!\n";
	...
	close FH;
}

but this has the unfortunate side-effect of localising all the other members of that typeglob as well, so if the caller had global variables $FH, @FH or %FH, or even a subroutine FH(), which my_sub() needed then it no longer has access to them either. (It does, on the other hand, have the rather nicer side-effect that the filehandle is automatically closed when the localised typeglob goes out of scope, so the "close FH;" above is no longer necessary.)

This problem can also be addressed by using the so-called *foo{THING} syntax. *foo{THING} returns a reference to the THING member of the *foo typeglob. For example, *foo{SCALAR} is equivalent to \$foo, and *foo{CODE} is equivalent to \&foo. *foo{IO} (or the older, now out-of-fashion notation *foo{FILEHANDLE}) yields the actual internal IO::Handle object that the *foo typeglob contains, so with this we can localise just the IO object, not the whole typeglob, so that we don't accidentally hide more than we meant to:

sub my_sub($) {
	local *FH{IO};
	fsopen(FH, 'file2.txt', 'r', SH_DENYWR) or
		die "Can't read 'file2.txt': $!\n";
	...
	close FH;	# As in the example above, this is also not necessary
}

However, this has a drawback as well: *FH{IO} only works if FH has already been used as a filehandle (or some other IO handle), because *foo{THING} returns undef if that particular THING hasn't been seen by the compiler yet (with the exception of when THING is SCALAR, which is treated differently). This is fine in the example above, but would not necessarily have been if the caller of my_sub() hadn't used the filehandle FH first, so this approach would be no good if my_sub() was to be put in a module to be used by other callers too.

The answer to all of these problems is to use so-called indirect filehandles instead of "normal" filehandles. An indirect filehandle is anything other than a symbol being used in a place where a filehandle is expected, i.e. an expression that evaluates to something that can be used as a filehandle, namely:

A string

A name like 'FH' to be used as a symbolic reference to the typeglob whose IO member is to be used as the filehandle.

A typeglob

Either a named typeglob like *FH, or an anonymous typeglob in a scalar variable (e.g. from Symbol::gensym()), whose IO member is to be used as the filehandle.

A reference to a typeglob

Either a hard reference like \*FH, or a symbolic reference as in the first case above, to a typeglob whose IO member is to be used as the filehandle.

A suitable IO object

Either the IO member of a typeglob obtained via the *foo{IO} syntax, or an instance of IO::Handle, or of IO::File or FileHandle (which are both just sub-classes of IO::Handle).

Of course, typeglobs are global in scope just like filehandles are, so if a named typeglob, a reference (hard or symbolic) to a named typeglob or the IO member of a named typeglob is used then we run into the same scoping problems that we saw above with filehandles. The remainder of the above, however, (namely, an anonymous typeglob in a scalar variable, or a suitable IO object) finally give us the answer that we have been looking for.

So we can now write my_sub() like this:

sub my_sub($) {
	# Create "my $fh" here: see below
	fsopen($fh, 'file2.txt', 'r', SH_DENYWR) or
		die "Can't read 'file2.txt': $!\n";
	...
	close $fh;		# Not necessary again
}

where any of the following may be used to create "my $fh":

use Symbol;
my $fh = gensym();

use IO::Handle;
my $fh = IO::Handle->new();

use IO::File;
my $fh = IO::File->new();

use FileHandle;
my $fh = FileHandle->new();

As we have noted in the code segment above, the "close $fh;" is once again not necessary: the filehandle is closed automatically when the lexical variable $fh is destroyed, i.e. when it goes out of scope (assuming there are no other references to it).

However, there is still another point to bear in mind regarding the four solutions shown above: they all load a good number of extra lines of code into your program that might not otherwise be made use of. Note that FileHandle is a sub-class of IO::File, which is in turn a sub-class of IO::Handle, so using either of those sub-classes is particularly wasteful in this respect unless the methods provided by them are going to be put to use. Even the IO::Handle class still loads a number of other modules, including Symbol, so using the Symbol module is certainly the best bet here if none of the IO::Handle methods are required.

Finally, there is another way to get an anonymous typeglob in a scalar variable which is even leaner and meaner than using Symbol::gensym(): the "First-Class Filehandle Trick". It is described in an article by Mark-Jason Dominus called "Seven Useful Uses of Local" which first appeared in The Perl Journal, and can also be found (at the time of writing) on his website at the URL http://perl.plover.com/local.html. It consists simply of the following:

my $fh = do { local *FH };

It works like this: the do { ... } block simply executes the commands within the block and returns the value of the last one. So in this case, the global *FH typeglob is temporarily replaced with a new glob that is local() to the do { ... } block. The new, local(), *FH typeglob then goes out of scope (i.e. is no longer accessible by that name) but is not destroyed because it gets returned from the do { ... } block. It is this, now anonymous, typeglob that gets assigned to "my $fh", exactly as we wanted.

If this trick is used only once within a program running under "use warnings;" that doesn't mention *FH or any of its members anywhere else then a warning like the following will be produced:

Name "main::FH" used only once: possible typo at ...

This can be easily avoided by turning off that warning within the do { ... } block:

my $fh = do { no warnings 'once'; local *FH };

Note that all of the above discussion of filehandles and indirect filehandles applies equally to Perl's built-in open() and sysopen() functions. It should also be noted that those two functions both support one other form of indirect filehandle that this module's fsopen() and sopen() functions do not: the undefined value. The calls

open my $fh, 'file.txt';
sysopen my $fh, 'file.txt', O_RDONLY;

each auto-vivify "my $fh" into something that can be used as an indirect filehandle. (In fact, they currently auto-vivify an entire typeglob, but this may change in a future version of Perl to only auto-vivify the IO member.) Any attempt to do likewise with this module's functions:

fsopen(my $fh, 'file.txt', 'r', SH_DENYNO);
sopen(my $fh, 'file.txt', O_RDONLY, SH_DENYNO);

causes the functions to croak().

Mode Strings

The $mode argument in fsopen() specifies the type of access requested for the file, as follows:

'r'

Opens the file for reading only. Fails if the file does not already exist.

'w'

Opens the file for writing only. Creates the file if it does not already exist; destroys the contents of the file if it does already exist.

'a'

Opens the file for appending only. Creates the file if it does not already exist.

'r+'

Opens the file for both reading and writing. Fails if the file does not already exist.

'w+'

Opens the file for both reading and writing. Creates the file if it does not already exist; destroys the contents of the file if it does already exist.

'a+'

Opens the file for both reading and appending. Creates the file if it does not already exist.

When the file is opened for appending the file pointer is always forced to the end of the file before any write operation is performed.

The following table shows the equivalent combination of "O_* Flags" for each mode string:

+------+-------------------------------+
| 'r'  | O_RDONLY                      |
+------+-------------------------------+
| 'w'  | O_WRONLY | O_CREAT | O_TRUNC  |
+------+-------------------------------+
| 'a'  | O_WRONLY | O_CREAT | O_APPEND |
+------+-------------------------------+
| 'r+' | O_RDWR                        |
+------+-------------------------------+
| 'w+' | O_RDWR | O_CREAT | O_TRUNC    |
+------+-------------------------------+
| 'a+' | O_RDWR | O_CREAT | O_APPEND   |
+------+-------------------------------+

See also "Text and Binary Modes".

O_* Flags

The $oflag argument in sopen() specifies the type of access requested for the file, as follows:

O_RDONLY

Opens the file for reading only.

O_WRONLY

Opens the file for writing only.

O_RDWR

Opens the file for both reading and writing.

Exactly one of the above flags must be used to specify the file access mode: there is no default value. In addition, the following flags may also be used in bitwise-OR combination:

O_APPEND

The file pointer is always forced to the end of the file before any write operation is performed.

O_CREAT

Creates the file if it does not already exist. (Has no effect if the file does already exist.) The $pmode argument is required if (and only if) this flag is used.

O_EXCL

Fails if the file already exists. Only applies when used with O_CREAT.

O_NOINHERIT

Prevents creation of a shared file descriptor.

O_RANDOM

Specifies the disk access will be primarily random.

O_SEQUENTIAL

Specifies the disk access will be primarily sequential.

O_SHORT_LIVED

Used with O_CREAT, creates the file such that, if possible, it does not flush the file to disk.

O_TEMPORARY

Used with O_CREAT, creates the file as temporary. The file will be deleted when the last file descriptor attached to it is closed.

O_TRUNC

Truncates the file to zero length, destroying the contents of the file, if it already exists. Cannot be specified with O_RDONLY, and the file must have write permission.

See also "Text and Binary Modes".

Text and Binary Modes

Both fsopen() and sopen() calls can specify whether the file should be opened in text (translated) mode or binary (untranslated) mode.

If the file is opened in text mode then on input carriage return-linefeed (CR-LF) pairs are translated to single linefeed (LF) characters and Ctrl+Z is interpreted as end-of-file (EOF), while on output linefeed (LF) characters are translated to carriage return-linefeed (CR-LF) pairs.

These translations are not performed if the file is opened in binary mode.

If neither mode is specified then text mode is assumed by default, as is usual for Perl filehandles. Binary mode can still be enabled after the file has been opened (but only before any I/O has been performed on it) by calling binmode() in the usual way.

't'
'b'

Text/binary modes are specified for fsopen() by inserting a 't' or a 'b' respectively into the $mode string, immediately following the 'r', 'w' or 'a', for example:

my $fh = fsopen($file, 'wt', SH_DENYNO);
O_TEXT
O_BINARY

Text/binary modes are specified for sopen() by using O_TEXT or O_BINARY respectively in bitwise-OR combination with other O_* flags in the $oflag argument, for example:

my $fh = sopen($file, O_WRONLY | O_TEXT, SH_DENYNO);

SH_* Flags

The $shflag argument in both fsopen() and sopen() specifies the type of sharing access permitted for the file, as follows:

SH_DENYNO

Permits both read and write access to the file.

SH_DENYRD

Denies read access to the file; write access is permitted.

SH_DENYWR

Denies write access to the file; read access is permitted.

SH_DENYRW

Denies both read and write access to the file.

S_I* Flags

The $pmode argument in sopen() is required if and only if the access mode, $oflag, includes O_CREAT. If the file does not already exist then $pmode specifies the file's permission settings, which are set the first time the file is closed. (It has no effect if the file already exists.) The value is specified as follows:

S_IREAD

Permits reading.

S_IWRITE

Permits writing.

Note that it is evidently not possible to deny read permission, so S_IWRITE and S_IREAD | S_IWRITE are equivalent.

Variables

$Debug

Boolean debug setting. Default value is 0.

Setting this variable to a true value will cause debug information to be emitted (via a straight-forward print() on STDERR).

DIAGNOSTICS

Warnings and Error Messages

The following diagnostic messages may be produced by this module. They are classified as follows (a la perldiag):

(W) A warning
(F) A fatal error
(I) An internal error that you should never see
%s() can't close file descriptor %d: %s

(W) The specified function called the corresponding Microsoft Visual C function which successfully opened the file, acquiring a new file descriptor in the proces, but the Perl function was then unable to attach a Perl filehandle to that new file descriptor. To prevent the file descriptor being wasted, and the file being left open, the Perl function then attempted to close this new file descriptor, but was unable to do so. The system error message set in $! is also given.

%s() can't use the undefined value as an indirect filehandle

(F) The specified function was passed the undefined value as the first argument. That is not a filehandle, cannot be used as an indirect filehandle, and (unlike the Perl built-in functions open() and sysopen()) the function is unable to auto-vivify something that can be used as an indirect filehandle in such a case.

Error generating subroutine '%s()': %s

(F) There was an error generating the specified subroutine (which supplies the value of the corresponding constant). The error set by eval() is also given.

The symbol '%s' is not defined on this system.

(F) The specified symbol is not provided by the C environment used to build this module.

Unexpected error autoloading '%s()': %s

(I) There was an unexpected error looking up the value of the specified constant. The error set by the constant-lookup function is also given.

Unexpected error in autoloader: _constant() is not defined.

(I) There was an unexpected error looking up the value of the specified constant: the constant-lookup function itself is apparently not defined.

Error Values

Both fsopen() and sopen() set the Perl Special Variables $! and/or $^E to values indicating the cause of the error when they fail. The possible values of each are as follows ($! shown first, $^E underneath):

EACCES (Permission denied) [1]
ERROR_ACCESS_DENIED (Access is denied)

The $file is a directory, or is a read-only file and an attempt was made to open it for writing.

EACCES (Permission denied) [2]
ERROR_SHARING_VIOLATION (The process cannot access the file because it is being used by another process.)

The $file cannot be opened because another process already has it open and is denying the requested access mode.

This is, of course, the error that other processes will get when trying to open a file that we have opened with an access mode that we have denied.

EEXIST (File exists)
ERROR_FILE_EXISTS (The file exists)

[sopen() only.] The $oflag included O_CREAT | O_EXCL, and the $file already exists.

EINVAL (Invalid argument)
ERROR_ENVVAR_NOT_FOUND (The system could not find the environment option that was entered)

The $oflag or $shflag argument was invalid.

EMFILE (Too many open files)
ERROR_TOO_MANY_OPEN_FILES (The system cannot open the file)

The maximum number of file descriptors has been reached.

ENOENT (No such file or directory)
ERROR_FILE_NOT_FOUND (The system cannot find the file specified)

The the filename or path in $file was not found.

$! corresponds to the standard C library variable errno, the possible values of which are defined in errno.h. $^E corresponds to the Microsoft C "last-error code", the possible values of which are defined in winerror.h.

The $! errors can be checked for by inspecting the values of the %! hash exported by the Errno module. The error which occurred will have a "true" value in the hash, for example:

use Errno;

if ($!{EACCES}) {
	...
}

The $^E errors can be checked for by comparing against values exported by the Win32::WinError module, for example:

use Win32::WinError;

if ($^E == ERROR_ACCESS_DENIED) {
	...
}

In both cases, the errors should be checked for immediately following the function call that failed because many functions that succeed will reset these variables.

The system error messages for both $! and $^E can be obtained by simply stringifying the special variables, e.g. by print()'ing them:

print "Errno was: $!\n";
print "Last error was: $^E\n";

or, alternatively, the message for $^E can also be obtained (slightly more nicely formatted) by calling FormatMessage() in the Win32 module:

print "Last error was: " . Win32::FormatMessage($^E) . "\n";

The $^E error code itself is also available from a Win32 module function, GetLastError(). Both functions are built-in to Perl itself (on Win32) so do not require a "use Win32;" call.

EXAMPLES

Open a file for reading, denying write access to other processes:
fsopen(FH, $file, 'r', SH_DENYWR) or
		die "Cannot read '$file' and take write-lock: $^E\n";

This example could be used for sharing a file amongst several processes for reading, but protecting the reads from interference by other processes trying to write the file.

Open a file for "update", denying read and write access to other processes:
fsopen(FH, $file, 'r+', SH_DENYRW) or
		die "Cannot update '$file' and take read-write-lock: $^E\n";

This example could be used by a process to both read and write a file (e.g. a simple database) and guard against other processes interfering with the reads or being interefered with by the writes.

Open a file for writing if and only if it doesn't already exist, denying write access to other processes:
sopen(FH, $file, O_WRONLY | O_CREAT | O_EXCL, SH_DENYWR, S_IWRITE) or
		die "Cannot create '$file' and take write-lock: $^E\n";

This example could be used by a process wishing to take an "advisory lock" on some non-file resource that can't be explicitly locked itself by dropping a "sentinel" file somewhere. The test for the non-existence of the file and creation of the file is atomic to avoid a "race condition". The file can be written by the process taking the lock and can be read by other processes to facilitate a "lock discovery" mechanism.

Open a temporary file for "update", denying read and write access to other processes:
sopen(FH, $file, O_RDWR | O_CREAT | O_TRUNC | O_TEMPORARY, SH_DENYRW,
			S_IWRITE) or
		die "Cannot update '$file' and take write-lock: $^E\n";

This example could be used by a process wishing to use a file as a temporary "scratch space" for both reading and writing. The space is protected from the prying eyes of and intereference by other processes, and is deleted when the process that opened it exits, even when dying abnormally.

EXPORTS

The following symbols are or can be exported by this module:

Default Exports

fsopen, sopen,

O_APPEND, O_BINARY, O_CREAT, O_EXCL, O_NOINHERIT, O_RANDOM, O_RDONLY, O_RDWR, O_SEQUENTIAL, O_SHORT_LIVED, O_TEMPORARY, O_TEXT, O_TRUNC, O_WRONLY,

S_IREAD, S_IWRITE,

SH_DENYNO, SH_DENYRD, SH_DENYRW, SH_DENYWR

Optional Exports

None

Export Tags
:oflags

O_APPEND, O_BINARY, O_CREAT, O_EXCL, O_NOINHERIT, O_RANDOM, O_RDONLY, O_RDWR, O_SEQUENTIAL, O_SHORT_LIVED, O_TEMPORARY, O_TEXT, O_TRUNC, O_WRONLY

:pmodes

S_IREAD, S_IWRITE

:shflags

SH_DENYNO, SH_DENYRD, SH_DENYRW, SH_DENYWR

DEPENDENCIES

The following modules are use()'d by this module:

Standard Modules

AutoLoader, Carp, DynaLoader, Errno, Exporter, POSIX, Symbol

CPAN Modules

None

Other Modules

None

BUGS AND CAVEATS

  • As noted in the "WARNING" near the top of this manpage, there is currently a significant bug in the implementation of the fsopen() function which causes it to waste a filehandle every time it is called.

    See the file WARNING-FSOPEN.TXT in the original distribution archive, Win32-SharedFileOpen-2.00.tar.gz, for more details.

  • The Perl filehandle returned by sopen() is obtained by effectively doing an fdopen(3) on the file descriptor returned by _sopen() using the Perl built-in function open(). This involves converting the O_* flags that specify the $mode in the sopen() call into the corresponding (+) < | > | >> string used in specifying the file in the open() call, e.g. O_RDONLY becomes "<", O_RDWR | O_APPEND becomes "+>>", etc. This conversion could possibly break down in some situations.

    There is less chance of such a problem with fsopen(), because the $mode is simply specified as 'r' | 'w' | 'a' (+), which is more readily converted.

SEE ALSO

"open" in perlfunc, "sysopen" in perlfunc, perlopentut,

Fcntl, FileHandle, IO::File, IO::Handle, Symbol, Win32API::File

In particular, the Win32API::File module (part of the "libwin32" bundle) contains an interface to another, lower-level, Microsoft Visual C function, CreateFile(), which provides similar (and more) capabilities but using a completely different set of arguments which are unfamiliar to unseasoned Microsoft developers. A more Perl-friendly wrapper function, createFile(), is also provided but does not entirely alleviate the pain.

AUTHOR

Steve Hay <Steve.Hay@uk.radan.com>

COPYRIGHT AND LICENCE

Copyright (c) 2001-2002, Steve Hay. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

VERSION

Win32::SharedFileOpen, Version 2.00

HISTORY

See the file Changes in the original distribution archive, Win32-SharedFileOpen-2.00.tar.gz.