attrib command improvements

This commit is contained in:
Doug Lyons 2019-12-08 09:24:28 -06:00 committed by Victor Perevertkin
parent b34b47056a
commit f83f650dd6

View file

@ -86,17 +86,22 @@ ErrorMessage(
ConPrintf(StdOut, L"%s\n", szMsg); ConPrintf(StdOut, L"%s\n", szMsg);
} }
/* Returns TRUE if anything found and listed, FALSE otherwise */
static static
INT BOOL
PrintAttribute( PrintAttribute(
LPWSTR pszPath, LPWSTR pszPath,
LPWSTR pszFile, LPWSTR pszFile,
BOOL bRecurse) BOOL bRecurse,
BOOL bDirectories)
{ {
WIN32_FIND_DATAW findData; WIN32_FIND_DATAW findData;
HANDLE hFind; HANDLE hFind;
WCHAR szFullName[MAX_PATH]; WCHAR szFullName[MAX_PATH];
LPWSTR pszFileName; LPWSTR pszFileName;
BOOL bFound = FALSE;
BOOL bIsDir;
BOOL bExactMatch;
/* prepare full file name buffer */ /* prepare full file name buffer */
wcscpy(szFullName, pszPath); wcscpy(szFullName, pszPath);
@ -105,14 +110,16 @@ PrintAttribute(
/* display all subdirectories */ /* display all subdirectories */
if (bRecurse) if (bRecurse)
{ {
/* append file name */ /* append *.* */
wcscpy(pszFileName, pszFile); wcscpy(pszFileName, L"*.*");
hFind = FindFirstFileW(szFullName, &findData); hFind = FindFirstFileW(szFullName, &findData);
if (hFind == INVALID_HANDLE_VALUE) if (hFind == INVALID_HANDLE_VALUE)
{ {
ErrorMessage(GetLastError(), pszFile); if ((GetLastError() != ERROR_DIRECTORY) && (GetLastError() != ERROR_SHARING_VIOLATION)
return 1; && (GetLastError() != ERROR_FILE_NOT_FOUND))
ErrorMessage(GetLastError(), pszFile);
return FALSE;
} }
do do
@ -120,31 +127,39 @@ PrintAttribute(
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
continue; continue;
if (!wcscmp(findData.cFileName, L".") || if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
!wcscmp(findData.cFileName, L".."))
continue; continue;
wcscpy(pszFileName, findData.cFileName); wcscpy(pszFileName, findData.cFileName);
wcscat(pszFileName, L"\\"); wcscat(pszFileName, L"\\");
PrintAttribute(szFullName, pszFile, bRecurse); bFound = PrintAttribute(szFullName, pszFile, bRecurse,
bDirectories) || bFound;
} }
while(FindNextFileW(hFind, &findData)); while (FindNextFileW(hFind, &findData));
FindClose(hFind); FindClose(hFind);
} }
/* append file name */ /* append file name */
wcscpy(pszFileName, pszFile); wcscpy(pszFileName, pszFile);
/* display current directory */ /* search current directory */
hFind = FindFirstFileW(szFullName, &findData); hFind = FindFirstFileW(szFullName, &findData);
if (hFind == INVALID_HANDLE_VALUE) if (hFind == INVALID_HANDLE_VALUE)
{ {
ErrorMessage(GetLastError(), pszFile); return bFound;
return 1;
} }
do do
{ {
bIsDir = findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
bExactMatch = wcsicmp(findData.cFileName, pszFile) == 0;
if (bIsDir && !bDirectories && !bExactMatch)
continue;
if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
continue;
wcscpy(pszFileName, findData.cFileName); wcscpy(pszFileName, findData.cFileName);
ConPrintf(StdOut, ConPrintf(StdOut,
@ -154,129 +169,112 @@ PrintAttribute(
(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? L'H' : L' ', (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? L'H' : L' ',
(findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? L'R' : L' ', (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? L'R' : L' ',
szFullName); szFullName);
bFound = TRUE;
} }
while(FindNextFileW(hFind, &findData)); while(FindNextFileW(hFind, &findData));
FindClose(hFind); FindClose(hFind);
return 0; return bFound;
} }
/* Returns TRUE if anything changed, FALSE otherwise */
static static
BOOL BOOL
ChangeAttribute( ChangeAttribute(
LPWSTR pszPath, LPWSTR pszPath,
LPWSTR pszFile, LPWSTR pszFile,
BOOL bRecurse,
BOOL bDirectories,
DWORD dwMask, DWORD dwMask,
DWORD dwAttrib, DWORD dwAttrib)
BOOL bRecurse,
BOOL bDirectories)
{ {
WIN32_FIND_DATAW findData; WIN32_FIND_DATAW findData;
HANDLE hFind; HANDLE hFind;
DWORD dwAttribute;
WCHAR szFullName[MAX_PATH]; WCHAR szFullName[MAX_PATH];
LPWSTR pszFileName; LPWSTR pszFileName;
BOOL bWildcard = (wcschr(pszFile, L'*') || wcschr(pszFile, L'?')); BOOL bFound = FALSE;
BOOL bIsDir;
BOOL bExactMatch;
DWORD dwAttribute;
/* prepare full file name buffer */ /* prepare full file name buffer */
wcscpy(szFullName, pszPath); wcscpy(szFullName, pszPath);
pszFileName = szFullName + wcslen(szFullName); pszFileName = szFullName + wcslen(szFullName);
/* append file name */ /* display all subdirectories */
wcscpy(pszFileName, pszFile); if (bRecurse)
hFind = FindFirstFileW(szFullName, &findData);
if (hFind == INVALID_HANDLE_VALUE)
return FALSE;
dwAttribute = findData.dwFileAttributes;
if (!bWildcard)
{ {
FindClose(hFind); /* append *.* */
if (dwAttribute & FILE_ATTRIBUTE_DIRECTORY) wcscpy(pszFileName, L"*.*");
hFind = FindFirstFileW(szFullName, &findData);
if (hFind == INVALID_HANDLE_VALUE)
{ {
dwAttribute = (dwAttribute & ~dwMask) | dwAttrib; if ((GetLastError() != ERROR_DIRECTORY) && (GetLastError() != ERROR_SHARING_VIOLATION)
SetFileAttributes(szFullName, dwAttribute); && (GetLastError() != ERROR_FILE_NOT_FOUND))
if (bRecurse) ErrorMessage(GetLastError(), pszFile);
{
if (bDirectories)
{
ChangeAttribute(szFullName, L"*", dwMask, dwAttrib,
bRecurse, bDirectories);
}
else
{
if (!ChangeAttribute(szFullName, L"*", dwMask, dwAttrib,
bRecurse, FALSE))
{
return FALSE;
}
}
}
else
{
if (!bDirectories)
{
ChangeAttribute(szFullName, L"*", dwMask, dwAttrib,
bRecurse, FALSE);
}
}
return TRUE;
}
else
{
dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
SetFileAttributes(szFullName, dwAttribute);
return TRUE;
}
}
else
{
if ((dwAttribute & FILE_ATTRIBUTE_DIRECTORY) && (!bRecurse || !bDirectories))
return FALSE; return FALSE;
}
do do
{ {
dwAttribute = findData.dwFileAttributes; if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
if (dwAttribute & FILE_ATTRIBUTE_DIRECTORY) continue;
{
if (!bDirectories)
continue;
if (!wcscmp(findData.cFileName, L".") || if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
!wcscmp(findData.cFileName, L"..")) continue;
continue;
wcscpy(pszFileName, findData.cFileName);
dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
SetFileAttributes(szFullName, dwAttribute);
if (bRecurse)
{
ChangeAttribute(szFullName, findData.cFileName, dwMask,
dwAttrib, bRecurse, FALSE);
}
}
else
{
wcscpy(pszFileName, findData.cFileName);
dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
SetFileAttributes(szFullName, dwAttribute);
}
} while (FindNextFileW(hFind, &findData));
wcscpy(pszFileName, findData.cFileName);
wcscat(pszFileName, L"\\");
bFound = ChangeAttribute(szFullName, pszFile, bRecurse, bDirectories,
dwMask, dwAttrib) || bFound;
}
while (FindNextFileW(hFind, &findData));
FindClose(hFind); FindClose(hFind);
} }
return TRUE; /* append file name */
wcscpy(pszFileName, pszFile);
/* search current directory */
hFind = FindFirstFileW(szFullName, &findData);
if (hFind == INVALID_HANDLE_VALUE)
{
return bFound;
}
do
{
bIsDir = findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
bExactMatch = wcsicmp(findData.cFileName, pszFile) == 0;
if (bIsDir && !bDirectories && !bExactMatch)
continue;
if (!wcscmp(findData.cFileName, L".") || !wcscmp(findData.cFileName, L".."))
continue;
if (bRecurse && bIsDir && !bDirectories)
continue;
wcscpy(pszFileName, findData.cFileName);
dwAttribute = (findData.dwFileAttributes & ~dwMask) | dwAttrib;
SetFileAttributes(szFullName, dwAttribute);
bFound = TRUE;
}
while(FindNextFileW(hFind, &findData));
FindClose(hFind);
return bFound;
} }
int wmain(int argc, WCHAR *argv[]) int wmain(int argc, WCHAR *argv[])
{ {
INT i; INT i;
WCHAR szPath[MAX_PATH]; WCHAR szPath[MAX_PATH] = L""; // For case we only use 'attrib +h /s' there is no szPath
WCHAR szFileName [MAX_PATH]; WCHAR szFileName [MAX_PATH];
BOOL bRecurse = FALSE; BOOL bRecurse = FALSE;
BOOL bDirectories = FALSE; BOOL bDirectories = FALSE;
@ -389,7 +387,7 @@ int wmain(int argc, WCHAR *argv[])
szPath[len + 1] = UNICODE_NULL; szPath[len + 1] = UNICODE_NULL;
} }
wcscpy(szFileName, L"*.*"); wcscpy(szFileName, L"*.*");
PrintAttribute(szPath, szFileName, bRecurse); PrintAttribute(szPath, szFileName, bRecurse, bDirectories);
return 0; return 0;
} }
@ -405,14 +403,33 @@ int wmain(int argc, WCHAR *argv[])
if (dwMask == 0) if (dwMask == 0)
{ {
PrintAttribute(szPath, szFileName, bRecurse); if (!PrintAttribute(szPath, szFileName, bRecurse, bDirectories))
{
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
}
} }
else if (!ChangeAttribute(szPath, szFileName, dwMask, else if (!ChangeAttribute(szPath, szFileName, bRecurse, bDirectories, dwMask, dwAttrib))
dwAttrib, bRecurse, bDirectories))
{ {
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]); ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, argv[i]);
} }
} }
// Code below handles the special case of 'attrib +h /s' and similar
if (bRecurse && dwMask && (wcscmp(szPath, L"") == 0))
{
DWORD len;
len = GetCurrentDirectory(MAX_PATH, szPath);
if (szPath[len-1] != L'\\')
{
szPath[len] = L'\\';
szPath[len + 1] = UNICODE_NULL;
}
wcscpy(szFileName, L"*.*");
if (!ChangeAttribute(szPath, szFileName, bRecurse, bDirectories, dwMask, dwAttrib))
ConResPrintf(StdOut, STRING_FILE_NOT_FOUND, szFileName);
}
return 0; return 0;
} }