| #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; |
| #ifdef HAVE_DIRENT_D_TYPE |
| bool is_directory = (ent->d_type == DT_DIR); |
| #else |
| // If dirent.d_type is missing, then use stat instead |
| struct stat stat_buf; |
| stat(full.c_str(), &stat_buf); |
| bool is_directory = S_ISDIR(stat_buf.st_mode); |
| #endif |
| 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; |
| } |
| } |
| |