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