rm.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 330 行
C
330 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: POSIX rm utility
* Removes files and directories
*
****************************************************************************/
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>
#include <direct.h>
#include <conio.h>
#include "lineprt.h"
#include "misc.h"
#include "getopt.h"
#include "filerx.h"
#include "fnutils.h"
char *OptEnvVar = "rm";
static const char *usageMsg[] = {
"Usage: rm [-?firRsvX] [files]",
"\tfiles : files/directories to delete",
"\tOptions: -? : print this list",
"\t\t -f : force deletion of read-only files",
"\t\t and don't complain about non existant files / dirs",
"\t\t -i : inquire about each deletion",
"\t\t -r : recursively delete all directories",
"\t\t -R : recursively delete all directories",
"\t\t -s : silent operation (default)",
"\t\t -v : verbose operation",
"\t\t -X : match files by regular expressions",
NULL
};
int rflag = FALSE;
int iflag = FALSE;
int fflag = FALSE;
int sflag = TRUE;
int rxflag = FALSE;
int error_occured = 0;
typedef struct dd {
struct dd *next;
char attr;
char name[1];
} iolist;
void DoRM( const char *f );
void RecursiveRM( const char *dir );
/* start of mainline */
int main( int argc, char *argv[] )
{
int i;
int ch;
DIR *d;
/* process options */
while( ( ch = GetOpt( &argc, argv, "firRsvX", usageMsg ) ) != -1 ) {
switch( ch ) {
case 'f': fflag = TRUE; iflag = FALSE; break;
case 'i': iflag = TRUE; fflag = FALSE; break;
case 'R':
case 'r': rflag = TRUE; break;
case 's': sflag = TRUE; break;
case 'v': sflag = FALSE; break;
case 'X': rxflag = TRUE; break;
}
}
if( argc < 2 )
Quit( usageMsg, "No filename/directory specified\n" );
StartPrint();
/* process -r option */
if( rflag ) {
for( i = 1; i < argc; i++ ) {
if( strcmp( argv[i], rxflag ? "*" : "*.*" ) == 0 )
RecursiveRM( "." );
else {
d = FileNameWild( argv[i], rxflag ) ? NULL : opendir( argv[i] );
if( d != NULL ) {
if( !( d->d_attr & _A_SUBDIR ) ) {
closedir( d );
if( fflag )
DoRM( argv[i] );
else
PrintALineThenDrop( "%s is not a directory.", argv[i] );
} else {
closedir( d );
RecursiveRM( argv[i] );
}
} else if( !fflag ) {
PrintALineThenDrop( "Directory %s not found.", argv[i] );
error_occured = 1;
}
}
}
} else {
/* run through all specified files */
for( i = 1; i < argc; i++ )
DoRM( argv[i] );
}
DropALine();
return( error_occured );
}
/* DoRM - perform RM on a specified file */
void DoRM( const char *f )
{
iolist *fhead = NULL;
iolist *ftail = NULL;
iolist *tmp;
iolist *dhead = NULL;
iolist *dtail = NULL;
char *bo;
char fpath[_MAX_PATH];
char tmppath[_MAX_PATH];
int i;
int j;
int k;
int l;
size_t len;
DIR *d;
struct dirent *nd;
char wild[_MAX_PATH];
char *err;
void *crx = NULL;
/* get file path prefix */
fpath[0] = 0;
for( i = ( int ) strlen( f ); i >= 0; i-- ) {
if( f[i] == ':' || f[i] == '\\' || f[i] == '/' ) {
fpath[i + 1] = 0;
for( j = i; j >= 0; j-- )
fpath[j] = f[j];
i = -1;
}
}
d = OpenDirAll( (char*)f, wild );
if( d == NULL ) {
PrintALineThenDrop( "File (%s) not found.", f );
if( !fflag ) {
error_occured = 1;
}
return;
}
if( rxflag ) {
err = FileMatchInit( &crx, wild );
if( err != NULL )
Die( "\"%s\": %s\n", err, wild );
}
k = ( int ) strlen( fpath );
while( ( nd = readdir( d ) ) != NULL ) {
FNameLower( nd->d_name );
if( rxflag ) {
if( !FileMatch( crx, nd->d_name ) )
continue;
} else {
if( !FileMatchNoRx( nd->d_name, wild ) )
continue;
}
/* set up file name, then try to delete it */
l = ( int ) strlen( nd->d_name );
bo = tmppath;
for( i = 0; i < k; i++ )
*bo++ = fpath[i];
for( i = 0; i < l; i++ )
*bo++ = nd->d_name[i];
*bo = 0;
if( nd->d_attr & _A_SUBDIR ) {
/* process a directory */
if( !IsDotOrDotDot( nd->d_name ) ) {
if( rflag ) {
/* build directory list */
len = strlen( tmppath );
tmp = MemAlloc( sizeof( iolist ) + len );
if( dtail == NULL )
dhead = tmp;
else
dtail->next = tmp;
dtail = tmp;
memcpy( tmp->name, tmppath, len + 1 );
} else {
PrintALineThenDrop( "%s is a directory, use -r", tmppath );
error_occured = 1;
}
}
} else if( ( nd->d_attr & _A_RDONLY ) && !fflag ) {
PrintALineThenDrop( "%s is read-only, use -f", tmppath );
error_occured = 1;
} else {
/* build file list */
len = strlen( tmppath );
tmp = MemAlloc( sizeof( iolist ) + len );
if( ftail == NULL )
fhead = tmp;
else
ftail->next = tmp;
ftail = tmp;
memcpy( tmp->name, tmppath, len + 1 );
tmp->attr = nd->d_attr;
}
}
closedir( d );
if( rxflag )
FileMatchFini( crx );
/* process any files found */
tmp = fhead;
if( tmp == NULL && !fflag ) {
PrintALineThenDrop( "File (%s) not found.", f );
error_occured = 1;
}
while( tmp != NULL ) {
if( tmp->attr & _A_RDONLY )
chmod( tmp->name, S_IWRITE | S_IREAD );
if( iflag ) {
PrintALine( "Delete %s (y\\n)", tmp->name );
while( ( i = tolower( getch() ) ) != 'y' && i != 'n' )
;
DropALine();
if( i == 'y' )
remove( tmp->name );
} else {
if( !sflag )
PrintALine( "Deleting file %s", tmp->name );
remove( tmp->name );
}
ftail = tmp;
tmp = tmp->next;
MemFree( ftail );
}
/* process any directories found */
if( rflag && ( tmp = dhead ) != NULL ) {
while( tmp != NULL ) {
RecursiveRM( tmp->name );
dtail = tmp;
tmp = tmp->next;
MemFree( dtail );
}
}
}
/* DoRMdir - perform RM on a specified directory */
void DoRMdir( const char *dir )
{
unsigned attribute;
int rc;
if( ( rc = rmdir( dir ) ) == -1 ) {
_dos_getfileattr( dir, &attribute );
if( attribute & _A_RDONLY ) {
if( fflag ) {
_dos_setfileattr( dir, _A_NORMAL );
rc = rmdir( dir );
} else {
PrintALineThenDrop( "Directory %s is read-only, use -f", dir );
error_occured = 1;
}
}
}
if( rc == -1 ) {
PrintALineThenDrop( "Unable to delete directory %s", dir );
error_occured = 1;
} else if( !sflag )
PrintALine( "Deleting directory %s", dir );
}
/* RecursiveRM - do an RM recursively on all files */
void RecursiveRM( const char *dir )
{
int i;
char fname[_MAX_PATH];
/* purge the files */
strcpy( fname, dir );
strcat( fname, ( rxflag ) ? "/*" : "/*.*" );
DoRM( fname );
/* purge the directory */
if( iflag ) {
PrintALine( "Delete directory %s (y\\n)", dir );
while( ( i = tolower( getch() ) ) != 'y' && i != 'n' )
;
DropALine();
} else
i = 'y';
if( i == 'y' )
DoRMdir( dir );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?