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 #ifdef HAVE_DIRENT_D_TYPE
     67             bool is_directory = (ent->d_type == DT_DIR);
     68 #else
     69             // If dirent.d_type is missing, then use stat instead
     70             struct stat stat_buf;
     71             stat(full.c_str(), &stat_buf);
     72             bool is_directory = S_ISDIR(stat_buf.st_mode);
     73 #endif
     74             if (is_directory) {
     75                 dirs.push_back(full);
     76             } else {
     77                 files.push_back(full);
     78             }
     79         }
     80         closedir(d);
     81 
     82         for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) {
     83             err = remove_file(*it);
     84             if (err != 0) {
     85                 return err;
     86             }
     87         }
     88 
     89         for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) {
     90             err = remove_recursively(*it);
     91             if (err != 0) {
     92                 return err;
     93             }
     94         }
     95 
     96         err = rmdir(path.c_str());
     97         if (err != 0) {
     98             fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(),
     99                     strerror(errno));
    100             return errno;
    101         }
    102         return 0;
    103     } else {
    104         return remove_file(path);
    105     }
    106 }
    107 
    108 int
    109 mkdir_recursively(const string& path)
    110 {
    111     int err;
    112     size_t pos = 0;
    113     // For absolute pathnames, that starts with leading '/'
    114     // use appropriate initial value.
    115     if (path.length() != 0 and path[0] == '/') pos++;
    116 
    117     while (true) {
    118         pos = path.find('/', pos);
    119         string p = path.substr(0, pos);
    120         struct stat st;
    121         err = stat(p.c_str(), &st);
    122         if (err != 0) {
    123             err = mkdir(p.c_str(), 0770);
    124             if (err != 0) {
    125                 fprintf(stderr, "can't create directory %s (%s)\n",
    126                         path.c_str(), strerror(errno));
    127                 return errno;
    128             }
    129         }
    130         else if (!S_ISDIR(st.st_mode)) {
    131             fprintf(stderr, "can't create directory %s because %s is a file.\n",
    132                         path.c_str(), p.c_str());
    133             return 1;
    134         }
    135         pos++;
    136         if (p == path) {
    137             return 0;
    138         }
    139     }
    140 }
    141 
    142 int
    143 copy_file(const string& src, const string& dst)
    144 {
    145     int err;
    146 
    147     err = copyFile(src.c_str(), dst.c_str(),
    148                     COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS);
    149     return err;
    150 }
    151 
    152 int
    153 strip_file(const string& path)
    154 {
    155     // Default strip command to run is "strip" unless overridden by the STRIP env var.
    156     const char* strip_cmd = getenv("STRIP");
    157     if (!strip_cmd || !strip_cmd[0]) {
    158         strip_cmd = "strip";
    159     }
    160     pid_t pid = fork();
    161     if (pid == -1) {
    162         // Fork failed. errno should be set.
    163         return -1;
    164     } else if (pid == 0) {
    165         // Exec in the child. Only returns if execve failed.
    166         return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL);
    167     } else {
    168         // Wait for child pid and return its exit code.
    169         int status;
    170         waitpid(pid, &status, 0);
    171         return status;
    172     }
    173 }
    174 
    175