Alien-uv
view release on metacpan or search on metacpan
libuv/src/win/fs.c view on Meta::CPAN
assert(r == target_len);
target[target_len] = '\0';
*target_ptr = target;
return 0;
}
INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
uint64_t* target_len_ptr) {
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
REPARSE_DATA_BUFFER* reparse_data = (REPARSE_DATA_BUFFER*) buffer;
WCHAR* w_target;
DWORD w_target_len;
DWORD bytes;
if (!DeviceIoControl(handle,
FSCTL_GET_REPARSE_POINT,
NULL,
0,
buffer,
sizeof buffer,
&bytes,
NULL)) {
return -1;
}
if (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
/* Real symlink */
w_target = reparse_data->SymbolicLinkReparseBuffer.PathBuffer +
(reparse_data->SymbolicLinkReparseBuffer.SubstituteNameOffset /
sizeof(WCHAR));
w_target_len =
reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
/* Real symlinks can contain pretty much everything, but the only thing we
* really care about is undoing the implicit conversion to an NT namespaced
* path that CreateSymbolicLink will perform on absolute paths. If the path
* is win32-namespaced then the user must have explicitly made it so, and
* we better just return the unmodified reparse data. */
if (w_target_len >= 4 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
w_target[2] == L'?' &&
w_target[3] == L'\\') {
/* Starts with \??\ */
if (w_target_len >= 6 &&
((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
(w_target[4] >= L'a' && w_target[4] <= L'z')) &&
w_target[5] == L':' &&
(w_target_len == 6 || w_target[6] == L'\\')) {
/* \??\<drive>:\ */
w_target += 4;
w_target_len -= 4;
} else if (w_target_len >= 8 &&
(w_target[4] == L'U' || w_target[4] == L'u') &&
(w_target[5] == L'N' || w_target[5] == L'n') &&
(w_target[6] == L'C' || w_target[6] == L'c') &&
w_target[7] == L'\\') {
/* \??\UNC\<server>\<share>\ - make sure the final path looks like
* \\<server>\<share>\ */
w_target += 6;
w_target[0] = L'\\';
w_target_len -= 6;
}
}
} else if (reparse_data->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
/* Junction. */
w_target = reparse_data->MountPointReparseBuffer.PathBuffer +
(reparse_data->MountPointReparseBuffer.SubstituteNameOffset /
sizeof(WCHAR));
w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength /
sizeof(WCHAR);
/* Only treat junctions that look like \??\<drive>:\ as symlink. Junctions
* can also be used as mount points, like \??\Volume{<guid>}, but that's
* confusing for programs since they wouldn't be able to actually
* understand such a path when returned by uv_readlink(). UNC paths are
* never valid for junctions so we don't care about them. */
if (!(w_target_len >= 6 &&
w_target[0] == L'\\' &&
w_target[1] == L'?' &&
w_target[2] == L'?' &&
w_target[3] == L'\\' &&
((w_target[4] >= L'A' && w_target[4] <= L'Z') ||
(w_target[4] >= L'a' && w_target[4] <= L'z')) &&
w_target[5] == L':' &&
(w_target_len == 6 || w_target[6] == L'\\'))) {
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
}
/* Remove leading \??\ */
w_target += 4;
w_target_len -= 4;
} else {
/* Reparse tag does not indicate a symlink. */
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
}
return fs__wide_to_utf8(w_target, w_target_len, target_ptr, target_len_ptr);
}
void fs__open(uv_fs_t* req) {
DWORD access;
DWORD share;
DWORD disposition;
DWORD attributes = 0;
HANDLE file;
int fd, current_umask;
int flags = req->fs.info.file_flags;
/* Obtain the active umask. umask() never fails and returns the previous
* umask. */
current_umask = umask(0);
umask(current_umask);
( run in 0.939 second using v1.01-cache-2.11-cpan-e1769b4cff6 )