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 bool is_directory = (ent->d_type == DT_DIR); 67 if (is_directory) { 68 dirs.push_back(full); 69 } else { 70 files.push_back(full); 71 } 72 } 73 closedir(d); 74 75 for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) { 76 err = remove_file(*it); 77 if (err != 0) { 78 return err; 79 } 80 } 81 82 for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) { 83 err = remove_recursively(*it); 84 if (err != 0) { 85 return err; 86 } 87 } 88 89 err = rmdir(path.c_str()); 90 if (err != 0) { 91 fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(), 92 strerror(errno)); 93 return errno; 94 } 95 return 0; 96 } else { 97 return remove_file(path); 98 } 99 } 100 101 int 102 mkdir_recursively(const string& path) 103 { 104 int err; 105 size_t pos = 0; 106 // For absolute pathnames, that starts with leading '/' 107 // use appropriate initial value. 108 if (path.length() != 0 and path[0] == '/') pos++; 109 110 while (true) { 111 pos = path.find('/', pos); 112 string p = path.substr(0, pos); 113 struct stat st; 114 err = stat(p.c_str(), &st); 115 if (err != 0) { 116 err = mkdir(p.c_str(), 0770); 117 if (err != 0) { 118 fprintf(stderr, "can't create directory %s (%s)\n", 119 path.c_str(), strerror(errno)); 120 return errno; 121 } 122 } 123 else if (!S_ISDIR(st.st_mode)) { 124 fprintf(stderr, "can't create directory %s because %s is a file.\n", 125 path.c_str(), p.c_str()); 126 return 1; 127 } 128 pos++; 129 if (p == path) { 130 return 0; 131 } 132 } 133 } 134 135 int 136 copy_file(const string& src, const string& dst) 137 { 138 int err; 139 140 err = copyFile(src.c_str(), dst.c_str(), 141 COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS); 142 return err; 143 } 144 145 int 146 strip_file(const string& path) 147 { 148 // Default strip command to run is "strip" unless overridden by the ATREE_STRIP env var. 149 const char* strip_cmd = getenv("ATREE_STRIP"); 150 if (!strip_cmd || !strip_cmd[0]) { 151 strip_cmd = "strip"; 152 } 153 pid_t pid = fork(); 154 if (pid == -1) { 155 // Fork failed. errno should be set. 156 return -1; 157 } else if (pid == 0) { 158 // Exec in the child. Only returns if execve failed. 159 160 int num_args = 0; 161 const char *s = strip_cmd; 162 while (*s) { 163 while (*s == ' ') ++s; 164 if (*s && *s != ' ') { 165 ++num_args; 166 while (*s && *s != ' ') ++s; 167 } 168 } 169 170 if (num_args <= 0) { 171 fprintf(stderr, "Invalid ATREE_STRIP command '%s'\n", strip_cmd); 172 return 1; 173 174 } else if (num_args == 1) { 175 return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL); 176 177 } else { 178 // Split the arguments if more than 1 179 char* cmd = strdup(strip_cmd); 180 const char** args = (const char**) malloc(sizeof(const char*) * (num_args + 2)); 181 182 const char** curr = args; 183 char* s = cmd; 184 while (*s) { 185 while (*s == ' ') ++s; 186 if (*s && *s != ' ') { 187 *curr = s; 188 ++curr; 189 while (*s && *s != ' ') ++s; 190 if (*s) { 191 *s = '\0'; 192 ++s; 193 } 194 } 195 } 196 197 args[num_args] = path.c_str(); 198 args[num_args + 1] = NULL; 199 200 int ret = execvp(args[0], (char* const*)args); 201 free(args); 202 free(cmd); 203 return ret; 204 } 205 } else { 206 // Wait for child pid and return its exit code. 207 int status; 208 waitpid(pid, &status, 0); 209 return status; 210 } 211 } 212 213