Skip to content

Commit

Permalink
Stop using SHFileOperation on Win32 (for speed)
Browse files Browse the repository at this point in the history
  • Loading branch information
phkelley committed Oct 15, 2012
1 parent a5ba72b commit 5ce31b6
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 44 deletions.
2 changes: 1 addition & 1 deletion clar.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ def _process_categories(self, suite_name, contents):
"clar_print_tap.c" : r"""eJyNVE1vnDAQPcOvmGWFBAiQot6yaqr2HFU9tLdKyAGzscLayDbbVlX+e8cDJPbuJtsTzPObmTcfdmwss6KFoxIdtAPTzaiFtI2Qwmb4A5Yb27RqkrYEZ5tJWL4CrZLGQvvINBTzgWQHbvL4bxxlLmT+6r5bIY94gq08ktBnyffP3+DItRFKws2HnzLJd/FzHL8h2TxOtlO/5HXZDuBaKz0D/yM3xDznXRxHoodsEwSMXmrYwsiM4R2wYYC0I2GZybGY0hOJhUV8MDxw7JkY0BGd2EHJ/am3l7BEvyiMtoa5qeu0O8/2dhspLPVQTod1xMbqqbUzjQhQ0MdrHbJdL9a8AFVVzSPzMJy5YXsOt5Ca1yKqu7mWg9mHdMNx/ML+uaVenEWj0QCcRSM8pLri4QLV4SGzx6ZfYjo8ZA5CrszOZzq8wXY8cJ2v67Ecddy0WozWbfTmI3z9cX/vLwuARzgV4B3lYafrur52OZSk1fEvLO2Du4bzhZhNUj0D8/rRhNdUqXFLWC3CUPiyop8gkcqCekqwGQl+3Jkf8MXEdHFE8kmc5qPSy86Z7EoFNNbs8pvj33IhO/470L2FoihQNWTbtMudQY313X3X92WwB5QcyMC9Ld0QKOeRNYPAI6b3445MjIQOzi5hWfF+UWbwxZrwRUq+YCMBfzdAO348JVAKFyKfY3LZZYv5HP8D5Mbj9w==""",
"clar_sandbox.c" : r"""eJydVWtP4kAU/dz+iism0gpKfWQ3G9YPm+gasioEMJgomdR2KhPplMwM7KLxv++dTqEP0DVrTKjcO+eec+6cKpWvWADBxBdAgqkvyMxXk/tT79uXcdu2pSkzrmwmycKfspCoeJY2OUHCpTJH9/UXrv1qW4PhjyEZglR42mIROBrC0eUm7Enlws4ZeK5tWYKqueDgrfp2BqQzOO/08cChVCROQupW+7Jnxw8CKmWGOiLdXy6cadi2/VbiHDFe5JsyfZxHERVNkOyFEgVTyp8M9V0W8ZBGQEadm5Nj28pwjMqse4EGBcmcKziD03alx+BTvkCjhLwfYw8aYtWG1z3UVWuCfko/Lszn7eCi3+t3f3auLmo2WG8oEaxsEtN6o0SAwxDHawOD7/n4NjQazE3hK7Ox+YkqfHDWRNgYjbGMyfilNlWfUozPqZ6SVjbXq1vNCJQpeDBbOivvsNRcOaehC0uyrDcbf22rtQ+dCNSE6m4mEh5TtC1MqOR19NNfgs+XasL4UxOUWIJKYC4ptHA+7Lfsd0jVdL2W8arSMsUSswIxJLVLp5Ia6EuqhjSe9TSocz7q9s9dc6wJBq5y+XYpD1lkdA0nTIJcSkXjtaApe6YooKRFiw/mQqTCmaCBSrD4gbjDd5UdfiRr9efBUTEAi4SFkEZ6zqXPw8fkj6O/S2OqCRTy7o11gOoPXj1XjVcDI1FMRDBBFcgSaRYMiSQRcQGsmkL0k01DklEwStc8CrdXF4jy2TRNTi3F09bcpT81nbZ1ZFcvjXLAcw4m3klUpOVigIpvHu2WbSEYTkO/8aEsoqr+FXD1PBExLu2FpnT1onvdQecOMKm/fRGCnPpyQmW65EKUrY0oaxF5iKv7YNk+HtJ9WFalBPVWfR219SIqGFrZARyN9RsX+82gcr3RyMH0PVpdu7wLGpppM1/ONmdxDDZllgF6xjgNHUKuOzeXo5NjQtyMXPyMkZmVjqLMm9urq4296P74Wd+34la9r5638S9EH8BkF0enKytPJfKf92ML7v8QWb1i8NQn5a5XmOe6HKEU4fMhhr29banbngCNYpJdJLrVixK9v7GvgW8=""",
"clar_fixtures.c" : r"""eJyFUV1LwzAUfW5+xZU9rLUVJ4ggZQ9DFAUfZEwQSglZmrBAl5Qkk6n43236tWbKfMvNOfecc+81llhBgSppLNAN0XCOuNjbnWa4InYTjpE1MSzxuD1Vki2L0BcKTKfn0EYgu57d3uRpjYhPhi1opSwumUwRCvo3zMFYXT9C5xA5stWSVh9hI5FAa+wUFG//osgJCA5tmQ1SF3CVw9kcppfTCAWBj8ZxDg3UN4/zZ7MaHBrHSBw7vpcJ4mGS5Ijtai9qnannNqk1q7myXU+KvhGaCF4wDnfPiyV+eHpbvS7v8cti9YjGq6Yl7lzCkxfo1L0j/lJOwOtrUrwrUcDBBRsii7Xan3bjBlNVL2WUzuMkgGlJdLuIP21oyYjcVf/a6G3ozXTQPRqmsZkwWQiOfgAVGffP""",
"clar_fs.c" : r"""eJylVdtu20YQfSa/YkAD8TKWY8dJX6L0wXDEVqgsBhINN7UFhiGX1qIkl9hd+dLG/57ZCynJUWEkfZE0s7NnZufMGe2xsqAlpJfj6ZsT399DgzUUojhKo8npb3Mg+ud8PBlNE/hq/NP4LJ5G49n5aTKOp71zNJvFs4vx06DzPz6MZ6HvS5UplkO+zAS89EtWUd7KtM3UkuS8kcqdGE/o/+t71tYm/ArTi8lk6HuS/UNTBRVtbtRyAGzo+x4rgaQ2zMaFvucJqlaicdd8z15AHKkE/rbxIQI6+DqrKp4TF3YAJ2GH/AxwTeu8fTBRA0jtl0Xp0K+sucAsx9suzPPauX2v5AIIMxYweO9AhnBwwELAbvTFXLGFrmf/aF+X4/Uu2L++3scEjwjmitRnQ/+x7/0tZ0XXecIaBTUv6AC22i/5SuRPnQWVynAy/z3CSYg/zpPZxVkCJQLp4m2YvYqVbJHrEHU7bJgG+y7IZNBQf1HBz2nNxQN5oeEHoDnnJdlOHYa2aa18dRetmlxziI8ZOl8bCV5ruk3u3ptw9OlUnaeMquxGorOfd/OcKs2kpEKlBFuMibHUuKUCm8gbW1aoOTge4HFwyZqC30l4EgdlhmYR+J4tVVBK1q0wpnv0U4JkKmqygxTDQEdfFKcfRpNRMsKx6zgzM7oLL+c4oz9A80aSs/jjp40U6bpmA46t0vgVzZpVS7TLApg3lOwe55A6ivMqE04hwcsgtCB7tJK0KxdH0pdLWlUpXylii3IVZuLm9mphsPXg6gsrqeXECtwH+Kl7jF96sLj4m6z1i773cGw1VLYCb5dEqoIKodnzgvmDVLQGtLl4B5/t7c+Q40ZwFL66bgLNmUfvmSKHr0Onsg5eT4LFp/c0vyWm1uPFwBTdBd9lTGGwvjCAF7b+Ad4b9mq9HP05TubJaXIxJ/b8f3DZU2lNU9Ivi+G2VNcL1dopLh3dt17IuC0LpHVDwuvA9TLtT21LrHm1EXlo9ly/s/4rwC5C1z00g6MvrDnK22DovCYoOJz1jpPFpsaN6412udkJndTNwdtF/zdiFF6vpMJxlNKIfD12hjQj7MiwD4qD7jkovbfcSEvtlVlTfOH3uxX+rKg3NL3B0dvFrh6I+rselNtN6F68oxk/+2araVBLuv3SZ6RvZL5q3BVi9r52bTgeUfZNwUr/G9kaoSs=""",
"clar_fs.c" : r"""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""",
"clar_categorize.c" : r"""eJydVV1v0zAUfU5+xV3RKudj0/ZcOqkqAyGVIU3bA9omy01dsJQlJXYRY+K/c32ddE6WtMBLGzv365x77s2blVyrQsJ8Mbvm89nN5YfP11/4u8v3s9vFDYzwrdjmZhSG5mkj8QTaVNvMwHMYZGWhDWTfRAVxXIhHqSdhoAq8KreFqZ9FnpfZJPwNWS4qngkjv5bVE8+VRotQG2FU1vMOuH+nfkkuC7HM5erFiTK1HFVBvqwnXGx/U/BLRoMofHZVKqx2XVbAFEzhbAIK3oL1OLlwWCBJVBQGgVoDQwIyoWX2uGEYIq3tCP+deohgihGsbVBJs60KOMfY9eMZErGr/0epVh0AYrXipvwvEFhYPxm1D9rZolwhSCJ5eBDhYlojoY5FtsGBdwHJFM6x/uaS8CJZrKWCqJJkzSx+RgjjyHNI/RwQg8bOlutWjCjCJMiSn+fOKzRJHjAt4jnApdML65BF74ixYebHQ9ojGl2Ev0rOESazELkBvVVGckLQdLCeJPKk1xDTn6b6aj+rzBbFhLxbfg22d4gja94Vt1cOXiSJ1QbZYEi0cnWgnE8bFnC4LXoYj4lHOji3/lJImT5Ldsz4p9nHKz6fd9iiUSKMTjGiYcgdl8RHPUIn4M2fSJeHOrGpMHHTwJYaNhVuvp/+CgiD77qsDGuEO6SDU6dlxD5o4RqNFn0KT1/j723S/ui7pUQQ12x0rI/1fTFKwSFLh/13y6rboM4K0U6XHfqGdOvGyteqzsRu1xztR2OB/KOmKSplxtWwk+nLlhv4OljJ7hnxAzNkITUD4qedAKGFoylc3S4WE7AnNyDDu3lPGRQt6nxH2h+SPx6FmFM=""",
"clar.h" : r"""eJy9VV1vmzAUfS6/wg17gAi1TR+7tlIUJWukqJvaVNueLGNMsQaG2mbNNO2/7xpICF/Juoe+JOZe33uOOecam4ciYCHCeLaaPuD1/HGN7zC2bAhywTpxy+aCxnnA0LXSQcz9s+jWsn6mPEA0JhJjohST2rFOuNCIpiLgmqfCs05grSASEYnGIY+ZV26JAaWVZVKmshULmKKSZ1UvU6iiNI8DTPxUavdjDwfMXnISY+Xs9/GGH6BpJwCNh/pyxxT0FfV12bbBimlMY0ZEnjlFzBlXj275PHY9VC7SjLzkrKaAQ9UoNW1tHhr5CpEWy2/rp4c5/jJd31n7HEwp3+hcMqepQhHDgiQNlCqsiAj8dPOWki27AyU2A0uE1s5gsxVe3uPZdD3/9PnhuwML17LOx2MLjdG0eN8gOUoIlalCr1xHiG2ymFOuUeETlDClyDOD/ee7pkApyZXGGSiGHSiQHjIOcpsmLTIuur1BFx44fbFczTE2q9XyvliNFrmgBQFK4hiFBHwbXKERsuueHpq4HWCz8zjw9SDufJMxqlmAwgYBnRYcjjCobHoU/nT43IAv4b0aYK6QSDXSMmd9uFutZhGjP/5DJ2rq3kmoC7eL/M5K9VF4B6Eujg2VSP9xnCpKfRN2/7Ra9Y9Cq2j/nXeKqqPvKppuLrcPm+7YOWq71QhdC3ZI1V5plx08S7GlXdF7kkUqqTERdIPL8vyVSMHFc5t9QaDHJ0PuWDO4hsthOBv1XxYV0lu6fi1LUJBL86cNCNswmhtXXY16PLf+lcHhSMt57dO1Pttq4qnLJqVdDpKu50Da2zHcERw96oJXwlVCNI2KYVAT+IU5MsvLgQtz912feLwfmDuQBGDeC2zzGoQfBvEdf+L5QyCnp5B2PfPXD+TXQP5hoMzJJl52uTdJDkRcdHODHAjvSWRUTJiO0gD0M7SIkaoU6cNvttFMCryf+WNtP+Z/AaQwXp0="""
}
Expand Down
215 changes: 172 additions & 43 deletions clar_fs.c
Original file line number Diff line number Diff line change
@@ -1,68 +1,197 @@
#ifdef _WIN32

