Windows-Server-2003/sdktools/rm/rm.c

266 lines
8.5 KiB
C

/*** RM.C - a generalized remove and unremove mechanism ***********************
*
* Copyright (c) 1987-1990, Microsoft Corporation. All rights reserved.
*
* Purpose:
* The three tools EXP, RM and UNDEL are used to delete files so
* that they can be undeleted. This is done my renaming the file into
* a hidden directory called DELETED.
*
* Notes:
* All deleted files are kept in the directory .\deleted with a unique name.
* The names are then kept in .\deleted\index.
* deleted name (RM_RECLEN bytes).
* The rm command will rename to the appropriate directory and make an entry.
* the undelete command will rename back if there is a single item otherwise
* it will give a list of alternatives. The exp command will free all deleted
* objects.
*
* Revision History:
* 07-Feb-1990 bw Add 'void' to walk() definition
* 08-Jan-1990 SB SLM version upgrading added; Add CopyRightYrs Macro
* 03-Jan-1990 SB define QH_TOPIC_NOT_FOUND
* 21-Dec-1989 SB Changes for new index file format
* 20-Dec-1989 SB Add check for return code of 3 for qh
* 14-Dec-1989 LN Update Copyright to include 1990
* 23-Oct-1989 LN Version no bumped to 1.01
* 12-Oct-1989 LN Changed Usage message
* 02-Oct-1989 LN Changed Version no to 1.00
* 08-Aug-1989 BW Add Version number and update copyright.
* 15-May-1987 WB Add /help
* 22-Apr-1987 DL Add /k
* 06-Apr-1987 BW Add copyright notice to usage.
* 30-Mar-1990 BW Get help on RM.EXE, not EXP.EXE
* 17-Oct-1990 w-barry Temporarily replaced 'rename' with 'rename_NT' until
* DosMove is completely implemented on NT.
*
******************************************************************************/
/* I N C L U D E Files */
#include <process.h>
#include <string.h>
/* Next two from ZTools */
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <tools.h>
/* D E F I N E s */
#define CopyRightYrs "1987-98"
/* Need 2 steps, first to get correct values in and 2nd to paste them */
/* paste() is hacked to allow LEADING ZEROES */
#define paste(a, b, c) #a ".0" #b ".00" #c
#define VERSION(major, minor, buildno) paste(major, minor, buildno)
#define QH_TOPIC_NOT_FOUND 3
/* G L O B A L s */
flagType fRecursive = FALSE; /* TRUE => descend tree */
flagType fPrompt = FALSE; /* TRUE => query for removal */
flagType fForce = FALSE; /* TRUE => no query for R/O files */
flagType fKeepRO = FALSE; /* TRUE => keep R/O files */
flagType fTakeOwnership = FALSE; /* TRUE => attempt takeown if fail */
flagType fExpunge = FALSE; /* TRUE => expunge immediately */
flagType fDelayUntilReboot = FALSE; /* TRUE => do delete next reboot */
// Forward Function Declarations...
void Usage( void );
void walk( char *, struct findType *, void * );
#if 0
extern BOOL TakeOwnership( char *lpFileName );
#endif /* 0 */
void Usage()
{
printf(
"Microsoft File Removal Utility. Version %s\n"
"Copyright (C) Microsoft Corp %s. All rights reserved.\n\n"
"Usage: RM [/help] [/ikft] [/x [/d]] [/r dir] files\n"
" /help invoke Quick Help for this utility\n"
" /i inquire of user for each file for permission to remove\n"
" /k keep read only files, no prompting to remove them\n"
" /r dir recurse into subdirectories\n"
" /f force delete of read only files without prompting\n"
" /t attempt to take ownership of file if delete fails\n"
" /x dont save deleted files in deleted subdirectory\n"
" /d delay until next reboot.\n",
VERSION(rmj, rmm, rup), CopyRightYrs);
exit(1);
}
void walk(p, b, dummy)
char *p;
struct findType *b;
void * dummy;
{
char buf[MAX_PATH];
int i, rc;
if (strcmp(b->fbuf.cFileName, ".") && strcmp(b->fbuf.cFileName, "..") &&
_strcmpi(b->fbuf.cFileName, "deleted")) {
if (HASATTR(b->fbuf.dwFileAttributes,FILE_ATTRIBUTE_DIRECTORY)) {
if (fRecursive) {
switch (strend(p)[-1]) {
case '/':
case '\\':
sprintf(buf, "%s*.*", p);
break;
default:
sprintf(buf, "%s\\*.*", p);
}
forfile(buf, -1, walk, NULL);
}
}
else if (fKeepRO && HASATTR(b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_READONLY)) {
printf("%s skipped\n", p);
return;
}
else {
if (fPrompt || (!fForce && HASATTR(b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_READONLY))) {
printf("%s? ", p);
fflush(stdout);
switch (_getch()) {
case 'y':
case 'Y':
printf("Yes\n");
break;
case 'p':
case 'P':
printf("Proceeding without asking again\n");
fPrompt = FALSE;
break;
default:
printf(" skipped\n");
return;
}
}
fflush(stdout);
if (HASATTR(b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_READONLY))
SetFileAttributes(p, b->fbuf.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
for (i=0; i<2; i++) {
if (fExpunge) {
if (fDelayUntilReboot) {
if (MoveFileEx(p, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) {
rc = 0;
}
else {
rc = 1;
}
}
else
if (DeleteFile(p)) {
rc = 0;
}
else {
rc = 1;
}
}
else {
rc = fdelete(p);
}
#if 0
if (rc == 0 || !fTakeOwnership) {
break;
}
printf( "%s file not deleted - attempting to take ownership and try again.\n" );
if (!TakeOwnership( p )) {
printf( "%s file not deleted - unable to take ownership.\n" );
rc = 0;
break;
}
#else
break;
#endif /* 0 */
}
switch (rc) {
case 0:
break;
case 1:
printf("%s file does not exist\n" , p);
break;
case 2:
printf("%s rename failed: %s\n", p, error());
break;
default:
printf("%s internal error: %s\n", p, error());
break;
}
}
}
dummy;
}
__cdecl main(c, v)
int c;
char *v[];
{
register char *p;
int iRetCode;
ConvertAppToOem( c, v );
SHIFT(c,v);
while (c && fSwitChr(*v[0])) {
p = *v;
while (*++p != '\0')
switch (*p) {
case 'f':
fForce = TRUE;
break;
case 'i':
fPrompt = TRUE;
break;
case 'k':
fKeepRO = TRUE;
break;
case 'r':
fRecursive = TRUE;
break;
case 't':
fTakeOwnership = TRUE;
break;
case 'x':
fExpunge = TRUE;
break;
case 'd':
if (fExpunge) {
fDelayUntilReboot = TRUE;
break;
}
// Fall thru if /d without /x
case 'h':
if (!_strcmpi(p, "help")) {
iRetCode = (int) _spawnlp(P_WAIT, "qh.exe", "qh", "/u",
"rm.exe", NULL);
/* When qh returns QH_TOPIC_NOT_FOUND or when we
* get -1 (returned when the spawn fails) then
* give Usage() message
*/
if (iRetCode != QH_TOPIC_NOT_FOUND && iRetCode != -1)
exit(0);
}
/*
* else fall thru...
*/
default:
Usage();
}
SHIFT(c,v);
}
while (c) {
if (!forfile(*v, -1, walk, NULL)) {
printf("%s does not exist\n", *v);
}
SHIFT(c,v);
}
return(0);
}