rm.c (1733B)
1 #include <u.h> 2 #include <sys/stat.h> 3 #include <libc.h> 4 5 #define rmdir p9rmdir 6 7 char errbuf[ERRMAX]; 8 int ignerr = 0; 9 10 static void 11 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 } 19 20 int 21 issymlink(char *name) 22 { 23 struct stat s; 24 return lstat(name, &s) >= 0 && S_ISLNK(s.st_mode); 25 } 26 27 /* 28 * f is a non-empty directory. Remove its contents and then it. 29 */ 30 void 31 rmdir(char *f) 32 { 33 char *name; 34 int fd, i, j, n, ndir, nname; 35 Dir *dirbuf; 36 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 } 48 49 nname = strlen(f)+1+STATMAX+1; /* plenty! */ 50 name = malloc(nname); 51 if(name == 0){ 52 err("memory allocation"); 53 return; 54 } 55 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 else 65 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 void 80 main(int argc, char *argv[]) 81 { 82 int i; 83 int recurse; 84 char *f; 85 Dir *db; 86 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 }ARGEND 100 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 else 108 err(f); 109 free(db); 110 } 111 exits(errbuf); 112 }