Opened 9 years ago

Closed 8 years ago

Last modified 5 years ago

#9016 closed Bugs (fixed)

filesystem::is_directory() returns false for junction

Reported by: harris.pc@… Owned by: Beman Dawes
Milestone: Boost 1.57.0 Component: filesystem
Version: Boost 1.53.0 Severity: Problem
Keywords: Cc:

Description

On Windows 7, create a Junction (to another folder).

You can use the "hardlink shell ext" tool to make the junctions/symlinks (google for it): Or the usual command line tools.

The boost::is_directory(target) returns false on this junction.

I used this Junction technique to move c:\Users\Me\AppData\Local\Temp to another disk, and as a consequence, temp_directory_path() will always fail because that host path is not treated as a directory.

ie the line in temp_directory_path():

  if ((ec&&!is_directory(p, *ec))||(!ec&&!is_directory(p)))

cheers, Paul

Change History (4)

comment:1 by Joseph Southwell <joseph@…>, 8 years ago

Upvote! Junctions are by definition directories on windows.

comment:2 by Beman Dawes, 8 years ago

Milestone: To Be DeterminedBoost 1.57.0
Resolution: fixed
Status: newclosed

The real question is whether or not it is safe to treat a Windows ReparseTag of either IO_REPARSE_TAG_SYMLINK or IO_REPARSE_TAG_MOUNT_POINT as a symlink for purposes of Boost.Filesystem. IO_REPARSE_TAG_MOUNT_POINT is the tag assigned by mklink /j to indicate a directory junction.

That appears to work OK, but (1) I'm worried about unintended consequences, and (2) it is too late for this change to go into Boost 1.56.0. So it is now in develop, and a 1.56.1 release of Boost.Filesystem will to into master as soon Boost 1.56.0 ships. That will give early adopters a chance to kick the tires and report any problems encountered before 1.57.0 ships.

Thanks,

--Beman

comment:3 by stsoe <stsoe@…>, 7 years ago

I just upgraded to boost_1_60_0 and was hit by a regression I think is related to 9016. My windows tests are failing sporadically with the error:

boost::filesystem::read_symlink: The process cannot access the file because it is being used by another process: "r:/data"

Debugging this comparing 1_60_0 to the earlier 1_56_0 I finally narrowed the difference to operations.cpp: bool is_reparse_point_a_symlink, which returns true in 1_60_0 but false in 1_56_0. The return value triggers canonical to call detail::read_symlink, which in turn ends up calling ::CreateFileW with dwShareMode set to 0 so that the file/directory is locked and cannot be opened by another process.

I am running my tests on LSF and many many processes end up accessing the same file / directory at the same time, thus leading the the above error message.

This problem unfortunately is a huge problem for the code I am working on, so I am wondering if I can get the 1_56_0 behavior by reverting the changes to is_reparse_point_a symlink?

comment:4 by martin.apel@…, 5 years ago

The implementation as of 1.64 (which is the same as for 1.60) still has a bug related to handling reparse points:

For an input path, which points to a IO_REPARSE_TAG_MOUNT_POINT, it returns something like

E:/?\Volume{3bb57579-710b-11e7-ac12-e8b1fc0f674c}\ \test

which is not accepted by other filesystem function, e.g. by create_directories.

From my point of view it is wrong to treat mount points as symlinks in all cases.

Note: See TracTickets for help on using tickets.