#define FOF_FLAGS (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR)
#ifdef __MINGW32__

static char *
fileops_path(const char *_path)
{
char *path = NULL;
size_t length, i;

if (_path == NULL)
return NULL;

length = strlen(_path);
path = malloc(length + 2);
/* These security-enhanced functions are not available
* in MinGW, so just use the vanilla ones */
#define wcscpy_s(a, b, c) wcscpy((a), (c))
#define wcscat_s(a, b, c) wcscat((a), (c))

if (path == NULL)
return NULL;

memcpy(path, _path, length);
path[length] = 0;
path[length + 1] = 0;

for (i = 0; i < length; ++i) {
if (path[i] == '/')
path[i] = '\\';
}
#endif /* __MINGW32__ */

return path;
static int
fs__dotordotdot(WCHAR *_tocheck)
{
return _tocheck[0] == '.' &&
(_tocheck[1] == '\0' ||
(_tocheck[1] == '.' && _tocheck[2] == '\0'));
}

static void
fileops(int mode, const char *_source, const char *_dest)
fs_rmdir_helper(WCHAR *_wsource)
{
SHFILEOPSTRUCT fops;

char *source = fileops_path(_source);
char *dest = fileops_path(_dest);

ZeroMemory(&fops, sizeof(SHFILEOPSTRUCT));
WCHAR buffer[MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
int buffer_prefix_len;

/* Set up the buffer and capture the length */
wcscpy_s(buffer, MAX_PATH, _wsource);
wcscat_s(buffer, MAX_PATH, L"\\");
buffer_prefix_len = wcslen(buffer);

/* FindFirstFile needs a wildcard to match multiple items */
wcscat_s(buffer, MAX_PATH, L"*");
find_handle = FindFirstFileW(buffer, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);

do {
/* FindFirstFile/FindNextFile gives back . and ..
* entries at the beginning */
if (fs__dotordotdot(find_data.cFileName))
continue;

wcscpy_s(buffer + buffer_prefix_len, MAX_PATH - buffer_prefix_len, find_data.cFileName);

if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
fs_rmdir_helper(buffer);
else {
/* If set, the +R bit must be cleared before deleting */
if (FILE_ATTRIBUTE_READONLY & find_data.dwFileAttributes)
cl_assert(SetFileAttributesW(buffer, find_data.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY));

cl_assert(DeleteFileW(buffer));
}
}
while (FindNextFileW(find_handle, &find_data));

fops.wFunc = mode;
fops.pFrom = source;
fops.pTo = dest;
fops.fFlags = FOF_FLAGS;
/* Ensure that we successfully completed the enumeration */
cl_assert(ERROR_NO_MORE_FILES == GetLastError());

cl_assert_(
SHFileOperation(&fops) == 0,
"Windows SHFileOperation failed"
);
/* Close the find handle */
FindClose(find_handle);

free(source);
free(dest);
/* Now that the directory is empty, remove it */
cl_assert(RemoveDirectoryW(_wsource));
}

static void
fs_rm(const char *_source)
{
fileops(FO_DELETE, _source, NULL);
WCHAR wsource[MAX_PATH];
DWORD attrs;

/* The input path is UTF-8. Convert it to wide characters
* for use with the Windows API */
cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_source,
-1, /* Indicates NULL termination */
wsource,
MAX_PATH));

/* Does the item exist? If not, we have no work to do */
attrs = GetFileAttributesW(wsource);

if (INVALID_FILE_ATTRIBUTES == attrs)
return;

if (FILE_ATTRIBUTE_DIRECTORY & attrs)
fs_rmdir_helper(wsource);
else {
/* The item is a file. Strip the +R bit */
if (FILE_ATTRIBUTE_READONLY & attrs)
cl_assert(SetFileAttributesW(wsource, attrs & ~FILE_ATTRIBUTE_READONLY));

cl_assert(DeleteFileW(wsource));
}
}

