rm.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h>
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h>
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h>
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dirent.h>
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <limits.h>
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h>
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h>
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int usage()
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    fprintf(stderr,"rm [-rR] <target>\n");
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return -1;
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* return -1 on failure, with errno set to the first error */
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int unlink_recursive(const char* name)
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct stat st;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    DIR *dir;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct dirent *de;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int fail = 0;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* is it a file or directory? */
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (lstat(name, &st) < 0)
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* a file, so unlink it */
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (!S_ISDIR(st.st_mode))
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return unlink(name);
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* a directory, so open handle */
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    dir = opendir(name);
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (dir == NULL)
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return -1;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* recurse over components */
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    errno = 0;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while ((de = readdir(dir)) != NULL) {
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        char dn[PATH_MAX];
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, "."))
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            continue;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sprintf(dn, "%s/%s", name, de->d_name);
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (unlink_recursive(dn) < 0) {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fail = 1;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        errno = 0;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
50    /* in case readdir or unlink_recursive failed */
51    if (fail || errno < 0) {
52        int save = errno;
53        closedir(dir);
54        errno = save;
55        return -1;
56    }
57
58    /* close directory handle */
59    if (closedir(dir) < 0)
60        return -1;
61
62    /* delete target directory */
63    return rmdir(name);
64}
65
66int rm_main(int argc, char *argv[])
67{
68    int ret;
69    int i = 1;
70    int recursive = 0;
71
72    if (argc < 2)
73        return usage();
74
75    /* check if recursive */
76    if (argc >=2 && (!strcmp(argv[1], "-r") || !strcmp(argv[1], "-R"))) {
77        recursive = 1;
78        i = 2;
79    }
80
81    /* loop over the file/directory args */
82    for (; i < argc; i++) {
83        int ret = recursive ? unlink_recursive(argv[i]) : unlink(argv[i]);
84        if (ret < 0) {
85            fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno));
86            return -1;
87        }
88    }
89
90    return 0;
91}
92
93