1 #include "fs.h" 2 #include "files.h" 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <sys/types.h> 6 #include <sys/wait.h> 7 #include <dirent.h> 8 #include <string> 9 #include <vector> 10 #include <stdio.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <sys/stat.h> 14 #include <unistd.h> 15 #include <string.h> 16 #include <host/CopyFile.h> 17 18 using namespace std; 19 20 static bool 21 is_dir(const string& path) 22 { 23 int err; 24 struct stat st; 25 err = stat(path.c_str(), &st); 26 return err != 0 || S_ISDIR(st.st_mode); 27 } 28 29 static int 30 remove_file(const string& path) 31 { 32 int err = unlink(path.c_str()); 33 if (err != 0) { 34 fprintf(stderr, "error deleting file %s (%s)\n", path.c_str(), 35 strerror(errno)); 36 return errno; 37 } 38 return 0; 39 } 40 41 int 42 remove_recursively(const string& path) 43 { 44 int err; 45 46 if (is_dir(path)) { 47 DIR *d = opendir(path.c_str()); 48 if (d == NULL) { 49 fprintf(stderr, "error getting directory contents %s (%s)\n", 50 path.c_str(), strerror(errno)); 51 return errno; 52 } 53 54 vector<string> files; 55 vector<string> dirs; 56 57 struct dirent *ent; 58 while (NULL != (ent = readdir(d))) { 59 if (0 == strcmp(".", ent->d_name) 60 || 0 == strcmp("..", ent->d_name)) { 61 continue; 62 } 63 string full = path; 64 full += '/'; 65 full += ent->d_name; 66 #ifdef HAVE_DIRENT_D_TYPE 67 bool is_directory = (ent->d_type == DT_DIR); 68 #else 69 // If dirent.d_type is missing, then use stat instead 70 struct stat stat_buf; 71 stat(full.c_str(), &stat_buf); 72 bool is_directory = S_ISDIR(stat_buf.st_mode); 73 #endif 74 if (is_directory) { 75 dirs.push_back(full); 76 } else { 77 files.push_back(full); 78 } 79 } 80 closedir(d); 81 82 for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) { 83 err = remove_file(*it); 84 if (err != 0) { 85 return err; 86 } 87 } 88 89 for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) { 90 err = remove_recursively(*it); 91 if (err != 0) { 92 return err; 93 } 94 } 95 96 err = rmdir(path.c_str()); 97 if (err != 0) { 98 fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(), 99 strerror(errno)); 100 return errno; 101 } 102 return 0; 103 } else { 104 return remove_file(path); 105 } 106 } 107 108 int 109 mkdir_recursively(const string& path) 110 { 111 int err; 112 size_t pos = 0; 113 // For absolute pathnames, that starts with leading '/' 114 // use appropriate initial value. 115 if (path.length() != 0 and path[0] == '/') pos++; 116 117 while (true) { 118 pos = path.find('/', pos); 119 string p = path.substr(0, pos); 120 struct stat st; 121 err = stat(p.c_str(), &st); 122 if (err != 0) { 123 err = mkdir(p.c_str(), 0770); 124 if (err != 0) { 125 fprintf(stderr, "can't create directory %s (%s)\n", 126 path.c_str(), strerror(errno)); 127 return errno; 128 } 129 } 130 else if (!S_ISDIR(st.st_mode)) { 131 fprintf(stderr, "can't create directory %s because %s is a file.\n", 132 path.c_str(), p.c_str()); 133 return 1; 134 } 135 pos++; 136 if (p == path) { 137 return 0; 138 } 139 } 140 } 141 142 int 143 copy_file(const string& src, const string& dst) 144 { 145 int err; 146 147 err = copyFile(src.c_str(), dst.c_str(), 148 COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS); 149 return err; 150 } 151 152 int 153 strip_file(const string& path) 154 { 155 // Default strip command to run is "strip" unless overridden by the ATREE_STRIP env var. 156 const char* strip_cmd = getenv("ATREE_STRIP"); 157 if (!strip_cmd || !strip_cmd[0]) { 158 strip_cmd = "strip"; 159 } 160 pid_t pid = fork(); 161 if (pid == -1) { 162 // Fork failed. errno should be set. 163 return -1; 164 } else if (pid == 0) { 165 // Exec in the child. Only returns if execve failed. 166 167 int num_args = 0; 168 const char *s = strip_cmd; 169 while (*s) { 170 while (*s == ' ') ++s; 171 if (*s && *s != ' ') { 172 ++num_args; 173 while (*s && *s != ' ') ++s; 174 } 175 } 176 177 if (num_args <= 0) { 178 fprintf(stderr, "Invalid ATREE_STRIP command '%s'\n", strip_cmd); 179 return 1; 180 181 } else if (num_args == 1) { 182 return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL); 183 184 } else { 185 // Split the arguments if more than 1 186 char* cmd = strdup(strip_cmd); 187 const char** args = (const char**) malloc(sizeof(const char*) * (num_args + 2)); 188 189 const char** curr = args; 190 char* s = cmd; 191 while (*s) { 192 while (*s == ' ') ++s; 193 if (*s && *s != ' ') { 194 *curr = s; 195 ++curr; 196 while (*s && *s != ' ') ++s; 197 if (*s) { 198 *s = '\0'; 199 ++s; 200 } 201 } 202 } 203 204 args[num_args] = path.c_str(); 205 args[num_args + 1] = NULL; 206 207 int ret = execvp(args[0], (char* const*)args); 208 free(args); 209 free(cmd); 210 return ret; 211 } 212 } else { 213 // Wait for child pid and return its exit code. 214 int status; 215 waitpid(pid, &status, 0); 216 return status; 217 } 218 } 219 220