| rm.c - sbase - suckless unix tools | |
| git clone git://git.suckless.org/sbase | |
| Log | |
| Files | |
| Refs | |
| README | |
| 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 } |