The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Win32::NTFS::Symlink - Support for NTFS symlinks and junctions on Microsoft Windows

SYNOPSIS

  use Win32::NTFS::Symlink qw(:global junction ntfs_reparse_tag :is_ :const);
  
  # Create NTFS symlinks.
  symlink 'D:\dir1'      => 'D:\symlink_to_dir1';      # To a directory.
  symlink 'D:\file1.txt' => 'D:\symlink_to_file1.txt'; # To a file.
  
  # Creates an NTFS directory junction.
  junction 'D:\dir1' => 'D:\junction_to_dir1';
  
  say readlink 'D:\symlink_to_dir1';      # 'D:\dir1'
  say readlink 'D:\symlink_to_file1.txt'; # 'D:\file1.txt'
  say readlink 'D:\junction_to_dir1';     # 'D:\dir1'
  
  # true
  say is_ntfs_symlink('D:\symlink_to_dir1');
  say is_ntfs_symlink('D:\symlink_to_file1.txt');
  say is_ntfs_junction('D:\junction_to_dir1');
  
  say ntfs_reparse_tag('D:\symlink_to_dir1')      == IO_REPARSE_TAG_SYMLINK;
  say ntfs_reparse_tag('D:\symlink_to_file1.txt') == IO_REPARSE_TAG_SYMLINK;
  say ntfs_reparse_tag('D:\junction_to_dir1')     == IO_REPARSE_TAG_MOUNT_POINT;
  
  # false
  say is_ntfs_symlink('D:\junction_to_dir1');
  say is_ntfs_junction('D:\symlink_to_dir1');
  say is_ntfs_junction('D:\symlink_to_file1.txt');
  
  say ntfs_reparse_tag('D:\junction_to_dir1')     == IO_REPARSE_TAG_SYMLINK;
  say ntfs_reparse_tag('D:\symlink_to_dir1')      == IO_REPARSE_TAG_MOUNT_POINT;
  say ntfs_reparse_tag('D:\symlink_to_file1.txt') == IO_REPARSE_TAG_MOUNT_POINT;

Or

  use if ($^O eq 'MSWin32'), qw(Win32::NTFS::Symlink :global);
  
  # Now symlink() and readlink() can be used in a program that will
  # behave the same way (in regards to symbolic links) on Windows as
  # it would on most unix-like systems, to make for more
  # platform-agnostic symbolic link handling.

DESCRIPTION

This module implements symlink and readlink routines, as well as a junction function, for use with NTFS file-systems on Microsoft Windows.

FUNCTIONS

Main Functions

symlink( $path ) , ntfs_symlink( $path )

Create an NTFS symlink. Can be either relative or absolute.

Has the same prototype as the built-in symlink function.

(For Windows XP, 2003 Server, or 2000, see section "NTFS Symlinks in Windows XP, 2003 Server, and 2000" below.)

junction( $path ) , ntfs_junction( $path )

Create an NTFS directory junction. Unlike symlinks, junctions are only able to link to absolute paths, even if a relative one is specified, and only to a local volume. This is is a limitation of how junctions themselves work.

Also has the same prototype as the built-in symlink function.

readlink( $path ) , ntfs_readlink( $path )

Read NTFS symlinks and junctions. Junctions are always returned as absolute.

Has the same prototype as the built-in readlink function.

The above can be imported by name.

Test Functions

is_ntfs_symlink( $path )

Returns true if $path is an NTFS symlink, false otherwise.

Has the same prototype as the built-in readlink function.

is_ntfs_junction( $path )

Returns true if $path is an NTFS junction, false otherwise.

Has the same prototype as the built-in readlink function.

ntfs_reparse_tag( $path )

Returns the NTFS reparse tag, which will be a specific value depending on if $path is a symlink, junction, or 0 if it is neither.

This routine is most useful as an alternative to is_ntfs_symlink and is_ntfs_junction above.

Has the same prototype as the built-in readlink function.

(See section "CONSTANTS" below.)

The above can be imported by name.

CONSTANTS

The following can be used to test the return value of ntfs_reparse_tag.

This value for the tag portion of the reparse data for an NTFS symlink.

IO_REPARSE_TAG_MOUNT_POINT

This value for the tag portion of the reparse data for an NTFS junction.

The above can be imported by name.

EXPORTS

By default, nothing is exported or overridden.

Override Built-In Functions

:global

This overrides the global readlink and symlink built-in functions. This can be useful to allow other modules that use readlink or symlink to be able to function correctly on Windows.

This can also be done on an individual basis with:

Note: global_junction does not exist since there is no built-in function with this name, as it is specific only to the NTFS file-system on the Win32 platform.

General Imports

:package

Imports the following into the current namespace:

readlink
symlink
junction

General Imports with ntfs_ prefix

This can be useful to prevent conflicts with existing sub routines the names above.

:ntfs_

Imports the following into the current namespace:

ntfs_junction
ntfs_reparse_tag

Test Imports

:is_

Imports the following into the current namespace:

is_ntfs_symlink
is_ntfs_junction

Importable Constants

:const

Imports the following into the current namespace:

IO_REPARSE_TAG_SYMLINK
IO_REPARSE_TAG_MOUNT_POINT

(See section "CONSTANTS" above.)

NTFS Symlinks in Windows XP, 2003 Server, and 2000

For proper NTFS symlink support in Windows XP, 2003 Server, and 2000 (NT 5.x), a driver is needed to enable support, to expose the existing underlying functionality to the user-land level so it can be accessed and manipulated by programs and libraries.

The driver and it's source code can be obtained from http://schinagl.priv.at/nt/ln/ln.html (at the bottom.)

Note that this is only required for full symlink support. Junctions, on the other hand do not require this, since that part of the NTFS reparse mechanism is already exposed to the user-land level. However, symlink will not work correctly without it, nor will readlink be able to properly read symlinks.

This isn't needed if you are using Vista or Server 2008 R1 (NT 6.0), or later.

TODO

Implement -l

I plan to do this for the next release!

ACKNOWLEDGEMENTS

I originally set out to fix Win32::Symlink, whose symlink and readlink implementations (ironically) only worked with NTFS junctions, without any support for NTFS symlinks.

I ended up creating a fresh new module to properly implement symlink as well as junction, and a readlink that could read either one.

So even though I ended up not using much of anything from Win32::Symlink, I still want to acknowledge Audrey Tang <cpan@audreyt.org> for the inspiration, as well as http://schinagl.priv.at/nt/ln/ln.html whose source code relating to the ln utility that helped greatly in figuring out how to properly work with NTFS reparse points.

I also want to greatly thank all of the wonderful folks in the perl IRC channels for their wisdom and advise.

AUTHOR

Bayan Maxim <baymax@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2018 by Bayan Maxim

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

See http://www.perl.com/perl/misc/Artistic.html

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 350:

'=item' outside of any '=over'

Around line 354:

You forgot a '=back' before '=head1'