Commit 65477db1 by Edward Thomson Committed by Philip Kelley

Handle win32 reparse points properly

parent c2c81615
......@@ -30,7 +30,7 @@ GIT_INLINE(int) p_link(const char *old, const char *new)
extern int p_mkdir(const char *path, mode_t mode);
extern int p_unlink(const char *path);
extern int p_lstat(const char *file_name, struct stat *buf);
extern int p_readlink(const char *link, char *target, size_t target_len);
extern int p_readlink(const char *path, char *buf, size_t bufsiz);
extern int p_symlink(const char *old, const char *new);
extern char *p_realpath(const char *orig_path, char *buffer);
extern int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr);
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_win32_reparse_h__
#define INCLUDE_git_win32_reparse_h__
/* This structure is defined on MSDN at
* http://msdn.microsoft.com/en-us/library/windows/hardware/ff552012(v=vs.85).aspx
*
* It was formerly included in the Windows 2000 SDK and remains defined in
* MinGW, so we must define it with a silly name to avoid conflicting.
*/
typedef struct _GIT_REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} GIT_REPARSE_DATA_BUFFER;
#define REPARSE_DATA_HEADER_SIZE 8
#define REPARSE_DATA_MOUNTPOINT_HEADER_SIZE 8
#define REPARSE_DATA_UNION_SIZE 12
/* Missing in MinGW */
#ifndef FSCTL_GET_REPARSE_POINT
# define FSCTL_GET_REPARSE_POINT 0x000900a8
#endif
/* Missing in MinGW */
#ifndef FSCTL_SET_REPARSE_POINT
# define FSCTL_SET_REPARSE_POINT 0x000900a4
#endif
#endif
\ No newline at end of file
......@@ -7,6 +7,8 @@
#include "w32_util.h"
#define CONST_STRLEN(x) ((sizeof(x)/sizeof(x[0])) - 1)
/**
* Creates a FindFirstFile(Ex) filter string from a UTF-8 path.
* The filter string enumerates all items in the directory.
......@@ -67,3 +69,71 @@ int git_win32__sethidden(const char *path)
return 0;
}
/**
* Removes any trailing backslashes from a path, except in the case of a drive
* letter path (C:\, D:\, etc.). This function cannot fail.
*
* @param path The path which should be trimmed.
* @return The length of the modified string (<= the input length)
*/
size_t git_win32__path_trim_end(wchar_t *str, size_t len)
{
while (1) {
if (!len || str[len - 1] != L'\\')
break;
/* Don't trim backslashes from drive letter paths, which
* are 3 characters long and of the form C:\, D:\, etc. */
if (3 == len && git_win32__isalpha(str[0]) && str[1] == ':')
break;
len--;
}
str[len] = L'\0';
return len;
}
/**
* Removes any of the following namespace prefixes from a path,
* if found: "\??\", "\\?\", "\\?\UNC\". This function cannot fail.
*
* @param path The path which should be converted.
* @return The length of the modified string (<= the input length)
*/
size_t git_win32__to_dos(wchar_t *str, size_t len)
{
static const wchar_t dosdevices_prefix[] = L"\\\?\?\\";
static const wchar_t nt_prefix[] = L"\\\\?\\";
static const wchar_t unc_prefix[] = L"UNC\\";
size_t to_advance = 0;
/* "\??\" -- DOS Devices prefix */
if (len >= CONST_STRLEN(dosdevices_prefix) &&
!wcsncmp(str, dosdevices_prefix, CONST_STRLEN(dosdevices_prefix))) {
to_advance += CONST_STRLEN(dosdevices_prefix);
len -= CONST_STRLEN(dosdevices_prefix);
}
/* "\\?\" -- NT namespace prefix */
else if (len >= CONST_STRLEN(nt_prefix) &&
!wcsncmp(str, nt_prefix, CONST_STRLEN(nt_prefix))) {
to_advance += CONST_STRLEN(nt_prefix);
len -= CONST_STRLEN(nt_prefix);
}
/* "\??\UNC\", "\\?\UNC\" -- UNC prefix */
if (to_advance && len >= CONST_STRLEN(unc_prefix) &&
!wcsncmp(str + to_advance, unc_prefix, CONST_STRLEN(unc_prefix))) {
to_advance += CONST_STRLEN(unc_prefix);
len -= CONST_STRLEN(unc_prefix);
}
if (to_advance) {
memmove(str, str + to_advance, len * sizeof(wchar_t));
str[len] = L'\0';
}
return git_win32__path_trim_end(str, len);
}
\ No newline at end of file
......@@ -10,6 +10,11 @@
#include "utf-conv.h"
GIT_INLINE(bool) git_win32__isalpha(wchar_t c)
{
return ((c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z'));
}
/**
* Creates a FindFirstFile(Ex) filter string from a UTF-8 path.
* The filter string enumerates all items in the directory.
......@@ -28,4 +33,22 @@ bool git_win32__findfirstfile_filter(git_win32_path dest, const char *src);
*/
int git_win32__sethidden(const char *path);
/**
* Removes any trailing backslashes from a path, except in the case of a drive
* letter path (C:\, D:\, etc.). This function cannot fail.
*
* @param path The path which should be trimmed.
* @return The length of the modified string (<= the input length)
*/
size_t git_win32__path_trim_end(wchar_t *str, size_t len);
/**
* Removes any of the following namespace prefixes from a path,
* if found: "\??\", "\\?\", "\\?\UNC\". This function cannot fail.
*
* @param path The path which should be converted.
* @return The length of the modified string (<= the input length)
*/
size_t git_win32__to_dos(wchar_t *str, size_t len);
#endif
......@@ -29,6 +29,17 @@
#define cl_git_fail_with(expr, error) cl_assert_equal_i(error,expr)
/**
* Like cl_git_pass, only for Win32 error code conventions
*/
#define cl_win32_pass(expr) do { \
int _win32_res; \
if ((_win32_res = (expr)) == 0) { \
giterr_set(GITERR_OS, "Returned: %d, system error code: %d", _win32_res, GetLastError()); \
cl_git_report_failure(_win32_res, __FILE__, __LINE__, "System call failed: " #expr); \
} \
} while(0)
void cl_git_report_failure(int, const char *, int, const char *);
#define cl_assert_at_line(expr,file,line) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment