rm.c - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       rm.c (1441B)
       ---
            1 /* See LICENSE file for copyright and license details. */
            2 #include <fcntl.h>
            3 #include  <string.h>
            4 
            5 #include "fs.h"
            6 #include "util.h"
            7 
            8 static void
            9 usage(void)
           10 {
           11         eprintf("usage: %s [-f] [-iRr] file ...\n", argv0);
           12 }
           13 
           14 static int
           15 forbidden(char *path, struct stat *root)
           16 {
           17         char *s, *t;
           18         size_t n;
           19         struct stat st;
           20         static int w1, w2;
           21 
           22         n = strlen(path);
           23         for (t = path + n; t > path && t[-1] == '/'; --t)
           24                 ;
           25         for (s = t; s > path && s[-1] != '/'; --s)
           26                 ;
           27         n = t - s;
           28         if (n == 1 && *s == '.' || n == 2 && s[0] == '.' && s[1] == '.') {
           29                 if (!w1)
           30                         weprintf("\".\" and \"..\" may not be removed\n");
           31                 w1 = 1;
           32                 return 1;
           33         }
           34 
           35         if (stat(path, &st) < 0)
           36                 return 0;
           37         if (st.st_dev == root->st_dev && st.st_ino == root->st_ino) {
           38                 if (!w2)
           39                         weprintf("\"/\" may not be removed\n");
           40                 w2 = 1;
           41                 return 1;
           42         }
           43 
           44         return 0;
           45 }
           46 
           47 int
           48 main(int argc, char *argv[])
           49 {
           50         char *s;
           51         struct stat st;
           52         struct recursor r = { .fn = rm, .maxdepth = 1, .follow = 'P' };
           53 
           54         ARGBEGIN {
           55         case 'f':
           56                 r.flags |= SILENT | IGNORE;
           57                 break;
           58         case 'i':
           59                 r.flags |= CONFIRM;
           60                 break;
           61         case 'R':
           62         case 'r':
           63                 r.maxdepth = 0;
           64                 break;
           65         default:
           66                 usage();
           67         } ARGEND
           68 
           69         if (!argc) {
           70                 if (!(r.flags & IGNORE))
           71                         usage();
           72                 else
           73                         return 0;
           74         }
           75 
           76         if (stat("/", &st) < 0)
           77                 eprintf("stat root:");
           78         for (; *argv; argc--, argv++) {
           79                 if (forbidden(*argv, &st)) {
           80                         rm_status = 1;
           81                         continue;
           82                 }
           83                 recurse(AT_FDCWD, *argv, NULL, &r);
           84         }
           85 
           86         return rm_status || recurse_status;
           87 }