/* * @(#) eraser.c - Program for file and directory unrecoverable deletion. * (c) 1996 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: ANSI C * Tested with: Watcom C16 v10.0 * Last modified: 1996-07-18 14:20:00 GMT+04:00 */ #include #include #include #include #include #include #include #include /* */ #define DRIVESPEC ':' /* Drive letter delimiter in MS-DOS */ #define DELIMITER '\\' /* MS-DOS style of directory names delimiter */ #ifndef PATH_MAX #define PATH_MAX FILENAME_MAX /* MS-DOS style of path name length */ #endif #define FILE_EXT 3 /* size of file name extension */ #define SPECIALCH '.' /* for '.' and '..' files */ #define BLANKCH '~' #define BUFSIZEMAX 16384 /* <= INT_MAX */ #define BUFBLOCKSIZE 1024 void printerror(char *errmsg,char *path) { fputs("Error ",stderr); fputs(errmsg,stderr); fputs(": ",stderr); fputs(path,stderr); fputs("\n",stderr); } int getfilestat(char *path) { struct stat info; if (!stat(path,&info)) if (S_ISDIR(info.st_mode)) return (1); else if (S_ISREG(info.st_mode)) return (0); return (-1); } int testpathname(char *path) { char *pc=strchr(path,'\0')-1; if (*pc==DELIMITER) if (path==pc || *(pc-1)==DRIVESPEC) return (3); else *(pc--)='\0'; else if (*pc==DRIVESPEC) { *(++pc)=SPECIALCH; *(pc+1)='\0'; } if (*pc==SPECIALCH && (path==pc || *(pc-1)==DELIMITER || *(pc-1)==DRIVESPEC || *(pc-1)==SPECIALCH && (path==pc-1 || *(pc-2)==DELIMITER || *(pc-2)==DRIVESPEC))) return (2); return (getfilestat(path)); } int readdirectoryentry(DIR *dirp,char *path,int isdir) { struct dirent *entry; do entry=readdir(dirp); while (entry && (entry->d_name[0]==SPECIALCH && (!entry->d_name[1] || entry->d_name[1]==SPECIALCH) || (strcpy(strrchr(path,DELIMITER)+1,&entry->d_name[0]), getfilestat(path)!=isdir))); return (!!entry); } int blankfile(char *path,char *buf,size_t bufsize) { int fid; off_t left; unsigned len; if ((fid=open(path,O_RDWR))<0) { printerror("opening file",path); return (1); } if ((left=lseek(fid,0,SEEK_END))<0) { close(fid); printerror("seeking file",path); return (1); } if (lseek(fid,0,SEEK_SET)<0) { close(fid); printerror("preparing to blank file",path); return (1); } if (!left) left++; left=(left+BUFBLOCKSIZE-1)/BUFBLOCKSIZE*BUFBLOCKSIZE; for (;left>0;left-=len) if (write(fid,buf,(len=leftd_name[0])); if (!entry) { closedir(dirp); printerror("finding",path); *name='\0'; if (!(dirp=opendir(path))) { printerror("rewinding directory",path); *subdir=0; return (2); } *name=DELIMITER; *subdir=readdirectoryentry(dirp,path,1); closedir(dirp); if (!*subdir) *name='\0'; return (1); } } else *(name+1)='\0'; *subdir=readdirectoryentry(dirp,path,1); closedir(dirp); if (!*subdir) *name='\0'; return (0); } int deletesubdir(char *path,char *buf,size_t bufsize,char *blankname) { int err=0; int level=1; int subdir=1; do { err+=searchdirectory(path,&subdir); if (!subdir) err+=scandirectory(path,buf,bufsize,blankname); subdir? level++ : level--; } while (level); return (err); } int deleterootdir(char *path,char *buf,size_t bufsize,char *blankname) { int err=0; DIR *dirp=opendir(path); if (!dirp) { printerror("opening root directory",path); return (1); } while (readdirectoryentry(dirp,path,1)) err+=deletesubdir(path,buf,bufsize,blankname); closedir(dirp); *(strrchr(path,DELIMITER)+1)='\0'; err+=scandirectory(path,buf,bufsize,blankname); return (err); } int main(int argc,char *argv[]) { int err=0; int cnt; char *buf; size_t bufsize=BUFSIZEMAX; static char path[PATH_MAX+NAME_MAX+2]; static char blankname[NAME_MAX+1]; if (argc<2) { puts("Files and Directories Complete Deletion Utility.\n" "Usage:\n" " ERASER pathname [...]"); return (2); } while (bufsize>0 && !(buf=(char *)calloc(bufsize,sizeof(char)))) bufsize-=BUFBLOCKSIZE; if (!buf) { fputs("Error: Not enough memory!\n",stderr); return (3); } for (cnt=0;cnt