diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:32:55 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:32:55 -0800 |
| commit | dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0 (patch) | |
| tree | 2ba8d1a0846d69b18f623515e8d9b5d9fe38b590 /toolbox/rm.c | |
| parent | e54eebbf1a908d65ee8cf80bab62821c05666d70 (diff) | |
| download | system_core-dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0.tar.gz system_core-dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0.tar.bz2 system_core-dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0.zip | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'toolbox/rm.c')
| -rw-r--r-- | toolbox/rm.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/toolbox/rm.c b/toolbox/rm.c new file mode 100644 index 00000000..bd663118 --- /dev/null +++ b/toolbox/rm.c @@ -0,0 +1,92 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <dirent.h> +#include <limits.h> +#include <sys/stat.h> +#include <sys/types.h> + +static int usage() +{ + fprintf(stderr,"rm [-rR] <target>\n"); + return -1; +} + +/* return -1 on failure, with errno set to the first error */ +static int unlink_recursive(const char* name) +{ + struct stat st; + DIR *dir; + struct dirent *de; + int fail = 0; + + /* is it a file or directory? */ + if (lstat(name, &st) < 0) + return -1; + + /* a file, so unlink it */ + if (!S_ISDIR(st.st_mode)) + return unlink(name); + + /* a directory, so open handle */ + dir = opendir(name); + if (dir == NULL) + return -1; + + /* recurse over components */ + errno = 0; + while ((de = readdir(dir)) != NULL) { + char dn[PATH_MAX]; + if (!strcmp(de->d_name, "..") || !strcmp(de->d_name, ".")) + continue; + sprintf(dn, "%s/%s", name, de->d_name); + if (unlink_recursive(dn) < 0) { + fail = 1; + break; + } + errno = 0; + } + /* in case readdir or unlink_recursive failed */ + if (fail || errno < 0) { + int save = errno; + closedir(dir); + errno = save; + return -1; + } + + /* close directory handle */ + if (closedir(dir) < 0) + return -1; + + /* delete target directory */ + return rmdir(name); +} + +int rm_main(int argc, char *argv[]) +{ + int ret; + int i = 1; + int recursive = 0; + + if (argc < 2) + return usage(); + + /* check if recursive */ + if (argc >=2 && (!strcmp(argv[1], "-r") || !strcmp(argv[1], "-R"))) { + recursive = 1; + i = 2; + } + + /* loop over the file/directory args */ + for (; i < argc; i++) { + int ret = recursive ? unlink_recursive(argv[i]) : unlink(argv[i]); + if (ret < 0) { + fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno)); + return -1; + } + } + + return 0; +} + |
