xref: /aosp_15_r20/build/make/tools/atree/atree.cpp (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker #include <stdio.h>
2*9e94795aSAndroid Build Coastguard Worker #include <stdlib.h>
3*9e94795aSAndroid Build Coastguard Worker #include <string.h>
4*9e94795aSAndroid Build Coastguard Worker #include <unistd.h>
5*9e94795aSAndroid Build Coastguard Worker #include <stdarg.h>
6*9e94795aSAndroid Build Coastguard Worker #include "options.h"
7*9e94795aSAndroid Build Coastguard Worker #include "files.h"
8*9e94795aSAndroid Build Coastguard Worker #include "fs.h"
9*9e94795aSAndroid Build Coastguard Worker #include <set>
10*9e94795aSAndroid Build Coastguard Worker #include <iostream>
11*9e94795aSAndroid Build Coastguard Worker #include <sstream>
12*9e94795aSAndroid Build Coastguard Worker 
13*9e94795aSAndroid Build Coastguard Worker using namespace std;
14*9e94795aSAndroid Build Coastguard Worker 
15*9e94795aSAndroid Build Coastguard Worker bool g_debug = getenv("ATREE_DEBUG") != NULL;
16*9e94795aSAndroid Build Coastguard Worker vector<string> g_listFiles;
17*9e94795aSAndroid Build Coastguard Worker vector<string> g_inputBases;
18*9e94795aSAndroid Build Coastguard Worker map<string, string> g_variables;
19*9e94795aSAndroid Build Coastguard Worker string g_outputBase;
20*9e94795aSAndroid Build Coastguard Worker string g_dependency;
21*9e94795aSAndroid Build Coastguard Worker bool g_useHardLinks = false;
22*9e94795aSAndroid Build Coastguard Worker 
23*9e94795aSAndroid Build Coastguard Worker const char* USAGE =
24*9e94795aSAndroid Build Coastguard Worker "\n"
25*9e94795aSAndroid Build Coastguard Worker "Usage: atree OPTIONS\n"
26*9e94795aSAndroid Build Coastguard Worker "\n"
27*9e94795aSAndroid Build Coastguard Worker "Options:\n"
28*9e94795aSAndroid Build Coastguard Worker "  -f FILELIST    Specify one or more files containing the\n"
29*9e94795aSAndroid Build Coastguard Worker "                 list of files to copy.\n"
30*9e94795aSAndroid Build Coastguard Worker "  -I INPUTDIR    Specify one or more base directories in\n"
31*9e94795aSAndroid Build Coastguard Worker "                 which to look for the files\n"
32*9e94795aSAndroid Build Coastguard Worker "  -o OUTPUTDIR   Specify the directory to copy all of the\n"
33*9e94795aSAndroid Build Coastguard Worker "                 output files to.\n"
34*9e94795aSAndroid Build Coastguard Worker "  -l             Use hard links instead of copying the files.\n"
35*9e94795aSAndroid Build Coastguard Worker "  -m DEPENDENCY  Output a make-formatted file containing the list.\n"
36*9e94795aSAndroid Build Coastguard Worker "                 of files included.  It sets the variable ATREE_FILES.\n"
37*9e94795aSAndroid Build Coastguard Worker "  -v VAR=VAL     Replaces ${VAR} by VAL when reading input files.\n"
38*9e94795aSAndroid Build Coastguard Worker "  -d             Verbose debug mode.\n"
39*9e94795aSAndroid Build Coastguard Worker "\n"
40*9e94795aSAndroid Build Coastguard Worker "FILELIST file format:\n"
41*9e94795aSAndroid Build Coastguard Worker "  The FILELIST files contain the list of files that will end up\n"
42*9e94795aSAndroid Build Coastguard Worker "  in the final OUTPUTDIR.  Atree will look for files in the INPUTDIR\n"
43*9e94795aSAndroid Build Coastguard Worker "  directories in the order they are specified.\n"
44*9e94795aSAndroid Build Coastguard Worker "\n"
45*9e94795aSAndroid Build Coastguard Worker "  In a FILELIST file, comment lines start with a #.  Other lines\n"
46*9e94795aSAndroid Build Coastguard Worker "  are of the format:\n"
47*9e94795aSAndroid Build Coastguard Worker "\n"
48*9e94795aSAndroid Build Coastguard Worker "    [rm|strip] DEST\n"
49*9e94795aSAndroid Build Coastguard Worker "    SRC [strip] DEST\n"
50*9e94795aSAndroid Build Coastguard Worker "    -SRCPATTERN\n"
51*9e94795aSAndroid Build Coastguard Worker "\n"
52*9e94795aSAndroid Build Coastguard Worker "  DEST should be path relative to the output directory.\n"
53*9e94795aSAndroid Build Coastguard Worker "  'rm DEST' removes the destination file and fails if it's missing.\n"
54*9e94795aSAndroid Build Coastguard Worker "  'strip DEST' strips the binary destination file.\n"
55*9e94795aSAndroid Build Coastguard Worker "  If SRC is supplied, the file names can be different.\n"
56*9e94795aSAndroid Build Coastguard Worker "  SRCPATTERN is a pattern for the filenames.\n"
57*9e94795aSAndroid Build Coastguard Worker "\n";
58*9e94795aSAndroid Build Coastguard Worker 
usage()59*9e94795aSAndroid Build Coastguard Worker int usage()
60*9e94795aSAndroid Build Coastguard Worker {
61*9e94795aSAndroid Build Coastguard Worker     fwrite(USAGE, strlen(USAGE), 1, stderr);
62*9e94795aSAndroid Build Coastguard Worker     return 1;
63*9e94795aSAndroid Build Coastguard Worker }
64*9e94795aSAndroid Build Coastguard Worker 
65*9e94795aSAndroid Build Coastguard Worker static bool
add_variable(const char * arg)66*9e94795aSAndroid Build Coastguard Worker add_variable(const char* arg) {
67*9e94795aSAndroid Build Coastguard Worker     const char* p = arg;
68*9e94795aSAndroid Build Coastguard Worker     while (*p && *p != '=') p++;
69*9e94795aSAndroid Build Coastguard Worker 
70*9e94795aSAndroid Build Coastguard Worker     if (*p == 0 || p == arg || p[1] == 0) {
71*9e94795aSAndroid Build Coastguard Worker         return false;
72*9e94795aSAndroid Build Coastguard Worker     }
73*9e94795aSAndroid Build Coastguard Worker 
74*9e94795aSAndroid Build Coastguard Worker     ostringstream var;
75*9e94795aSAndroid Build Coastguard Worker     var << "${" << string(arg, p-arg) << "}";
76*9e94795aSAndroid Build Coastguard Worker     g_variables[var.str()] = string(p+1);
77*9e94795aSAndroid Build Coastguard Worker     return true;
78*9e94795aSAndroid Build Coastguard Worker }
79*9e94795aSAndroid Build Coastguard Worker 
80*9e94795aSAndroid Build Coastguard Worker static void
debug_printf(const char * format,...)81*9e94795aSAndroid Build Coastguard Worker debug_printf(const char* format, ...)
82*9e94795aSAndroid Build Coastguard Worker {
83*9e94795aSAndroid Build Coastguard Worker     if (g_debug) {
84*9e94795aSAndroid Build Coastguard Worker         fflush(stderr);
85*9e94795aSAndroid Build Coastguard Worker         va_list ap;
86*9e94795aSAndroid Build Coastguard Worker         va_start(ap, format);
87*9e94795aSAndroid Build Coastguard Worker         vprintf(format, ap);
88*9e94795aSAndroid Build Coastguard Worker         va_end(ap);
89*9e94795aSAndroid Build Coastguard Worker         fflush(stdout);
90*9e94795aSAndroid Build Coastguard Worker     }
91*9e94795aSAndroid Build Coastguard Worker }
92*9e94795aSAndroid Build Coastguard Worker 
93*9e94795aSAndroid Build Coastguard Worker // Escape the filename so that it can be added to the makefile properly.
94*9e94795aSAndroid Build Coastguard Worker static string
escape_filename(const string & name)95*9e94795aSAndroid Build Coastguard Worker escape_filename(const string& name)
96*9e94795aSAndroid Build Coastguard Worker {
97*9e94795aSAndroid Build Coastguard Worker     ostringstream new_name;
98*9e94795aSAndroid Build Coastguard Worker     for (string::const_iterator iter = name.begin(); iter != name.end(); ++iter)
99*9e94795aSAndroid Build Coastguard Worker     {
100*9e94795aSAndroid Build Coastguard Worker         switch (*iter)
101*9e94795aSAndroid Build Coastguard Worker         {
102*9e94795aSAndroid Build Coastguard Worker             case '$':
103*9e94795aSAndroid Build Coastguard Worker                 new_name << "$$";
104*9e94795aSAndroid Build Coastguard Worker                 break;
105*9e94795aSAndroid Build Coastguard Worker             default:
106*9e94795aSAndroid Build Coastguard Worker                 new_name << *iter;
107*9e94795aSAndroid Build Coastguard Worker                 break;
108*9e94795aSAndroid Build Coastguard Worker         }
109*9e94795aSAndroid Build Coastguard Worker     }
110*9e94795aSAndroid Build Coastguard Worker     return new_name.str();
111*9e94795aSAndroid Build Coastguard Worker }
112*9e94795aSAndroid Build Coastguard Worker 
113*9e94795aSAndroid Build Coastguard Worker int
main(int argc,char * const * argv)114*9e94795aSAndroid Build Coastguard Worker main(int argc, char* const* argv)
115*9e94795aSAndroid Build Coastguard Worker {
116*9e94795aSAndroid Build Coastguard Worker     int err;
117*9e94795aSAndroid Build Coastguard Worker     bool done = false;
118*9e94795aSAndroid Build Coastguard Worker     while (!done) {
119*9e94795aSAndroid Build Coastguard Worker         int opt = getopt(argc, argv, "f:I:o:hlm:v:d");
120*9e94795aSAndroid Build Coastguard Worker         switch (opt)
121*9e94795aSAndroid Build Coastguard Worker         {
122*9e94795aSAndroid Build Coastguard Worker             case -1:
123*9e94795aSAndroid Build Coastguard Worker                 done = true;
124*9e94795aSAndroid Build Coastguard Worker                 break;
125*9e94795aSAndroid Build Coastguard Worker             case 'f':
126*9e94795aSAndroid Build Coastguard Worker                 g_listFiles.push_back(string(optarg));
127*9e94795aSAndroid Build Coastguard Worker                 break;
128*9e94795aSAndroid Build Coastguard Worker             case 'I':
129*9e94795aSAndroid Build Coastguard Worker                 g_inputBases.push_back(string(optarg));
130*9e94795aSAndroid Build Coastguard Worker                 break;
131*9e94795aSAndroid Build Coastguard Worker             case 'o':
132*9e94795aSAndroid Build Coastguard Worker                 if (g_outputBase.length() != 0) {
133*9e94795aSAndroid Build Coastguard Worker                     fprintf(stderr, "%s: -o may only be supplied once -- "
134*9e94795aSAndroid Build Coastguard Worker                                 "-o %s\n", argv[0], optarg);
135*9e94795aSAndroid Build Coastguard Worker                     return usage();
136*9e94795aSAndroid Build Coastguard Worker                 }
137*9e94795aSAndroid Build Coastguard Worker                 g_outputBase = optarg;
138*9e94795aSAndroid Build Coastguard Worker                 break;
139*9e94795aSAndroid Build Coastguard Worker             case 'l':
140*9e94795aSAndroid Build Coastguard Worker                 g_useHardLinks = true;
141*9e94795aSAndroid Build Coastguard Worker                 break;
142*9e94795aSAndroid Build Coastguard Worker             case 'm':
143*9e94795aSAndroid Build Coastguard Worker                 if (g_dependency.length() != 0) {
144*9e94795aSAndroid Build Coastguard Worker                     fprintf(stderr, "%s: -m may only be supplied once -- "
145*9e94795aSAndroid Build Coastguard Worker                                 "-m %s\n", argv[0], optarg);
146*9e94795aSAndroid Build Coastguard Worker                     return usage();
147*9e94795aSAndroid Build Coastguard Worker                 }
148*9e94795aSAndroid Build Coastguard Worker                 g_dependency = optarg;
149*9e94795aSAndroid Build Coastguard Worker                 break;
150*9e94795aSAndroid Build Coastguard Worker             case 'v':
151*9e94795aSAndroid Build Coastguard Worker                 if (!add_variable(optarg)) {
152*9e94795aSAndroid Build Coastguard Worker                     fprintf(stderr, "%s Invalid expression in '-v %s': "
153*9e94795aSAndroid Build Coastguard Worker                             "expected format is '-v VAR=VALUE'.\n",
154*9e94795aSAndroid Build Coastguard Worker                             argv[0], optarg);
155*9e94795aSAndroid Build Coastguard Worker                     return usage();
156*9e94795aSAndroid Build Coastguard Worker                 }
157*9e94795aSAndroid Build Coastguard Worker                 break;
158*9e94795aSAndroid Build Coastguard Worker             case 'd':
159*9e94795aSAndroid Build Coastguard Worker                 g_debug = true;
160*9e94795aSAndroid Build Coastguard Worker                 break;
161*9e94795aSAndroid Build Coastguard Worker             default:
162*9e94795aSAndroid Build Coastguard Worker             case '?':
163*9e94795aSAndroid Build Coastguard Worker             case 'h':
164*9e94795aSAndroid Build Coastguard Worker                 return usage();
165*9e94795aSAndroid Build Coastguard Worker         }
166*9e94795aSAndroid Build Coastguard Worker     }
167*9e94795aSAndroid Build Coastguard Worker     if (optind != argc) {
168*9e94795aSAndroid Build Coastguard Worker         fprintf(stderr, "%s: invalid argument -- %s\n", argv[0], argv[optind]);
169*9e94795aSAndroid Build Coastguard Worker         return usage();
170*9e94795aSAndroid Build Coastguard Worker     }
171*9e94795aSAndroid Build Coastguard Worker 
172*9e94795aSAndroid Build Coastguard Worker     if (g_listFiles.size() == 0) {
173*9e94795aSAndroid Build Coastguard Worker         fprintf(stderr, "%s: At least one -f option must be supplied.\n",
174*9e94795aSAndroid Build Coastguard Worker                  argv[0]);
175*9e94795aSAndroid Build Coastguard Worker         return usage();
176*9e94795aSAndroid Build Coastguard Worker     }
177*9e94795aSAndroid Build Coastguard Worker 
178*9e94795aSAndroid Build Coastguard Worker     if (g_inputBases.size() == 0) {
179*9e94795aSAndroid Build Coastguard Worker         fprintf(stderr, "%s: At least one -I option must be supplied.\n",
180*9e94795aSAndroid Build Coastguard Worker                  argv[0]);
181*9e94795aSAndroid Build Coastguard Worker         return usage();
182*9e94795aSAndroid Build Coastguard Worker     }
183*9e94795aSAndroid Build Coastguard Worker 
184*9e94795aSAndroid Build Coastguard Worker     if (g_outputBase.length() == 0) {
185*9e94795aSAndroid Build Coastguard Worker         fprintf(stderr, "%s: -o option must be supplied.\n", argv[0]);
186*9e94795aSAndroid Build Coastguard Worker         return usage();
187*9e94795aSAndroid Build Coastguard Worker     }
188*9e94795aSAndroid Build Coastguard Worker 
189*9e94795aSAndroid Build Coastguard Worker 
190*9e94795aSAndroid Build Coastguard Worker #if 0
191*9e94795aSAndroid Build Coastguard Worker     for (vector<string>::iterator it=g_listFiles.begin();
192*9e94795aSAndroid Build Coastguard Worker                                 it!=g_listFiles.end(); it++) {
193*9e94795aSAndroid Build Coastguard Worker         printf("-f \"%s\"\n", it->c_str());
194*9e94795aSAndroid Build Coastguard Worker     }
195*9e94795aSAndroid Build Coastguard Worker     for (vector<string>::iterator it=g_inputBases.begin();
196*9e94795aSAndroid Build Coastguard Worker                                 it!=g_inputBases.end(); it++) {
197*9e94795aSAndroid Build Coastguard Worker         printf("-I \"%s\"\n", it->c_str());
198*9e94795aSAndroid Build Coastguard Worker     }
199*9e94795aSAndroid Build Coastguard Worker     printf("-o \"%s\"\n", g_outputBase.c_str());
200*9e94795aSAndroid Build Coastguard Worker     if (g_useHardLinks) {
201*9e94795aSAndroid Build Coastguard Worker         printf("-l\n");
202*9e94795aSAndroid Build Coastguard Worker     }
203*9e94795aSAndroid Build Coastguard Worker #endif
204*9e94795aSAndroid Build Coastguard Worker 
205*9e94795aSAndroid Build Coastguard Worker     vector<FileRecord> files;
206*9e94795aSAndroid Build Coastguard Worker     vector<FileRecord> more;
207*9e94795aSAndroid Build Coastguard Worker     vector<string> excludes;
208*9e94795aSAndroid Build Coastguard Worker     set<string> directories;
209*9e94795aSAndroid Build Coastguard Worker     set<string> deleted;
210*9e94795aSAndroid Build Coastguard Worker 
211*9e94795aSAndroid Build Coastguard Worker     // read file lists
212*9e94795aSAndroid Build Coastguard Worker     for (vector<string>::iterator it=g_listFiles.begin();
213*9e94795aSAndroid Build Coastguard Worker                                  it!=g_listFiles.end(); it++) {
214*9e94795aSAndroid Build Coastguard Worker         err = read_list_file(*it, g_variables, &files, &excludes);
215*9e94795aSAndroid Build Coastguard Worker         if (err != 0) {
216*9e94795aSAndroid Build Coastguard Worker             return err;
217*9e94795aSAndroid Build Coastguard Worker         }
218*9e94795aSAndroid Build Coastguard Worker     }
219*9e94795aSAndroid Build Coastguard Worker 
220*9e94795aSAndroid Build Coastguard Worker     // look for input files
221*9e94795aSAndroid Build Coastguard Worker     err = 0;
222*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
223*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
224*9e94795aSAndroid Build Coastguard Worker         err |= locate(&(*it), g_inputBases);
225*9e94795aSAndroid Build Coastguard Worker     }
226*9e94795aSAndroid Build Coastguard Worker 
227*9e94795aSAndroid Build Coastguard Worker     // expand the directories that we should copy into a list of files
228*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
229*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
230*9e94795aSAndroid Build Coastguard Worker         if (it->sourceIsDir) {
231*9e94795aSAndroid Build Coastguard Worker             err |= list_dir(*it, excludes, &more);
232*9e94795aSAndroid Build Coastguard Worker         }
233*9e94795aSAndroid Build Coastguard Worker     }
234*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=more.begin();
235*9e94795aSAndroid Build Coastguard Worker                                 it!=more.end(); it++) {
236*9e94795aSAndroid Build Coastguard Worker         files.push_back(*it);
237*9e94795aSAndroid Build Coastguard Worker     }
238*9e94795aSAndroid Build Coastguard Worker 
239*9e94795aSAndroid Build Coastguard Worker     // get the name and modtime of the output files
240*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
241*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
242*9e94795aSAndroid Build Coastguard Worker         stat_out(g_outputBase, &(*it));
243*9e94795aSAndroid Build Coastguard Worker     }
244*9e94795aSAndroid Build Coastguard Worker 
245*9e94795aSAndroid Build Coastguard Worker     if (err != 0) {
246*9e94795aSAndroid Build Coastguard Worker         return 1;
247*9e94795aSAndroid Build Coastguard Worker     }
248*9e94795aSAndroid Build Coastguard Worker 
249*9e94795aSAndroid Build Coastguard Worker     // gather directories
250*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
251*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
252*9e94795aSAndroid Build Coastguard Worker         if (it->sourceIsDir) {
253*9e94795aSAndroid Build Coastguard Worker             directories.insert(it->outPath);
254*9e94795aSAndroid Build Coastguard Worker         } else {
255*9e94795aSAndroid Build Coastguard Worker             string s = dir_part(it->outPath);
256*9e94795aSAndroid Build Coastguard Worker             if (s != ".") {
257*9e94795aSAndroid Build Coastguard Worker                 directories.insert(s);
258*9e94795aSAndroid Build Coastguard Worker             }
259*9e94795aSAndroid Build Coastguard Worker         }
260*9e94795aSAndroid Build Coastguard Worker     }
261*9e94795aSAndroid Build Coastguard Worker 
262*9e94795aSAndroid Build Coastguard Worker     // gather files that should become directores
263*9e94795aSAndroid Build Coastguard Worker     // and directories that should become files
264*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
265*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
266*9e94795aSAndroid Build Coastguard Worker         if (it->outMod != 0 && it->sourceIsDir != it->outIsDir) {
267*9e94795aSAndroid Build Coastguard Worker             deleted.insert(it->outPath);
268*9e94795aSAndroid Build Coastguard Worker         }
269*9e94795aSAndroid Build Coastguard Worker     }
270*9e94795aSAndroid Build Coastguard Worker 
271*9e94795aSAndroid Build Coastguard Worker     // delete files
272*9e94795aSAndroid Build Coastguard Worker     for (set<string>::iterator it=deleted.begin();
273*9e94795aSAndroid Build Coastguard Worker                                 it!=deleted.end(); it++) {
274*9e94795aSAndroid Build Coastguard Worker         debug_printf("deleting %s\n", it->c_str());
275*9e94795aSAndroid Build Coastguard Worker         err = remove_recursively(*it);
276*9e94795aSAndroid Build Coastguard Worker         if (err != 0) {
277*9e94795aSAndroid Build Coastguard Worker             return err;
278*9e94795aSAndroid Build Coastguard Worker         }
279*9e94795aSAndroid Build Coastguard Worker     }
280*9e94795aSAndroid Build Coastguard Worker 
281*9e94795aSAndroid Build Coastguard Worker     // remove all files or directories as requested from the input atree file.
282*9e94795aSAndroid Build Coastguard Worker     // must be done before create new directories.
283*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
284*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
285*9e94795aSAndroid Build Coastguard Worker         if (!it->sourceIsDir) {
286*9e94795aSAndroid Build Coastguard Worker             if (it->fileOp == FILE_OP_REMOVE &&
287*9e94795aSAndroid Build Coastguard Worker                     deleted.count(it->outPath) == 0) {
288*9e94795aSAndroid Build Coastguard Worker                 debug_printf("remove %s\n", it->outPath.c_str());
289*9e94795aSAndroid Build Coastguard Worker                 err = remove_recursively(it->outPath);
290*9e94795aSAndroid Build Coastguard Worker                 if (err != 0) {
291*9e94795aSAndroid Build Coastguard Worker                     return err;
292*9e94795aSAndroid Build Coastguard Worker                 }
293*9e94795aSAndroid Build Coastguard Worker             }
294*9e94795aSAndroid Build Coastguard Worker         }
295*9e94795aSAndroid Build Coastguard Worker     }
296*9e94795aSAndroid Build Coastguard Worker 
297*9e94795aSAndroid Build Coastguard Worker     // make directories
298*9e94795aSAndroid Build Coastguard Worker     for (set<string>::iterator it=directories.begin();
299*9e94795aSAndroid Build Coastguard Worker                                 it!=directories.end(); it++) {
300*9e94795aSAndroid Build Coastguard Worker         debug_printf("mkdir %s\n", it->c_str());
301*9e94795aSAndroid Build Coastguard Worker         err = mkdir_recursively(*it);
302*9e94795aSAndroid Build Coastguard Worker         if (err != 0) {
303*9e94795aSAndroid Build Coastguard Worker             return err;
304*9e94795aSAndroid Build Coastguard Worker         }
305*9e94795aSAndroid Build Coastguard Worker     }
306*9e94795aSAndroid Build Coastguard Worker 
307*9e94795aSAndroid Build Coastguard Worker     // copy (or link) files that are newer or of different size
308*9e94795aSAndroid Build Coastguard Worker     for (vector<FileRecord>::iterator it=files.begin();
309*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
310*9e94795aSAndroid Build Coastguard Worker         if (!it->sourceIsDir) {
311*9e94795aSAndroid Build Coastguard Worker             if (it->fileOp == FILE_OP_REMOVE) {
312*9e94795aSAndroid Build Coastguard Worker                 continue;
313*9e94795aSAndroid Build Coastguard Worker             }
314*9e94795aSAndroid Build Coastguard Worker 
315*9e94795aSAndroid Build Coastguard Worker             debug_printf("copy %s(%ld) ==> %s(%ld)",
316*9e94795aSAndroid Build Coastguard Worker                 it->sourcePath.c_str(), it->sourceMod,
317*9e94795aSAndroid Build Coastguard Worker                 it->outPath.c_str(), it->outMod);
318*9e94795aSAndroid Build Coastguard Worker 
319*9e94795aSAndroid Build Coastguard Worker             if (it->outSize != it->sourceSize || it->outMod < it->sourceMod) {
320*9e94795aSAndroid Build Coastguard Worker                 err = copy_file(it->sourcePath, it->outPath);
321*9e94795aSAndroid Build Coastguard Worker                 debug_printf(" done.\n");
322*9e94795aSAndroid Build Coastguard Worker                 if (err != 0) {
323*9e94795aSAndroid Build Coastguard Worker                     return err;
324*9e94795aSAndroid Build Coastguard Worker                 }
325*9e94795aSAndroid Build Coastguard Worker             } else {
326*9e94795aSAndroid Build Coastguard Worker                 debug_printf(" skipping.\n");
327*9e94795aSAndroid Build Coastguard Worker             }
328*9e94795aSAndroid Build Coastguard Worker 
329*9e94795aSAndroid Build Coastguard Worker             if (it->fileOp == FILE_OP_STRIP) {
330*9e94795aSAndroid Build Coastguard Worker                 debug_printf("strip %s\n", it->outPath.c_str());
331*9e94795aSAndroid Build Coastguard Worker                 err = strip_file(it->outPath);
332*9e94795aSAndroid Build Coastguard Worker                 if (err != 0) {
333*9e94795aSAndroid Build Coastguard Worker                     return err;
334*9e94795aSAndroid Build Coastguard Worker                 }
335*9e94795aSAndroid Build Coastguard Worker             }
336*9e94795aSAndroid Build Coastguard Worker         }
337*9e94795aSAndroid Build Coastguard Worker     }
338*9e94795aSAndroid Build Coastguard Worker 
339*9e94795aSAndroid Build Coastguard Worker     // output the dependency file
340*9e94795aSAndroid Build Coastguard Worker     if (g_dependency.length() != 0) {
341*9e94795aSAndroid Build Coastguard Worker         FILE *f = fopen(g_dependency.c_str(), "w");
342*9e94795aSAndroid Build Coastguard Worker         if (f != NULL) {
343*9e94795aSAndroid Build Coastguard Worker             fprintf(f, "ATREE_FILES := $(ATREE_FILES) \\\n");
344*9e94795aSAndroid Build Coastguard Worker             for (vector<FileRecord>::iterator it=files.begin();
345*9e94795aSAndroid Build Coastguard Worker                                 it!=files.end(); it++) {
346*9e94795aSAndroid Build Coastguard Worker                 if (!it->sourceIsDir) {
347*9e94795aSAndroid Build Coastguard Worker                     fprintf(f, "%s \\\n",
348*9e94795aSAndroid Build Coastguard Worker                             escape_filename(it->sourcePath).c_str());
349*9e94795aSAndroid Build Coastguard Worker                 }
350*9e94795aSAndroid Build Coastguard Worker             }
351*9e94795aSAndroid Build Coastguard Worker             fprintf(f, "\n");
352*9e94795aSAndroid Build Coastguard Worker             fclose(f);
353*9e94795aSAndroid Build Coastguard Worker         } else {
354*9e94795aSAndroid Build Coastguard Worker             fprintf(stderr, "error opening manifest file for write: %s\n",
355*9e94795aSAndroid Build Coastguard Worker                     g_dependency.c_str());
356*9e94795aSAndroid Build Coastguard Worker         }
357*9e94795aSAndroid Build Coastguard Worker     }
358*9e94795aSAndroid Build Coastguard Worker 
359*9e94795aSAndroid Build Coastguard Worker     return 0;
360*9e94795aSAndroid Build Coastguard Worker }
361