1*9e94795aSAndroid Build Coastguard Worker #include "fs.h"
2*9e94795aSAndroid Build Coastguard Worker #include "files.h"
3*9e94795aSAndroid Build Coastguard Worker #include <unistd.h>
4*9e94795aSAndroid Build Coastguard Worker #include <stdlib.h>
5*9e94795aSAndroid Build Coastguard Worker #include <sys/types.h>
6*9e94795aSAndroid Build Coastguard Worker #include <sys/wait.h>
7*9e94795aSAndroid Build Coastguard Worker #include <dirent.h>
8*9e94795aSAndroid Build Coastguard Worker #include <string>
9*9e94795aSAndroid Build Coastguard Worker #include <vector>
10*9e94795aSAndroid Build Coastguard Worker #include <stdio.h>
11*9e94795aSAndroid Build Coastguard Worker #include <string.h>
12*9e94795aSAndroid Build Coastguard Worker #include <errno.h>
13*9e94795aSAndroid Build Coastguard Worker #include <sys/stat.h>
14*9e94795aSAndroid Build Coastguard Worker #include <unistd.h>
15*9e94795aSAndroid Build Coastguard Worker #include <string.h>
16*9e94795aSAndroid Build Coastguard Worker #include <host/CopyFile.h>
17*9e94795aSAndroid Build Coastguard Worker
18*9e94795aSAndroid Build Coastguard Worker using namespace std;
19*9e94795aSAndroid Build Coastguard Worker
20*9e94795aSAndroid Build Coastguard Worker static bool
is_dir(const string & path)21*9e94795aSAndroid Build Coastguard Worker is_dir(const string& path)
22*9e94795aSAndroid Build Coastguard Worker {
23*9e94795aSAndroid Build Coastguard Worker int err;
24*9e94795aSAndroid Build Coastguard Worker struct stat st;
25*9e94795aSAndroid Build Coastguard Worker err = stat(path.c_str(), &st);
26*9e94795aSAndroid Build Coastguard Worker return err != 0 || S_ISDIR(st.st_mode);
27*9e94795aSAndroid Build Coastguard Worker }
28*9e94795aSAndroid Build Coastguard Worker
29*9e94795aSAndroid Build Coastguard Worker static int
remove_file(const string & path)30*9e94795aSAndroid Build Coastguard Worker remove_file(const string& path)
31*9e94795aSAndroid Build Coastguard Worker {
32*9e94795aSAndroid Build Coastguard Worker int err = unlink(path.c_str());
33*9e94795aSAndroid Build Coastguard Worker if (err != 0) {
34*9e94795aSAndroid Build Coastguard Worker fprintf(stderr, "error deleting file %s (%s)\n", path.c_str(),
35*9e94795aSAndroid Build Coastguard Worker strerror(errno));
36*9e94795aSAndroid Build Coastguard Worker return errno;
37*9e94795aSAndroid Build Coastguard Worker }
38*9e94795aSAndroid Build Coastguard Worker return 0;
39*9e94795aSAndroid Build Coastguard Worker }
40*9e94795aSAndroid Build Coastguard Worker
41*9e94795aSAndroid Build Coastguard Worker int
remove_recursively(const string & path)42*9e94795aSAndroid Build Coastguard Worker remove_recursively(const string& path)
43*9e94795aSAndroid Build Coastguard Worker {
44*9e94795aSAndroid Build Coastguard Worker int err;
45*9e94795aSAndroid Build Coastguard Worker
46*9e94795aSAndroid Build Coastguard Worker if (is_dir(path)) {
47*9e94795aSAndroid Build Coastguard Worker DIR *d = opendir(path.c_str());
48*9e94795aSAndroid Build Coastguard Worker if (d == NULL) {
49*9e94795aSAndroid Build Coastguard Worker fprintf(stderr, "error getting directory contents %s (%s)\n",
50*9e94795aSAndroid Build Coastguard Worker path.c_str(), strerror(errno));
51*9e94795aSAndroid Build Coastguard Worker return errno;
52*9e94795aSAndroid Build Coastguard Worker }
53*9e94795aSAndroid Build Coastguard Worker
54*9e94795aSAndroid Build Coastguard Worker vector<string> files;
55*9e94795aSAndroid Build Coastguard Worker vector<string> dirs;
56*9e94795aSAndroid Build Coastguard Worker
57*9e94795aSAndroid Build Coastguard Worker struct dirent *ent;
58*9e94795aSAndroid Build Coastguard Worker while (NULL != (ent = readdir(d))) {
59*9e94795aSAndroid Build Coastguard Worker if (0 == strcmp(".", ent->d_name)
60*9e94795aSAndroid Build Coastguard Worker || 0 == strcmp("..", ent->d_name)) {
61*9e94795aSAndroid Build Coastguard Worker continue;
62*9e94795aSAndroid Build Coastguard Worker }
63*9e94795aSAndroid Build Coastguard Worker string full = path;
64*9e94795aSAndroid Build Coastguard Worker full += '/';
65*9e94795aSAndroid Build Coastguard Worker full += ent->d_name;
66*9e94795aSAndroid Build Coastguard Worker bool is_directory = (ent->d_type == DT_DIR);
67*9e94795aSAndroid Build Coastguard Worker if (is_directory) {
68*9e94795aSAndroid Build Coastguard Worker dirs.push_back(full);
69*9e94795aSAndroid Build Coastguard Worker } else {
70*9e94795aSAndroid Build Coastguard Worker files.push_back(full);
71*9e94795aSAndroid Build Coastguard Worker }
72*9e94795aSAndroid Build Coastguard Worker }
73*9e94795aSAndroid Build Coastguard Worker closedir(d);
74*9e94795aSAndroid Build Coastguard Worker
75*9e94795aSAndroid Build Coastguard Worker for (vector<string>::iterator it=files.begin(); it!=files.end(); it++) {
76*9e94795aSAndroid Build Coastguard Worker err = remove_file(*it);
77*9e94795aSAndroid Build Coastguard Worker if (err != 0) {
78*9e94795aSAndroid Build Coastguard Worker return err;
79*9e94795aSAndroid Build Coastguard Worker }
80*9e94795aSAndroid Build Coastguard Worker }
81*9e94795aSAndroid Build Coastguard Worker
82*9e94795aSAndroid Build Coastguard Worker for (vector<string>::iterator it=dirs.begin(); it!=dirs.end(); it++) {
83*9e94795aSAndroid Build Coastguard Worker err = remove_recursively(*it);
84*9e94795aSAndroid Build Coastguard Worker if (err != 0) {
85*9e94795aSAndroid Build Coastguard Worker return err;
86*9e94795aSAndroid Build Coastguard Worker }
87*9e94795aSAndroid Build Coastguard Worker }
88*9e94795aSAndroid Build Coastguard Worker
89*9e94795aSAndroid Build Coastguard Worker err = rmdir(path.c_str());
90*9e94795aSAndroid Build Coastguard Worker if (err != 0) {
91*9e94795aSAndroid Build Coastguard Worker fprintf(stderr, "error deleting directory %s (%s)\n", path.c_str(),
92*9e94795aSAndroid Build Coastguard Worker strerror(errno));
93*9e94795aSAndroid Build Coastguard Worker return errno;
94*9e94795aSAndroid Build Coastguard Worker }
95*9e94795aSAndroid Build Coastguard Worker return 0;
96*9e94795aSAndroid Build Coastguard Worker } else {
97*9e94795aSAndroid Build Coastguard Worker return remove_file(path);
98*9e94795aSAndroid Build Coastguard Worker }
99*9e94795aSAndroid Build Coastguard Worker }
100*9e94795aSAndroid Build Coastguard Worker
101*9e94795aSAndroid Build Coastguard Worker int
mkdir_recursively(const string & path)102*9e94795aSAndroid Build Coastguard Worker mkdir_recursively(const string& path)
103*9e94795aSAndroid Build Coastguard Worker {
104*9e94795aSAndroid Build Coastguard Worker int err;
105*9e94795aSAndroid Build Coastguard Worker size_t pos = 0;
106*9e94795aSAndroid Build Coastguard Worker // For absolute pathnames, that starts with leading '/'
107*9e94795aSAndroid Build Coastguard Worker // use appropriate initial value.
108*9e94795aSAndroid Build Coastguard Worker if (path.length() != 0 and path[0] == '/') pos++;
109*9e94795aSAndroid Build Coastguard Worker
110*9e94795aSAndroid Build Coastguard Worker while (true) {
111*9e94795aSAndroid Build Coastguard Worker pos = path.find('/', pos);
112*9e94795aSAndroid Build Coastguard Worker string p = path.substr(0, pos);
113*9e94795aSAndroid Build Coastguard Worker struct stat st;
114*9e94795aSAndroid Build Coastguard Worker err = stat(p.c_str(), &st);
115*9e94795aSAndroid Build Coastguard Worker if (err != 0) {
116*9e94795aSAndroid Build Coastguard Worker err = mkdir(p.c_str(), 0770);
117*9e94795aSAndroid Build Coastguard Worker if (err != 0) {
118*9e94795aSAndroid Build Coastguard Worker fprintf(stderr, "can't create directory %s (%s)\n",
119*9e94795aSAndroid Build Coastguard Worker path.c_str(), strerror(errno));
120*9e94795aSAndroid Build Coastguard Worker return errno;
121*9e94795aSAndroid Build Coastguard Worker }
122*9e94795aSAndroid Build Coastguard Worker }
123*9e94795aSAndroid Build Coastguard Worker else if (!S_ISDIR(st.st_mode)) {
124*9e94795aSAndroid Build Coastguard Worker fprintf(stderr, "can't create directory %s because %s is a file.\n",
125*9e94795aSAndroid Build Coastguard Worker path.c_str(), p.c_str());
126*9e94795aSAndroid Build Coastguard Worker return 1;
127*9e94795aSAndroid Build Coastguard Worker }
128*9e94795aSAndroid Build Coastguard Worker pos++;
129*9e94795aSAndroid Build Coastguard Worker if (p == path) {
130*9e94795aSAndroid Build Coastguard Worker return 0;
131*9e94795aSAndroid Build Coastguard Worker }
132*9e94795aSAndroid Build Coastguard Worker }
133*9e94795aSAndroid Build Coastguard Worker }
134*9e94795aSAndroid Build Coastguard Worker
135*9e94795aSAndroid Build Coastguard Worker int
copy_file(const string & src,const string & dst)136*9e94795aSAndroid Build Coastguard Worker copy_file(const string& src, const string& dst)
137*9e94795aSAndroid Build Coastguard Worker {
138*9e94795aSAndroid Build Coastguard Worker int err;
139*9e94795aSAndroid Build Coastguard Worker
140*9e94795aSAndroid Build Coastguard Worker err = copyFile(src.c_str(), dst.c_str(),
141*9e94795aSAndroid Build Coastguard Worker COPY_NO_DEREFERENCE | COPY_FORCE | COPY_PERMISSIONS);
142*9e94795aSAndroid Build Coastguard Worker return err;
143*9e94795aSAndroid Build Coastguard Worker }
144*9e94795aSAndroid Build Coastguard Worker
145*9e94795aSAndroid Build Coastguard Worker int
strip_file(const string & path)146*9e94795aSAndroid Build Coastguard Worker strip_file(const string& path)
147*9e94795aSAndroid Build Coastguard Worker {
148*9e94795aSAndroid Build Coastguard Worker // Default strip command to run is "strip" unless overridden by the ATREE_STRIP env var.
149*9e94795aSAndroid Build Coastguard Worker const char* strip_cmd = getenv("ATREE_STRIP");
150*9e94795aSAndroid Build Coastguard Worker if (!strip_cmd || !strip_cmd[0]) {
151*9e94795aSAndroid Build Coastguard Worker strip_cmd = "strip";
152*9e94795aSAndroid Build Coastguard Worker }
153*9e94795aSAndroid Build Coastguard Worker pid_t pid = fork();
154*9e94795aSAndroid Build Coastguard Worker if (pid == -1) {
155*9e94795aSAndroid Build Coastguard Worker // Fork failed. errno should be set.
156*9e94795aSAndroid Build Coastguard Worker return -1;
157*9e94795aSAndroid Build Coastguard Worker } else if (pid == 0) {
158*9e94795aSAndroid Build Coastguard Worker // Exec in the child. Only returns if execve failed.
159*9e94795aSAndroid Build Coastguard Worker
160*9e94795aSAndroid Build Coastguard Worker int num_args = 0;
161*9e94795aSAndroid Build Coastguard Worker const char *s = strip_cmd;
162*9e94795aSAndroid Build Coastguard Worker while (*s) {
163*9e94795aSAndroid Build Coastguard Worker while (*s == ' ') ++s;
164*9e94795aSAndroid Build Coastguard Worker if (*s && *s != ' ') {
165*9e94795aSAndroid Build Coastguard Worker ++num_args;
166*9e94795aSAndroid Build Coastguard Worker while (*s && *s != ' ') ++s;
167*9e94795aSAndroid Build Coastguard Worker }
168*9e94795aSAndroid Build Coastguard Worker }
169*9e94795aSAndroid Build Coastguard Worker
170*9e94795aSAndroid Build Coastguard Worker if (num_args <= 0) {
171*9e94795aSAndroid Build Coastguard Worker fprintf(stderr, "Invalid ATREE_STRIP command '%s'\n", strip_cmd);
172*9e94795aSAndroid Build Coastguard Worker return 1;
173*9e94795aSAndroid Build Coastguard Worker
174*9e94795aSAndroid Build Coastguard Worker } else if (num_args == 1) {
175*9e94795aSAndroid Build Coastguard Worker return execlp(strip_cmd, strip_cmd, path.c_str(), (char *)NULL);
176*9e94795aSAndroid Build Coastguard Worker
177*9e94795aSAndroid Build Coastguard Worker } else {
178*9e94795aSAndroid Build Coastguard Worker // Split the arguments if more than 1
179*9e94795aSAndroid Build Coastguard Worker char* cmd = strdup(strip_cmd);
180*9e94795aSAndroid Build Coastguard Worker const char** args = (const char**) calloc((num_args + 2), sizeof(const char*));
181*9e94795aSAndroid Build Coastguard Worker
182*9e94795aSAndroid Build Coastguard Worker const char** curr = args;
183*9e94795aSAndroid Build Coastguard Worker char* s = cmd;
184*9e94795aSAndroid Build Coastguard Worker while (*s) {
185*9e94795aSAndroid Build Coastguard Worker while (*s == ' ') ++s;
186*9e94795aSAndroid Build Coastguard Worker if (*s && *s != ' ') {
187*9e94795aSAndroid Build Coastguard Worker *curr = s;
188*9e94795aSAndroid Build Coastguard Worker ++curr;
189*9e94795aSAndroid Build Coastguard Worker while (*s && *s != ' ') ++s;
190*9e94795aSAndroid Build Coastguard Worker if (*s) {
191*9e94795aSAndroid Build Coastguard Worker *s = '\0';
192*9e94795aSAndroid Build Coastguard Worker ++s;
193*9e94795aSAndroid Build Coastguard Worker }
194*9e94795aSAndroid Build Coastguard Worker }
195*9e94795aSAndroid Build Coastguard Worker }
196*9e94795aSAndroid Build Coastguard Worker
197*9e94795aSAndroid Build Coastguard Worker args[num_args] = path.c_str();
198*9e94795aSAndroid Build Coastguard Worker args[num_args + 1] = NULL;
199*9e94795aSAndroid Build Coastguard Worker
200*9e94795aSAndroid Build Coastguard Worker int ret = execvp(args[0], (char* const*)args);
201*9e94795aSAndroid Build Coastguard Worker free(args);
202*9e94795aSAndroid Build Coastguard Worker free(cmd);
203*9e94795aSAndroid Build Coastguard Worker return ret;
204*9e94795aSAndroid Build Coastguard Worker }
205*9e94795aSAndroid Build Coastguard Worker } else {
206*9e94795aSAndroid Build Coastguard Worker // Wait for child pid and return its exit code.
207*9e94795aSAndroid Build Coastguard Worker int status;
208*9e94795aSAndroid Build Coastguard Worker waitpid(pid, &status, 0);
209*9e94795aSAndroid Build Coastguard Worker return status;
210*9e94795aSAndroid Build Coastguard Worker }
211*9e94795aSAndroid Build Coastguard Worker }
212*9e94795aSAndroid Build Coastguard Worker
213