Blob
1 #include <u.h>2 #include <sys/stat.h>3 #include <libc.h>5 #define rmdir p9rmdir7 char errbuf[ERRMAX];8 int ignerr = 0;10 static void11 err(char *f)12 {13 if(!ignerr){14 errbuf[0] = '\0';15 errstr(errbuf, sizeof errbuf);16 fprint(2, "rm: %s: %s\n", f, errbuf);17 }18 }20 int21 issymlink(char *name)22 {23 struct stat s;24 return lstat(name, &s) >= 0 && S_ISLNK(s.st_mode);25 }27 /*28 * f is a non-empty directory. Remove its contents and then it.29 */30 void31 rmdir(char *f)32 {33 char *name;34 int fd, i, j, n, ndir, nname;35 Dir *dirbuf;37 fd = open(f, OREAD);38 if(fd < 0){39 err(f);40 return;41 }42 n = dirreadall(fd, &dirbuf);43 close(fd);44 if(n < 0){45 err("dirreadall");46 return;47 }49 nname = strlen(f)+1+STATMAX+1; /* plenty! */50 name = malloc(nname);51 if(name == 0){52 err("memory allocation");53 return;54 }56 ndir = 0;57 for(i=0; i<n; i++){58 snprint(name, nname, "%s/%s", f, dirbuf[i].name);59 if(remove(name) != -1 || issymlink(name))60 dirbuf[i].qid.type = QTFILE; /* so we won't recurse */61 else{62 if(dirbuf[i].qid.type & QTDIR)63 ndir++;64 else65 err(name);66 }67 }68 if(ndir)69 for(j=0; j<n; j++)70 if(dirbuf[j].qid.type & QTDIR){71 snprint(name, nname, "%s/%s", f, dirbuf[j].name);72 rmdir(name);73 }74 if(remove(f) == -1)75 err(f);76 free(name);77 free(dirbuf);78 }79 void80 main(int argc, char *argv[])81 {82 int i;83 int recurse;84 char *f;85 Dir *db;87 ignerr = 0;88 recurse = 0;89 ARGBEGIN{90 case 'r':91 recurse = 1;92 break;93 case 'f':94 ignerr = 1;95 break;96 default:97 fprint(2, "usage: rm [-fr] file ...\n");98 exits("usage");99 }ARGEND100 for(i=0; i<argc; i++){101 f = argv[i];102 if(remove(f) != -1)103 continue;104 db = nil;105 if(recurse && (db=dirstat(f))!=nil && (db->qid.type&QTDIR))106 rmdir(f);107 else108 err(f);109 free(db);110 }111 exits(errbuf);112 }