libgit2/libgit2 — pull request #2265 by ethomson (2014-04-12 20:44:24+00:00)
Title: Handle reparse points properly on win32

@jamill and I tracked down a bug that we've been seeing intermittently where users on Win32 were occasionally seeing strange errors where objects can't be loaded. This can occur on machines running [data de-duplication](http://msdn.microsoft.com/en-us/library/hh769303(v=vs.85).aspx): the system actually marks de-dup'd files as reparse points.

Libgit2 [currently treats any reparse point as a symbolic link] in `lstat` (https://github.com/libgit2/libgit2/blob/development/src/win32/posix_w32.c#L91), and sets the `S_IFMT` to `S_IFLNK`. In fact, we should only be considering junctions and symbolic links as `S_IFLNK`s, otherwise files that are other types of reparse points (like these de-dup'd files) that have the semantics of regular files will fail tests where callers call `S_ISREG()`. (`odb_pack` does this, for example, to ensure that a pack file is not a directory.)

This adds numerous tests around `readlink`, `stat` and `lstat` for symbolic links on all platforms. On Windows, this also adds tests for handling junctions using the same functions. Finally, this adds some tests on Windows that create custom reparse points and ensures that they are treated as regular files. Since only administrators can create reparse points on Windows, these tests only run as administrator and use `clar__skip` otherwise.

In order to deal with these cases on Windows, this rewrites `p_readlink` in order to actually read the contents of the reparse points. `p_lstat` now takes advantage of this handling. `p_stat` keeps the existing mechanism of using `GetFinalPathNameByHandle` to resolve symbolic links and junctions to the final destination and `stat`ting that.