314 lines
7.2 KiB
C
314 lines
7.2 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
killfile.c
|
|
|
|
Abstract:
|
|
|
|
Performs a test of the file enumeration code.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 14-Jan-1998
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
BOOL
|
|
pKillEverything (
|
|
PCTSTR Pattern,
|
|
BOOL Root
|
|
);
|
|
|
|
|
|
UINT g_Dirs, g_Files;
|
|
|
|
VOID
|
|
HelpAndExit (
|
|
VOID
|
|
)
|
|
{
|
|
printf ("Command line syntax:\n\n"
|
|
"kf [-sf|-sd|-s] [-l] <pattern>\n\n"
|
|
"<pattern> Specifies pattern of file(s) or dir(s)\n"
|
|
"\n"
|
|
"Options:\n"
|
|
"\n"
|
|
"-sf Search all subdirs for matching files, then kill them\n"
|
|
"-sd Search all subdirs for matching dirs, then kill them\n"
|
|
"-s Kill all matches of <pattern> in any subdir\n"
|
|
"-l List kill candidates; don't kill them\n"
|
|
);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
|
|
HANDLE g_hHeap;
|
|
HINSTANCE g_hInst;
|
|
BOOL g_DeleteFile = TRUE;
|
|
BOOL g_DeleteDir = FALSE;
|
|
BOOL g_Recursive = FALSE;
|
|
BOOL g_ListOnly = FALSE;
|
|
|
|
INT
|
|
__cdecl
|
|
_tmain (
|
|
INT argc,
|
|
TCHAR *argv[]
|
|
)
|
|
{
|
|
PCTSTR Pattern = NULL;
|
|
PCTSTR FilePattern = NULL;
|
|
INT i;
|
|
DWORD d;
|
|
BOOL DefaultOptions = TRUE;
|
|
|
|
g_hHeap = GetProcessHeap();
|
|
|
|
for (i = 1 ; i < argc ; i++) {
|
|
|
|
if (argv[i][0] == TEXT('-') || argv[i][0] == TEXT('/')) {
|
|
switch (_totlower (argv[i][1])) {
|
|
|
|
case TEXT('s'):
|
|
if (g_Recursive) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
g_Recursive = TRUE;
|
|
switch (_totlower (argv[i][2])) {
|
|
|
|
case TEXT('f'):
|
|
g_DeleteFile = TRUE;
|
|
g_DeleteDir = FALSE;
|
|
DefaultOptions = FALSE;
|
|
break;
|
|
|
|
case TEXT('d'):
|
|
g_DeleteFile = FALSE;
|
|
g_DeleteDir = TRUE;
|
|
DefaultOptions = FALSE;
|
|
break;
|
|
|
|
case 0:
|
|
g_DeleteFile = TRUE;
|
|
g_DeleteDir = TRUE;
|
|
DefaultOptions = FALSE;
|
|
break;
|
|
|
|
default:
|
|
HelpAndExit();
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case TEXT('l'):
|
|
g_ListOnly = TRUE;
|
|
break;
|
|
|
|
default:
|
|
HelpAndExit();
|
|
}
|
|
}
|
|
|
|
else if (Pattern) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
else {
|
|
Pattern = argv[i];
|
|
}
|
|
}
|
|
|
|
if (!Pattern || !Pattern[0]) {
|
|
HelpAndExit();
|
|
}
|
|
|
|
d = GetFileAttributes (Pattern);
|
|
if (d != INVALID_ATTRIBUTES && (d & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
if (DefaultOptions) {
|
|
g_DeleteDir = TRUE;
|
|
}
|
|
}
|
|
|
|
pKillEverything (Pattern, TRUE);
|
|
|
|
printf ("\nFiles: %u Dirs: %u\n\n", g_Files, g_Dirs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pKillPattern (
|
|
PCTSTR Pattern
|
|
)
|
|
{
|
|
FILE_ENUM e;
|
|
TCHAR CurrentDir[MAX_TCHAR_PATH];
|
|
|
|
GetCurrentDirectory (MAX_TCHAR_PATH, CurrentDir);
|
|
|
|
if (EnumFirstFile (&e, CurrentDir, Pattern)) {
|
|
do {
|
|
if (e.Directory && !g_DeleteDir) {
|
|
continue;
|
|
}
|
|
|
|
if (!e.Directory && !g_DeleteFile) {
|
|
continue;
|
|
}
|
|
|
|
if (e.Directory) {
|
|
g_Dirs++;
|
|
} else {
|
|
g_Files++;
|
|
}
|
|
|
|
if (g_ListOnly) {
|
|
_tprintf (TEXT("%s\n"), e.FullPath);
|
|
} else {
|
|
SetCurrentDirectory (CurrentDir);
|
|
SetFileAttributes (e.FullPath, FILE_ATTRIBUTE_NORMAL);
|
|
|
|
if (e.Directory) {
|
|
|
|
if (!RemoveCompleteDirectory (e.FullPath)) {
|
|
_tprintf (TEXT("Can't kill directory %s, GLE=%u\n"), e.FullPath, GetLastError());
|
|
}
|
|
} else if (!DeleteFile (e.FullPath)) {
|
|
_tprintf (TEXT("Can't kill %s, GLE=%u\n"), e.FullPath, GetLastError());
|
|
}
|
|
}
|
|
} while (EnumNextFile (&e));
|
|
}
|
|
|
|
SetCurrentDirectory (CurrentDir);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pKillEverything (
|
|
PCTSTR Pattern,
|
|
BOOL Root
|
|
)
|
|
{
|
|
TCHAR FilePattern[MAX_TCHAR_PATH];
|
|
TCHAR SubPattern[MAX_TCHAR_PATH];
|
|
TCHAR CurrentDir[MAX_TCHAR_PATH];
|
|
PCTSTR p;
|
|
PCTSTR q;
|
|
PCTSTR NextPattern;
|
|
FILE_ENUM e;
|
|
DWORD d;
|
|
TCHAR c = TEXT('\\');
|
|
|
|
GetCurrentDirectory (MAX_TCHAR_PATH, CurrentDir);
|
|
|
|
if (!Pattern || !Pattern[0]) {
|
|
lstrcpy (FilePattern, TEXT("*.*"));
|
|
NextPattern = NULL;
|
|
} else {
|
|
p = _tcschr (Pattern, TEXT('\\'));
|
|
if (!p) {
|
|
p = GetEndOfString (Pattern);
|
|
} else {
|
|
q = _tcschr (Pattern, TEXT(':'));
|
|
if (q && p > q) {
|
|
if (Root) {
|
|
p++;
|
|
c = 0;
|
|
} else {
|
|
_tprintf (TEXT("Pattern is bad: %s\n"), Pattern);
|
|
return FALSE;
|
|
}
|
|
} else if (p == Pattern) {
|
|
if (Root) {
|
|
p++;
|
|
c = 0;
|
|
} else {
|
|
_tprintf (TEXT("Pattern is bad: %s\n"), Pattern);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
StringCopyAB (FilePattern, Pattern, p);
|
|
|
|
if (*p) {
|
|
NextPattern = p;
|
|
if (*NextPattern == c) {
|
|
NextPattern++;
|
|
}
|
|
} else {
|
|
NextPattern = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If NextPattern is NULL, then we must delete this pattern
|
|
//
|
|
|
|
if (!NextPattern) {
|
|
if (g_Recursive) {
|
|
wsprintf (SubPattern, TEXT("*.*\\%s"), Pattern);
|
|
if (!pKillEverything (SubPattern, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
pKillPattern (Pattern);
|
|
}
|
|
|
|
//
|
|
// Otherwise we enumerate the files and dirs at this level,
|
|
// and apply the rest of the pattern to the subdirs
|
|
//
|
|
|
|
else {
|
|
d = GetFileAttributes (FilePattern);
|
|
|
|
if (d != INVALID_ATTRIBUTES && (d & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
if (!SetCurrentDirectory (FilePattern)) {
|
|
_tprintf (TEXT("Can't change dir to %s\n"), FilePattern);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!pKillEverything (NextPattern, FALSE)) {
|
|
return FALSE;
|
|
}
|
|
|
|
} else if (EnumFirstFile (&e, TEXT("."), FilePattern)) {
|
|
|
|
do {
|
|
if (e.Directory) {
|
|
SetCurrentDirectory (CurrentDir);
|
|
|
|
if (SetCurrentDirectory (e.FileName)) {
|
|
if (!pKillEverything (NextPattern, FALSE)) {
|
|
AbortFileEnum (&e);
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
} while (EnumNextFile (&e));
|
|
}
|
|
}
|
|
|
|
SetCurrentDirectory (CurrentDir);
|
|
return TRUE;
|
|
}
|
|
|
|
|