POSIX mandates that the protection should care about the basename, and we cannot use basename because it can modify the input string and it would make harder later operations. Also, it would put a limit in the length of the name of the paths and POSIX forbids limitations about that regard in rm(1). --- rm.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/rm.c b/rm.c index 1f23c09..c1ae4fd 100644 --- a/rm.c +++ b/rm.c @@ -11,9 +11,29 @@ usage(void) eprintf("usage: %s [-f] [-iRr] file ...\n", argv0); } +static int +dotdot(char *path) +{ + char *s, *t; + size_t len; + + len = strlen(path); + for (t = path + len; t > path && t[-1] == '/'; --t) + ; + for (s = t; s > path && s[-1] != '/'; --s) + ; + + if (t - s == 1 && *s == '.') + return 1; + if (t - s == 2 && s[0] == '.' && s[1] == '.') + return 1; + return 0; +} + int main(int argc, char *argv[]) { + char *s; struct recursor r = { .fn = rm, .maxdepth = 1, .follow = 'P' }; ARGBEGIN { @@ -39,8 +59,12 @@ main(int argc, char *argv[]) } for (; *argv; argc--, argv++) { - if (strcmp(*argv, ".") && strcmp(*argv, "..")) - recurse(AT_FDCWD, *argv, NULL, &r); + if (dotdot(*argv)) { + weprintf("\".\" and \"..\" may not be removed"); + rm_status = 1; + continue; + } + recurse(AT_FDCWD, *argv, NULL, &r); } return rm_status || recurse_status; -- 2.46.1