|  | #include "fs.h" | 
|  | #include "files.h" | 
|  | #include <unistd.h> | 
|  | #include <stdlib.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/wait.h> | 
|  | #include <dirent.h> | 
|  | #include <string> | 
|  | #include <vector> | 
|  | #include <stdio.h> | 
|  | #include <string.h> | 
|  | #include <errno.h> | 
|  | #include <sys/stat.h> | 
|  | #include <unistd.h> | 
|  | #include <string.h> | 
|  | #include <host/CopyFile.h> | 
|  |  | 
|  | using namespace std; | 
|  |  | 
|  | static bool | 
|  | is_dir(const string& path) | 
|  | { | 
|  | int err; | 
|  | struct stat st; | 
|  | err = stat(path.c_str(), &st); | 
|  | return err != 0 || S_ISDIR(st.st_mode); | 
|  | } | 
|  |  | 
|  | static int | 
|  | remove_file(const string& path) | 
|  | { | 
|  | int err = unlink(path.c_str()); | 
|  | if (err != 0) { | 
|  | fprintf(stderr, "error deleting file %s (%s)\n", path.c_str(), | 
|  | strerror(errno)); | 
|  | return errno; | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int | 
|  | remove_recursively(const string& path) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | if (is_dir(path)) { | 
|  | DIR *d = opendir(path.c_str()); | 
|  | if (d == NULL) { | 
|  | fprintf(stderr, "error getting directory contents %s (%s)\n", | 
|  | path.c_str(), strerror(errno)); | 
|  | return errno; | 
|  | } | 
|  |  | 
|  | vector<string> files; | 
|  | vector<string> dirs; | 
|  |  | 
|  | struct dirent *ent; | 
|  | while (NULL != (ent = readdir(d))) { | 
|  | if (0 == strcmp(".", ent->d_name) | 
|  | || 0 == strcmp("..", ent->d_name)) { | 
|  | continue; | 
|  | } | 
|  | string full = path; | 
|  | full += '/'; | 
|  | full += ent->d_name; | 
|  | bool is_directory = (ent->d_type == DT_DIR); | 
|  | if (is_directory) { | 
|  | dirs.push_back(full); | 
|  | } else { | 
|  | files.push_back(full); | 
|  | } | 
|  | } | 
|  | closedir(d); | 
|  |  | 
|  | for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) { | 
|  | err = remove_file(*it); | 
|  | if (err != 0) { | 
|  | return err; | 
|  | } | 
|  | } | 
|  |  | 
|  | for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) { | 
|  | err = remove_recursively(*it); | 
|  | if (err != 0) { | 
|  | return err; | 
|  | } | 
|  | } | 
|  |  | 
|  | err = rmdir(path.c_str()); | 
|  | if (err != 0) { | 
|  | fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(), | 
|  | strerror(errno)); | 
|  | return errno; | 
|  | } | 
|  | return 0; | 
|  | } else { | 
|  | return remove_file(path); | 
|  | } | 
|  | } | 
|  |  | 
|  | int | 
|  | mkdir_recursively(const string& path) | 
|  | { | 
|  | int err; | 
|  | size_t pos = 0; | 
|  | // For absolute pathnames, that starts with leading '/' | 
|  | // use appropriate initial value. | 
|  | if (path.length() != 0 and path[0] == '/') pos++; | 
|  |  | 
|  | while (true) { | 
|  | pos = path.find('/', pos); | 
|  | string p = path.substr(0, pos); | 
|  | struct stat st; | 
|  | err = stat(p.c_str(), &st); | 
|  | if (err != 0) { | 
|  | err = mkdir(p.c_str(), 0770); | 
|  | if (err != 0) { | 
|  | fprintf(stderr, "can't create directory %s (%s)\n", | 
|  | path.c_str(), strerror(errno)); | 
|  | return errno; | 
|  | } | 
|  | } | 
|  | else if (!S_ISDIR(st.st_mode)) { | 
|  | fprintf(stderr, "can't create directory %s because %s is a file.\n", | 
|  | path.c_str(), p.c_str()); | 
|  | return 1; | 
|  | } | 
|  | pos++; | 
|  | if (p == path) { | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | int | 
|  | copy_file(const string& src, const string& dst) | 
|  | { | 
|  | int err; | 
|  |  | 
|  | err = copyFile(src.c_str(), dst.c_str(), | 
|  | COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | int | 
|  | strip_file(const string& path) | 
|  | { | 
|  | // Default strip command to run is "strip" unless overridden by the ATREE_STRIP env var. | 
|  | const char* strip_cmd = getenv("ATREE_STRIP"); | 
|  | if (!strip_cmd || !strip_cmd[0]) { | 
|  | strip_cmd = "strip"; | 
|  | } | 
|  | pid_t pid = fork(); | 
|  | if (pid == -1) { | 
|  | // Fork failed. errno should be set. | 
|  | return -1; | 
|  | } else if (pid == 0) { | 
|  | // Exec in the child. Only returns if execve failed. | 
|  |  | 
|  | int num_args = 0; | 
|  | const char *s = strip_cmd; | 
|  | while (*s) { | 
|  | while (*s == ' ') ++s; | 
|  | if (*s && *s != ' ') { | 
|  | ++num_args; | 
|  | while (*s && *s != ' ') ++s; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (num_args <= 0) { | 
|  | fprintf(stderr, "Invalid ATREE_STRIP command '%s'\n", strip_cmd); | 
|  | return 1; | 
|  |  | 
|  | } else if (num_args == 1) { | 
|  | return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL); | 
|  |  | 
|  | } else { | 
|  | // Split the arguments if more than 1 | 
|  | char* cmd = strdup(strip_cmd); | 
|  | const char** args = (const char**) malloc(sizeof(const char*) * (num_args + 2)); | 
|  |  | 
|  | const char** curr = args; | 
|  | char* s = cmd; | 
|  | while (*s) { | 
|  | while (*s == ' ') ++s; | 
|  | if (*s && *s != ' ') { | 
|  | *curr = s; | 
|  | ++curr; | 
|  | while (*s && *s != ' ') ++s; | 
|  | if (*s) { | 
|  | *s = '\0'; | 
|  | ++s; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | args[num_args] = path.c_str(); | 
|  | args[num_args + 1] = NULL; | 
|  |  | 
|  | int ret = execvp(args[0], (char* const*)args); | 
|  | free(args); | 
|  | free(cmd); | 
|  | return ret; | 
|  | } | 
|  | } else { | 
|  | // Wait for child pid and return its exit code. | 
|  | int status; | 
|  | waitpid(pid, &status, 0); | 
|  | return status; | 
|  | } | 
|  | } | 
|  |  |