xref: /aosp_15_r20/build/make/tools/atree/fs.cpp (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
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