github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/make/tools/atree/fs.cpp (about)

     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