ref: 94443daf8e248e65afc8d3f17f26efea22748b51
dir: /utils/rm/rm-Nt.c/
#include <lib9.h>
#include <windows.h>
typedef struct Direntry
{
int isdir;
char *name;
} Direntry;
char errbuf[ERRMAX];
long ndirbuf = 0;
int ignerr = 0;
void
err(char *f)
{
if(!ignerr){
errstr(errbuf, sizeof errbuf);
fprint(2, "rm: %s: %s\n", f, errbuf);
}
}
int
badentry(char *filename)
{
if(*filename == 0)
return 1;
if(filename[0] == '.'){
if(filename[1] == 0)
return 1;
if(filename[1] == '.' && filename[2] == 0)
return 1;
}
return 0;
}
/*
* Read a whole directory before removing anything as the holes formed
* by removing affect the read offset.
*/
Direntry*
readdirect(char *path)
{
long n;
HANDLE h;
Direntry *d;
char fullpath[MAX_PATH];
WIN32_FIND_DATA data;
snprint(fullpath, MAX_PATH, "%s\\*.*", path);
h = FindFirstFile(fullpath, &data);
if(h == INVALID_HANDLE_VALUE)
err(path);
n = 0;
d = 0;
for(;;){
if(!badentry(data.cFileName)){
d = realloc(d, (n+2)*sizeof(Direntry));
if(d == 0){
err("memory allocation");
exits(errbuf);
}
d[n].name = malloc(strlen(data.cFileName)+1);
if(d[n].name == 0){
err("memory allocation");
exits(errbuf);
}
strcpy(d[n].name, data.cFileName);
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
d[n].isdir = 1;
else
d[n].isdir = 0;
n++;
}
if(FindNextFile(h, &data) == 0)
break;
}
FindClose(h);
if(d){
d[n].name = 0;
d[n].isdir = 0;
}
return d;
}
/*
* f is a non-empty directory. Remove its contents and then it.
*/
void
Ntrmdir(char *f)
{
Direntry *dp, *dq;
char name[MAX_PATH];
dq = readdirect(f);
if(dq == 0)
return;
for(dp = dq; dp->name; dp++){
snprint(name, MAX_PATH, "%s/%s", f, dp->name);
if(remove(name) == -1){
if(dp->isdir == 0)
err(name);
else
if(RemoveDirectory(name) == 0)
Ntrmdir(name);
}
free(dp->name);
}
if(RemoveDirectory(f) == 0)
err(f);
free(dq);
}
void
main(int argc, char *argv[])
{
int i;
int recurse;
char *f;
Dir *db;
ignerr = 0;
recurse = 0;
ARGBEGIN{
case 'r':
recurse = 1;
break;
case 'f':
ignerr = 1;
break;
default:
fprint(2, "usage: rm [-fr] file ...\n");
exits("usage");
}ARGEND
for(i=0; i<argc; i++){
f = argv[i];
if(remove(f) != -1)
continue;
if((db = dirstat(f)) == nil || (db->qid.type&QTDIR) ==0)
err(f);
else if(RemoveDirectory(f) == 0)
if(recurse)
Ntrmdir(f);
else
err(f);
}
exits(errbuf);
}