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