static void
fs_copydir_helper(WCHAR *_wsource, WCHAR *_wdest)
{
WCHAR buf_source[MAX_PATH], buf_dest[MAX_PATH];
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
int buf_source_prefix_len, buf_dest_prefix_len;

wcscpy_s(buf_source, MAX_PATH, _wsource);
wcscat_s(buf_source, MAX_PATH, L"\\");
buf_source_prefix_len = wcslen(buf_source);

wcscpy_s(buf_dest, MAX_PATH, _wdest);
wcscat_s(buf_dest, MAX_PATH, L"\\");
buf_dest_prefix_len = wcslen(buf_dest);

/* Get an enumerator for the items in the source. */
wcscat_s(buf_source, MAX_PATH, L"*");
find_handle = FindFirstFileW(buf_source, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);

/* Create the target directory. */
cl_assert(CreateDirectoryW(_wdest, NULL));

do {
/* FindFirstFile/FindNextFile gives back . and ..
* entries at the beginning */
if (fs__dotordotdot(find_data.cFileName))
continue;

wcscpy_s(buf_source + buf_source_prefix_len, MAX_PATH - buf_source_prefix_len, find_data.cFileName);
wcscpy_s(buf_dest + buf_dest_prefix_len, MAX_PATH - buf_dest_prefix_len, find_data.cFileName);

if (FILE_ATTRIBUTE_DIRECTORY & find_data.dwFileAttributes)
fs_copydir_helper(buf_source, buf_dest);
else
cl_assert(CopyFileW(buf_source, buf_dest, TRUE));
}
while (FindNextFileW(find_handle, &find_data));

/* Ensure that we successfully completed the enumeration */
cl_assert(ERROR_NO_MORE_FILES == GetLastError());

/* Close the find handle */
FindClose(find_handle);
}

