/* * ATTRIB.C - attrib internal command. * * * History: * * 04-Dec-1998 (Eric Kohl ) * started * * 09-Dec-1998 (Eric Kohl ) * implementation works, except recursion ("attrib /s"). * * 05-Jan-1999 (Eric Kohl ) * major rewrite. * fixed recursion ("attrib /s"). * started directory support ("attrib /s /d"). * updated help text. * * 14-Jan-1999 (Eric Kohl ) * Unicode ready! * * 19-Jan-1999 (Eric Kohl ) * Redirection ready! * * 21-Jan-1999 (Eric Kohl ) * Added check for invalid filenames. * * 23-Jan-1999 (Eric Kohl ) * Added handling of multiple filenames. */ #include "config.h" #ifdef INCLUDE_CMD_ATTRIB #include #include #include #include #include "cmd.h" static VOID PrintAttribute (LPTSTR pszPath, LPTSTR pszFile, BOOL bRecurse) { WIN32_FIND_DATA findData; HANDLE hFind; TCHAR szFullName[MAX_PATH]; LPTSTR pszFileName; /* prepare full file name buffer */ _tcscpy (szFullName, pszPath); pszFileName = szFullName + _tcslen (szFullName); /* display all subdirectories */ if (bRecurse) { /* append file name */ _tcscpy (pszFileName, pszFile); hFind = FindFirstFile (szFullName, &findData); if (hFind == INVALID_HANDLE_VALUE) { ErrorMessage (GetLastError (), pszFile); return; } do { if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) continue; if (!_tcscmp (findData.cFileName, _T(".")) || !_tcscmp (findData.cFileName, _T(".."))) continue; _tcscpy (pszFileName, findData.cFileName); _tcscat (pszFileName, _T("\\")); PrintAttribute (szFullName, pszFile, bRecurse); } while (FindNextFile (hFind, &findData)); FindClose (hFind); } /* append file name */ _tcscpy (pszFileName, pszFile); /* display current directory */ hFind = FindFirstFile (szFullName, &findData); if (hFind == INVALID_HANDLE_VALUE) { ErrorMessage (GetLastError (), pszFile); return; } do { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; _tcscpy (pszFileName, findData.cFileName); ConOutPrintf (_T("%c %c%c%c %s\n"), (findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? _T('A') : _T(' '), (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? _T('S') : _T(' '), (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? _T('H') : _T(' '), (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _T('R') : _T(' '), szFullName); } while (FindNextFile (hFind, &findData)); FindClose (hFind); } static VOID ChangeAttribute (LPTSTR pszPath, LPTSTR pszFile, DWORD dwMask, DWORD dwAttrib, BOOL bRecurse, BOOL bDirectories) { WIN32_FIND_DATA findData; HANDLE hFind; DWORD dwAttribute; TCHAR szFullName[MAX_PATH]; LPTSTR pszFileName; /* prepare full file name buffer */ _tcscpy (szFullName, pszPath); pszFileName = szFullName + _tcslen (szFullName); /* change all subdirectories */ if (bRecurse) { /* append file name */ _tcscpy (pszFileName, _T("*.*")); hFind = FindFirstFile (szFullName, &findData); if (hFind == INVALID_HANDLE_VALUE) { ErrorMessage (GetLastError (), pszFile); return; } do { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (!_tcscmp (findData.cFileName, _T(".")) || !_tcscmp (findData.cFileName, _T(".."))) continue; _tcscpy (pszFileName, findData.cFileName); _tcscat (pszFileName, _T("\\")); ChangeAttribute (szFullName, pszFile, dwMask, dwAttrib, bRecurse, bDirectories); } } while (FindNextFile (hFind, &findData)); FindClose (hFind); } /* append file name */ _tcscpy (pszFileName, pszFile); hFind = FindFirstFile (szFullName, &findData); if (hFind == INVALID_HANDLE_VALUE) { ErrorMessage (GetLastError (), pszFile); return; } do { if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; _tcscpy (pszFileName, findData.cFileName); dwAttribute = GetFileAttributes (szFullName); if (dwAttribute != 0xFFFFFFFF) { dwAttribute = (dwAttribute & ~dwMask) | dwAttrib; SetFileAttributes (szFullName, dwAttribute); } } while (FindNextFile (hFind, &findData)); FindClose (hFind); } INT cmd_attrib (LPTSTR cmd, LPTSTR param) { LPTSTR *arg; INT argc, i; TCHAR szPath[MAX_PATH]; TCHAR szFileName [MAX_PATH]; BOOL bRecurse = FALSE; BOOL bDirectories = FALSE; DWORD dwAttrib = 0; DWORD dwMask = 0; /* initialize strings */ szPath[0] = _T('\0'); szFileName[0] = _T('\0'); /* print help */ if (!_tcsncmp (param, _T("/?"), 2)) { ConOutPuts (_T("Displays or changes file attributes.\n\n" "ATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] file ...\n" " [/S [/D]]\n\n" " + Sets an attribute\n" " - Clears an attribute\n" " R Read-only file attribute\n" " A Archive file attribute\n" " S System file attribute\n" " H Hidden file attribute\n" " /S Processes matching files in the current directory\n" " and all subdirectories\n" " /D Processes direcories as well\n\n" "Type ATTRIB without a parameter to display the attributes of all files.")); return 0; } /* build parameter array */ arg = split (param, &argc); /* check for options */ for (i = 0; i < argc; i++) { if (_tcsicmp (arg[i], _T("/s")) == 0) bRecurse = TRUE; else if (_tcsicmp (arg[i], _T("/d")) == 0) bDirectories = TRUE; } /* create attributes and mask */ for (i = 0; i < argc; i++) { if (*arg[i] == _T('+')) { if (_tcslen (arg[i]) != 2) { error_invalid_parameter_format (arg[i]); freep (arg); return -1; } switch ((TCHAR)_totupper (arg[i][1])) { case _T('A'): dwMask |= FILE_ATTRIBUTE_ARCHIVE; dwAttrib |= FILE_ATTRIBUTE_ARCHIVE; break; case _T('H'): dwMask |= FILE_ATTRIBUTE_HIDDEN; dwAttrib |= FILE_ATTRIBUTE_HIDDEN; break; case _T('R'): dwMask |= FILE_ATTRIBUTE_READONLY; dwAttrib |= FILE_ATTRIBUTE_READONLY; break; case _T('S'): dwMask |= FILE_ATTRIBUTE_SYSTEM; dwAttrib |= FILE_ATTRIBUTE_SYSTEM; break; default: error_invalid_parameter_format (arg[i]); freep (arg); return -1; } } else if (*arg[i] == _T('-')) { if (_tcslen (arg[i]) != 2) { error_invalid_parameter_format (arg[i]); freep (arg); return -1; } switch ((TCHAR)_totupper (arg[i][1])) { case _T('A'): dwMask |= FILE_ATTRIBUTE_ARCHIVE; dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE; break; case _T('H'): dwMask |= FILE_ATTRIBUTE_HIDDEN; dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN; break; case _T('R'): dwMask |= FILE_ATTRIBUTE_READONLY; dwAttrib &= ~FILE_ATTRIBUTE_READONLY; break; case _T('S'): dwMask |= FILE_ATTRIBUTE_SYSTEM; dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM; break; default: error_invalid_parameter_format (arg[i]); freep (arg); return -1; } } } if (argc == 0) { DWORD len; len = GetCurrentDirectory (MAX_PATH, szPath); if (szPath[len-1] != _T('\\')) { szPath[len] = _T('\\'); szPath[len + 1] = 0; } _tcscpy (szFileName, _T("*.*")); PrintAttribute (szPath, szFileName, bRecurse); } else { /* get full file name */ for (i = 0; i < argc; i++) { if ((*arg[i] != _T('+')) && (*arg[i] != _T('-')) && (*arg[i] != _T('/'))) { LPTSTR p; GetFullPathName (arg[i], MAX_PATH, szPath, NULL); p = _tcsrchr (szPath, _T('\\')) + 1; _tcscpy (szFileName, p); *p = _T('\0'); if (dwMask == 0) PrintAttribute (szPath, szFileName, bRecurse); else ChangeAttribute (szPath, szFileName, dwMask, dwAttrib, bRecurse, bDirectories); } } } freep (arg); return 0; } #endif /* INCLUDE_CMD_ATTRIB */