| The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 1 | #include "fs.h" | 
|  | 2 | #include "files.h" | 
|  | 3 | #include <unistd.h> | 
|  | 4 | #include <sys/types.h> | 
|  | 5 | #include <dirent.h> | 
|  | 6 | #include <string> | 
|  | 7 | #include <vector> | 
|  | 8 | #include <stdio.h> | 
| The Android Open Source Project | 4f85cc5 | 2009-01-09 17:50:54 -0800 | [diff] [blame] | 9 | #include <string.h> | 
| The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 10 | #include <errno.h> | 
|  | 11 | #include <sys/stat.h> | 
|  | 12 | #include <unistd.h> | 
| Alexey Zaytsev | 8ae3ad5 | 2008-10-22 02:02:30 +0400 | [diff] [blame] | 13 | #include <string.h> | 
| The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 14 | #include <host/CopyFile.h> | 
|  | 15 |  | 
|  | 16 | using namespace std; | 
|  | 17 |  | 
|  | 18 | static bool | 
|  | 19 | is_dir(const string& path) | 
|  | 20 | { | 
|  | 21 | int err; | 
|  | 22 | struct stat st; | 
|  | 23 | err = stat(path.c_str(), &st); | 
|  | 24 | return err != 0 || S_ISDIR(st.st_mode); | 
|  | 25 | } | 
|  | 26 |  | 
|  | 27 | static int | 
|  | 28 | remove_file(const string& path) | 
|  | 29 | { | 
|  | 30 | int err = unlink(path.c_str()); | 
|  | 31 | if (err != 0) { | 
|  | 32 | fprintf(stderr, "error deleting file %s (%s)\n", path.c_str(), | 
|  | 33 | strerror(errno)); | 
|  | 34 | return errno; | 
|  | 35 | } | 
|  | 36 | return 0; | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | int | 
|  | 40 | remove_recursively(const string& path) | 
|  | 41 | { | 
|  | 42 | int err; | 
|  | 43 |  | 
|  | 44 | if (is_dir(path)) { | 
|  | 45 | DIR *d = opendir(path.c_str()); | 
|  | 46 | if (d == NULL) { | 
|  | 47 | fprintf(stderr, "error getting directory contents %s (%s)\n", | 
|  | 48 | path.c_str(), strerror(errno)); | 
|  | 49 | return errno; | 
|  | 50 | } | 
|  | 51 |  | 
|  | 52 | vector<string> files; | 
|  | 53 | vector<string> dirs; | 
|  | 54 |  | 
|  | 55 | struct dirent *ent; | 
|  | 56 | while (NULL != (ent = readdir(d))) { | 
|  | 57 | if (0 == strcmp(".", ent->d_name) | 
|  | 58 | || 0 == strcmp("..", ent->d_name)) { | 
|  | 59 | continue; | 
|  | 60 | } | 
|  | 61 | string full = path; | 
|  | 62 | full += '/'; | 
|  | 63 | full += ent->d_name; | 
|  | 64 | #ifdef HAVE_DIRENT_D_TYPE | 
|  | 65 | bool is_directory = (ent->d_type == DT_DIR); | 
|  | 66 | #else | 
|  | 67 | // If dirent.d_type is missing, then use stat instead | 
|  | 68 | struct stat stat_buf; | 
|  | 69 | stat(full.c_str(), &stat_buf); | 
|  | 70 | bool is_directory = S_ISDIR(stat_buf.st_mode); | 
|  | 71 | #endif | 
|  | 72 | if (is_directory) { | 
|  | 73 | dirs.push_back(full); | 
|  | 74 | } else { | 
|  | 75 | files.push_back(full); | 
|  | 76 | } | 
|  | 77 | } | 
|  | 78 | closedir(d); | 
|  | 79 |  | 
|  | 80 | for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) { | 
|  | 81 | err = remove_file(*it); | 
|  | 82 | if (err != 0) { | 
|  | 83 | return err; | 
|  | 84 | } | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) { | 
|  | 88 | err = remove_recursively(*it); | 
|  | 89 | if (err != 0) { | 
|  | 90 | return err; | 
|  | 91 | } | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | err = rmdir(path.c_str()); | 
|  | 95 | if (err != 0) { | 
|  | 96 | fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(), | 
|  | 97 | strerror(errno)); | 
|  | 98 | return errno; | 
|  | 99 | } | 
|  | 100 | return 0; | 
|  | 101 | } else { | 
|  | 102 | return remove_file(path); | 
|  | 103 | } | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | int | 
|  | 107 | mkdir_recursively(const string& path) | 
|  | 108 | { | 
|  | 109 | int err; | 
|  | 110 | size_t pos = 0; | 
| Jey | 9af5fc4 | 2008-12-10 09:07:28 -0800 | [diff] [blame] | 111 | // For absolute pathnames, that starts with leading '/' | 
|  | 112 | // use appropriate initial value. | 
|  | 113 | if (path.length() != 0 and path[0] == '/') pos++; | 
|  | 114 |  | 
| The Android Open Source Project | b6c1cf6 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 115 | while (true) { | 
|  | 116 | pos = path.find('/', pos); | 
|  | 117 | string p = path.substr(0, pos); | 
|  | 118 | struct stat st; | 
|  | 119 | err = stat(p.c_str(), &st); | 
|  | 120 | if (err != 0) { | 
|  | 121 | err = mkdir(p.c_str(), 0770); | 
|  | 122 | if (err != 0) { | 
|  | 123 | fprintf(stderr, "can't create directory %s (%s)\n", | 
|  | 124 | path.c_str(), strerror(errno)); | 
|  | 125 | return errno; | 
|  | 126 | } | 
|  | 127 | } | 
|  | 128 | else if (!S_ISDIR(st.st_mode)) { | 
|  | 129 | fprintf(stderr, "can't create directory %s because %s is a file.\n", | 
|  | 130 | path.c_str(), p.c_str()); | 
|  | 131 | return 1; | 
|  | 132 | } | 
|  | 133 | pos++; | 
|  | 134 | if (p == path) { | 
|  | 135 | return 0; | 
|  | 136 | } | 
|  | 137 | } | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | int | 
|  | 141 | copy_file(const string& src, const string& dst) | 
|  | 142 | { | 
|  | 143 | int err; | 
|  | 144 |  | 
|  | 145 | err = copyFile(src.c_str(), dst.c_str(), | 
|  | 146 | COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS); | 
|  | 147 | return err; | 
|  | 148 | } |