static void
fs_copy(const char *_source, const char *_dest)
{
fileops(FO_COPY, _source, _dest);
WCHAR wsource[MAX_PATH], wdest[MAX_PATH];
DWORD source_attrs, dest_attrs;
HANDLE find_handle;
WIN32_FIND_DATAW find_data;

/* The input paths are UTF-8. Convert them to wide characters
* for use with the Windows API. */
cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_source,
-1,
wsource,
MAX_PATH));

cl_assert(MultiByteToWideChar(CP_UTF8,
MB_ERR_INVALID_CHARS,
_dest,
-1,
wdest,
MAX_PATH));

/* Check the source for existence */
source_attrs = GetFileAttributesW(wsource);
cl_assert(INVALID_FILE_ATTRIBUTES != source_attrs);

/* Check the target for existence */
dest_attrs = GetFileAttributesW(wdest);

if (INVALID_FILE_ATTRIBUTES != dest_attrs) {
/* Target exists; append last path part of source to target.
* Use FindFirstFile to parse the path */
find_handle = FindFirstFileW(wsource, &find_data);
cl_assert(INVALID_HANDLE_VALUE != find_handle);
wcscat_s(wdest, MAX_PATH, L"\\");
wcscat_s(wdest, MAX_PATH, find_data.cFileName);
FindClose(find_handle);

/* Check the new target for existence */
cl_assert(INVALID_FILE_ATTRIBUTES == GetFileAttributesW(wdest));
}

if (FILE_ATTRIBUTE_DIRECTORY & source_attrs)
fs_copydir_helper(wsource, wdest);
else
cl_assert(CopyFileW(wsource, wdest, TRUE));
}

void
Expand Down

0 comments on commit 5ce31b6

Please sign in to comment.