#include #include #include #include #include #include #include unsigned int f_flag; int get_stat(const char *path, struct stat *stat_path) { if (lstat(path, stat_path)) { if (!f_flag) fprintf(stderr, "rm: unable to stat %s: %s\n", path, strerror(errno)); return 1; } return 0; } char *make_path(const char *src, const char *dst) { size_t len = strlen(src) + strlen(dst) + 2; char *full_path = malloc(len + 1); if (full_path == NULL) { fprintf(stderr, "rm: malloc() returned NULL\n"); return NULL; } snprintf(full_path, len, "%s/%s", src, dst); return full_path; } int rmtree(const char *path) { struct stat stat_path; if (get_stat(path, &stat_path)) return 1; if (!S_ISDIR(stat_path.st_mode) || S_ISLNK(stat_path.st_mode)) { if (unlink(path) < 0) { if (!f_flag) fprintf(stderr, "rm: %s: is not directory\n", path); return 1; } return 0; } DIR *dir = opendir(path); if (dir == NULL) { if (!f_flag) fprintf(stderr, "rm: %s: Can`t open directory\n", path); return 1; } struct dirent *ep; while ((ep = readdir(dir)) != NULL) { if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..")) continue; char *full_path = make_path(path, ep->d_name); if (full_path == NULL) continue; rmtree(full_path); free(full_path); } closedir(dir); if (rmdir(path) < 0) if (!f_flag) fprintf(stderr, "rm: %s: can`t remove a directory\n", path); return 0; } int main(const int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; else if (!strcmp(argv[i], "-f")) f_flag = 1; else if (!strcmp(argv[i], "--help")) { printf("rm [-f force] [src1 src2...]\n"); return 0; } } int status = 0; for (; i < argc; i++) { if (!strcmp(argv[i], ".") || !strcmp(argv[i], "..")){ printf("rm: refusing to remove '.' or '..' directory\n"); break; } int status = rmtree(argv[i]); if (status != 0) status = 1; } return status; }