rm.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       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 }