1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h> 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <limits.h> 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h> 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 100ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot#define OPT_RECURSIVE 1 110ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot#define OPT_FORCE 2 120ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int usage() 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 150ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot fprintf(stderr,"Usage: rm [-rR] [-f] <target>\n"); 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* return -1 on failure, with errno set to the first error */ 200ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvotstatic int unlink_recursive(const char* name, int flags) 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct stat st; 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DIR *dir; 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fail = 0; 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* is it a file or directory? */ 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (lstat(name, &st) < 0) 290ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot return ((flags & OPT_FORCE) && errno == ENOENT) ? 0 : -1; 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* a file, so unlink it */ 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!S_ISDIR(st.st_mode)) 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return unlink(name); 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* a directory, so open handle */ 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dir = opendir(name); 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (dir == NULL) 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* recurse over components */ 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = 0; 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while ((de = readdir(dir)) != NULL) { 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char dn[PATH_MAX]; 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(dn, "%s/%s", name, de->d_name); 470ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot if (unlink_recursive(dn, flags) < 0) { 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fail = 1; 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = 0; 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* in case readdir or unlink_recursive failed */ 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fail || errno < 0) { 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int save = errno; 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(dir); 57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project errno = save; 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* close directory handle */ 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (closedir(dir) < 0) 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* delete target directory */ 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return rmdir(name); 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint rm_main(int argc, char *argv[]) 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int ret; 720ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot int i, c; 730ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot int flags = 0; 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (argc < 2) 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return usage(); 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 780ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot /* check flags */ 790ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot do { 800ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot c = getopt(argc, argv, "frR"); 810ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot if (c == EOF) 820ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot break; 830ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot switch (c) { 840ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot case 'f': 850ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot flags |= OPT_FORCE; 860ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot break; 870ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot case 'r': 880ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot case 'R': 890ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot flags |= OPT_RECURSIVE; 900ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot break; 910ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot } 920ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot } while (1); 930ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot 940ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot if (optind < 1 || optind >= argc) { 950ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot usage(); 960ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot return -1; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 980ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* loop over the file/directory args */ 1000ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot for (i = optind; i < argc; i++) { 1010ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot 1020ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot if (flags & OPT_RECURSIVE) { 1030ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot ret = unlink_recursive(argv[i], flags); 1040ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot } else { 1050ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot ret = unlink(argv[i]); 1060ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot if (errno == ENOENT && (flags & OPT_FORCE)) { 1070ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot return 0; 1080ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot } 1090ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot } 1100ffc5b37e553f4514121d2775879a153e6ea5eccTanguy Pruvot 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ret < 0) { 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno)); 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 120