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
is_dir(const string & path)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
remove_file(const string & path)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
remove_recursively(const string & path)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
mkdir_recursively(const string & path)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
copy_file(const string & src,const string & dst)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
strip_file(const string & path)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