Home | History | Annotate | Download | only in atree
      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