Hash :
bdec3363
Author :
Date :
2015-08-03T17:48:33
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
/*
* 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.
*/
#include "w32_util.h"
/**
* Creates a FindFirstFile(Ex) filter string from a UTF-8 path.
* The filter string enumerates all items in the directory.
*
* @param dest The buffer to receive the filter string.
* @param src The UTF-8 path of the directory to enumerate.
* @return True if the filter string was created successfully; false otherwise
*/
bool git_win32__findfirstfile_filter(git_win32_path dest, const char *src)
{
static const wchar_t suffix[] = L"\\*";
int len = git_win32_path_from_utf8(dest, src);
/* Ensure the path was converted */
if (len < 0)
return false;
/* Ensure that the path does not end with a trailing slash,
* because we're about to add one. Don't rely our trim_end
* helper, because we want to remove the backslash even for
* drive letter paths, in this case. */
if (len > 0 &&
(dest[len - 1] == L'/' || dest[len - 1] == L'\\')) {
dest[len - 1] = L'\0';
len--;
}
/* Ensure we have enough room to add the suffix */
if ((size_t)len >= GIT_WIN_PATH_UTF16 - CONST_STRLEN(suffix))
return false;
wcscat(dest, suffix);
return true;
}
/**
* Ensures the given path (file or folder) has the +H (hidden) attribute set.
*
* @param path The path which should receive the +H bit.
* @return 0 on success; -1 on failure
*/
int git_win32__set_hidden(const char *path, bool hidden)
{
git_win32_path buf;
DWORD attrs, newattrs;
if (git_win32_path_from_utf8(buf, path) < 0)
return -1;
attrs = GetFileAttributesW(buf);
/* Ensure the path exists */
if (attrs == INVALID_FILE_ATTRIBUTES)
return -1;
if (hidden)
newattrs = attrs | FILE_ATTRIBUTE_HIDDEN;
else
newattrs = attrs & ~FILE_ATTRIBUTE_HIDDEN;
if (attrs != newattrs && !SetFileAttributesW(buf, newattrs)) {
giterr_set(GITERR_OS, "Failed to %s hidden bit for '%s'",
hidden ? "set" : "unset", path);
return -1;
}
return 0;
}
int git_win32__hidden(bool *out, const char *path)
{
git_win32_path buf;
DWORD attrs;
if (git_win32_path_from_utf8(buf, path) < 0)
return -1;
attrs = GetFileAttributesW(buf);
/* Ensure the path exists */
if (attrs == INVALID_FILE_ATTRIBUTES)
return -1;
*out = (attrs & FILE_ATTRIBUTE_HIDDEN) ? true : false;
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 (len == 3 && 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__canonicalize_path(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);
}