1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2016 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "util.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include <sys/types.h>
20*d57664e9SAndroid Build Coastguard Worker #include <sys/stat.h>
21*d57664e9SAndroid Build Coastguard Worker #include <dirent.h>
22*d57664e9SAndroid Build Coastguard Worker #include <string.h>
23*d57664e9SAndroid Build Coastguard Worker #include <unistd.h>
24*d57664e9SAndroid Build Coastguard Worker
25*d57664e9SAndroid Build Coastguard Worker
FileInfo()26*d57664e9SAndroid Build Coastguard Worker FileInfo::FileInfo()
27*d57664e9SAndroid Build Coastguard Worker {
28*d57664e9SAndroid Build Coastguard Worker memset(this, 0, sizeof(FileInfo));
29*d57664e9SAndroid Build Coastguard Worker }
30*d57664e9SAndroid Build Coastguard Worker
FileInfo(const FileInfo & that)31*d57664e9SAndroid Build Coastguard Worker FileInfo::FileInfo(const FileInfo& that)
32*d57664e9SAndroid Build Coastguard Worker {
33*d57664e9SAndroid Build Coastguard Worker memcpy(this, &that, sizeof(FileInfo));
34*d57664e9SAndroid Build Coastguard Worker }
35*d57664e9SAndroid Build Coastguard Worker
FileInfo(const string & filename)36*d57664e9SAndroid Build Coastguard Worker FileInfo::FileInfo(const string& filename)
37*d57664e9SAndroid Build Coastguard Worker {
38*d57664e9SAndroid Build Coastguard Worker struct stat st;
39*d57664e9SAndroid Build Coastguard Worker int err = stat(filename.c_str(), &st);
40*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
41*d57664e9SAndroid Build Coastguard Worker memset(this, 0, sizeof(FileInfo));
42*d57664e9SAndroid Build Coastguard Worker } else {
43*d57664e9SAndroid Build Coastguard Worker exists = true;
44*d57664e9SAndroid Build Coastguard Worker mtime = st.st_mtime;
45*d57664e9SAndroid Build Coastguard Worker ctime = st.st_ctime;
46*d57664e9SAndroid Build Coastguard Worker size = st.st_size;
47*d57664e9SAndroid Build Coastguard Worker }
48*d57664e9SAndroid Build Coastguard Worker }
49*d57664e9SAndroid Build Coastguard Worker
50*d57664e9SAndroid Build Coastguard Worker bool
operator ==(const FileInfo & that) const51*d57664e9SAndroid Build Coastguard Worker FileInfo::operator==(const FileInfo& that) const
52*d57664e9SAndroid Build Coastguard Worker {
53*d57664e9SAndroid Build Coastguard Worker return exists == that.exists
54*d57664e9SAndroid Build Coastguard Worker && mtime == that.mtime
55*d57664e9SAndroid Build Coastguard Worker && ctime == that.ctime
56*d57664e9SAndroid Build Coastguard Worker && size == that.size;
57*d57664e9SAndroid Build Coastguard Worker }
58*d57664e9SAndroid Build Coastguard Worker
59*d57664e9SAndroid Build Coastguard Worker bool
operator !=(const FileInfo & that) const60*d57664e9SAndroid Build Coastguard Worker FileInfo::operator!=(const FileInfo& that) const
61*d57664e9SAndroid Build Coastguard Worker {
62*d57664e9SAndroid Build Coastguard Worker return exists != that.exists
63*d57664e9SAndroid Build Coastguard Worker || mtime != that.mtime
64*d57664e9SAndroid Build Coastguard Worker || ctime != that.ctime
65*d57664e9SAndroid Build Coastguard Worker || size != that.size;
66*d57664e9SAndroid Build Coastguard Worker }
67*d57664e9SAndroid Build Coastguard Worker
~FileInfo()68*d57664e9SAndroid Build Coastguard Worker FileInfo::~FileInfo()
69*d57664e9SAndroid Build Coastguard Worker {
70*d57664e9SAndroid Build Coastguard Worker }
71*d57664e9SAndroid Build Coastguard Worker
TrackedFile()72*d57664e9SAndroid Build Coastguard Worker TrackedFile::TrackedFile()
73*d57664e9SAndroid Build Coastguard Worker :filename(),
74*d57664e9SAndroid Build Coastguard Worker fileInfo()
75*d57664e9SAndroid Build Coastguard Worker {
76*d57664e9SAndroid Build Coastguard Worker }
77*d57664e9SAndroid Build Coastguard Worker
TrackedFile(const TrackedFile & that)78*d57664e9SAndroid Build Coastguard Worker TrackedFile::TrackedFile(const TrackedFile& that)
79*d57664e9SAndroid Build Coastguard Worker {
80*d57664e9SAndroid Build Coastguard Worker filename = that.filename;
81*d57664e9SAndroid Build Coastguard Worker fileInfo = that.fileInfo;
82*d57664e9SAndroid Build Coastguard Worker }
83*d57664e9SAndroid Build Coastguard Worker
TrackedFile(const string & file)84*d57664e9SAndroid Build Coastguard Worker TrackedFile::TrackedFile(const string& file)
85*d57664e9SAndroid Build Coastguard Worker :filename(file),
86*d57664e9SAndroid Build Coastguard Worker fileInfo(file)
87*d57664e9SAndroid Build Coastguard Worker {
88*d57664e9SAndroid Build Coastguard Worker }
89*d57664e9SAndroid Build Coastguard Worker
~TrackedFile()90*d57664e9SAndroid Build Coastguard Worker TrackedFile::~TrackedFile()
91*d57664e9SAndroid Build Coastguard Worker {
92*d57664e9SAndroid Build Coastguard Worker }
93*d57664e9SAndroid Build Coastguard Worker
94*d57664e9SAndroid Build Coastguard Worker bool
HasChanged() const95*d57664e9SAndroid Build Coastguard Worker TrackedFile::HasChanged() const
96*d57664e9SAndroid Build Coastguard Worker {
97*d57664e9SAndroid Build Coastguard Worker FileInfo updated(filename);
98*d57664e9SAndroid Build Coastguard Worker return !updated.exists || fileInfo != updated;
99*d57664e9SAndroid Build Coastguard Worker }
100*d57664e9SAndroid Build Coastguard Worker
101*d57664e9SAndroid Build Coastguard Worker void
get_directory_contents(const string & name,map<string,FileInfo> * results)102*d57664e9SAndroid Build Coastguard Worker get_directory_contents(const string& name, map<string,FileInfo>* results)
103*d57664e9SAndroid Build Coastguard Worker {
104*d57664e9SAndroid Build Coastguard Worker DIR* dir = opendir(name.c_str());
105*d57664e9SAndroid Build Coastguard Worker if (dir == NULL) {
106*d57664e9SAndroid Build Coastguard Worker return;
107*d57664e9SAndroid Build Coastguard Worker }
108*d57664e9SAndroid Build Coastguard Worker
109*d57664e9SAndroid Build Coastguard Worker dirent* entry;
110*d57664e9SAndroid Build Coastguard Worker while ((entry = readdir(dir)) != NULL) {
111*d57664e9SAndroid Build Coastguard Worker if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
112*d57664e9SAndroid Build Coastguard Worker continue;
113*d57664e9SAndroid Build Coastguard Worker }
114*d57664e9SAndroid Build Coastguard Worker if (entry->d_type == DT_DIR) {
115*d57664e9SAndroid Build Coastguard Worker string subdir = name + "/" + entry->d_name;
116*d57664e9SAndroid Build Coastguard Worker get_directory_contents(subdir, results);
117*d57664e9SAndroid Build Coastguard Worker } else if (entry->d_type == DT_LNK || entry->d_type == DT_REG) {
118*d57664e9SAndroid Build Coastguard Worker string filename(name + "/" + entry->d_name);
119*d57664e9SAndroid Build Coastguard Worker (*results)[filename] = FileInfo(filename);
120*d57664e9SAndroid Build Coastguard Worker }
121*d57664e9SAndroid Build Coastguard Worker }
122*d57664e9SAndroid Build Coastguard Worker
123*d57664e9SAndroid Build Coastguard Worker closedir(dir);
124*d57664e9SAndroid Build Coastguard Worker }
125*d57664e9SAndroid Build Coastguard Worker
126*d57664e9SAndroid Build Coastguard Worker bool
directory_contents_differ(const map<string,FileInfo> & before,const map<string,FileInfo> & after)127*d57664e9SAndroid Build Coastguard Worker directory_contents_differ(const map<string,FileInfo>& before, const map<string,FileInfo>& after)
128*d57664e9SAndroid Build Coastguard Worker {
129*d57664e9SAndroid Build Coastguard Worker if (before.size() != after.size()) {
130*d57664e9SAndroid Build Coastguard Worker return true;
131*d57664e9SAndroid Build Coastguard Worker }
132*d57664e9SAndroid Build Coastguard Worker map<string,FileInfo>::const_iterator b = before.begin();
133*d57664e9SAndroid Build Coastguard Worker map<string,FileInfo>::const_iterator a = after.begin();
134*d57664e9SAndroid Build Coastguard Worker while (b != before.end() && a != after.end()) {
135*d57664e9SAndroid Build Coastguard Worker if (b->first != a->first) {
136*d57664e9SAndroid Build Coastguard Worker return true;
137*d57664e9SAndroid Build Coastguard Worker }
138*d57664e9SAndroid Build Coastguard Worker if (a->second != b->second) {
139*d57664e9SAndroid Build Coastguard Worker return true;
140*d57664e9SAndroid Build Coastguard Worker }
141*d57664e9SAndroid Build Coastguard Worker a++;
142*d57664e9SAndroid Build Coastguard Worker b++;
143*d57664e9SAndroid Build Coastguard Worker }
144*d57664e9SAndroid Build Coastguard Worker return false;
145*d57664e9SAndroid Build Coastguard Worker }
146*d57664e9SAndroid Build Coastguard Worker
147*d57664e9SAndroid Build Coastguard Worker string
escape_quotes(const char * str)148*d57664e9SAndroid Build Coastguard Worker escape_quotes(const char* str)
149*d57664e9SAndroid Build Coastguard Worker {
150*d57664e9SAndroid Build Coastguard Worker string result;
151*d57664e9SAndroid Build Coastguard Worker while (*str) {
152*d57664e9SAndroid Build Coastguard Worker if (*str == '"') {
153*d57664e9SAndroid Build Coastguard Worker result += '\\';
154*d57664e9SAndroid Build Coastguard Worker result += '"';
155*d57664e9SAndroid Build Coastguard Worker } else {
156*d57664e9SAndroid Build Coastguard Worker result += *str;
157*d57664e9SAndroid Build Coastguard Worker }
158*d57664e9SAndroid Build Coastguard Worker }
159*d57664e9SAndroid Build Coastguard Worker return result;
160*d57664e9SAndroid Build Coastguard Worker }
161*d57664e9SAndroid Build Coastguard Worker
162*d57664e9SAndroid Build Coastguard Worker string
escape_for_commandline(const char * str)163*d57664e9SAndroid Build Coastguard Worker escape_for_commandline(const char* str)
164*d57664e9SAndroid Build Coastguard Worker {
165*d57664e9SAndroid Build Coastguard Worker if (strchr(str, '"') != NULL || strchr(str, ' ') != NULL
166*d57664e9SAndroid Build Coastguard Worker || strchr(str, '\t') != NULL) {
167*d57664e9SAndroid Build Coastguard Worker return escape_quotes(str);
168*d57664e9SAndroid Build Coastguard Worker } else {
169*d57664e9SAndroid Build Coastguard Worker return str;
170*d57664e9SAndroid Build Coastguard Worker }
171*d57664e9SAndroid Build Coastguard Worker }
172*d57664e9SAndroid Build Coastguard Worker
173*d57664e9SAndroid Build Coastguard Worker static bool
spacechr(char c)174*d57664e9SAndroid Build Coastguard Worker spacechr(char c)
175*d57664e9SAndroid Build Coastguard Worker {
176*d57664e9SAndroid Build Coastguard Worker return c == ' ' || c == '\t' || c == '\n' || c == '\r';
177*d57664e9SAndroid Build Coastguard Worker }
178*d57664e9SAndroid Build Coastguard Worker
179*d57664e9SAndroid Build Coastguard Worker string
trim(const string & str)180*d57664e9SAndroid Build Coastguard Worker trim(const string& str)
181*d57664e9SAndroid Build Coastguard Worker {
182*d57664e9SAndroid Build Coastguard Worker const ssize_t N = (ssize_t)str.size();
183*d57664e9SAndroid Build Coastguard Worker ssize_t begin = 0;
184*d57664e9SAndroid Build Coastguard Worker while (begin < N && spacechr(str[begin])) {
185*d57664e9SAndroid Build Coastguard Worker begin++;
186*d57664e9SAndroid Build Coastguard Worker }
187*d57664e9SAndroid Build Coastguard Worker ssize_t end = N - 1;
188*d57664e9SAndroid Build Coastguard Worker while (end >= begin && spacechr(str[end])) {
189*d57664e9SAndroid Build Coastguard Worker end--;
190*d57664e9SAndroid Build Coastguard Worker }
191*d57664e9SAndroid Build Coastguard Worker return string(str, begin, end-begin+1);
192*d57664e9SAndroid Build Coastguard Worker }
193*d57664e9SAndroid Build Coastguard Worker
194*d57664e9SAndroid Build Coastguard Worker bool
starts_with(const string & str,const string & prefix)195*d57664e9SAndroid Build Coastguard Worker starts_with(const string& str, const string& prefix)
196*d57664e9SAndroid Build Coastguard Worker {
197*d57664e9SAndroid Build Coastguard Worker return str.compare(0, prefix.length(), prefix) == 0;
198*d57664e9SAndroid Build Coastguard Worker }
199*d57664e9SAndroid Build Coastguard Worker
200*d57664e9SAndroid Build Coastguard Worker bool
ends_with(const string & str,const string & suffix)201*d57664e9SAndroid Build Coastguard Worker ends_with(const string& str, const string& suffix)
202*d57664e9SAndroid Build Coastguard Worker {
203*d57664e9SAndroid Build Coastguard Worker if (str.length() < suffix.length()) {
204*d57664e9SAndroid Build Coastguard Worker return false;
205*d57664e9SAndroid Build Coastguard Worker } else {
206*d57664e9SAndroid Build Coastguard Worker return str.compare(str.length()-suffix.length(), suffix.length(), suffix) == 0;
207*d57664e9SAndroid Build Coastguard Worker }
208*d57664e9SAndroid Build Coastguard Worker }
209*d57664e9SAndroid Build Coastguard Worker
210*d57664e9SAndroid Build Coastguard Worker void
split_lines(vector<string> * result,const string & str)211*d57664e9SAndroid Build Coastguard Worker split_lines(vector<string>* result, const string& str)
212*d57664e9SAndroid Build Coastguard Worker {
213*d57664e9SAndroid Build Coastguard Worker const int N = str.length();
214*d57664e9SAndroid Build Coastguard Worker int begin = 0;
215*d57664e9SAndroid Build Coastguard Worker int end = 0;
216*d57664e9SAndroid Build Coastguard Worker for (; end < N; end++) {
217*d57664e9SAndroid Build Coastguard Worker const char c = str[end];
218*d57664e9SAndroid Build Coastguard Worker if (c == '\r' || c == '\n') {
219*d57664e9SAndroid Build Coastguard Worker if (begin != end) {
220*d57664e9SAndroid Build Coastguard Worker result->push_back(string(str, begin, end-begin));
221*d57664e9SAndroid Build Coastguard Worker }
222*d57664e9SAndroid Build Coastguard Worker begin = end+1;
223*d57664e9SAndroid Build Coastguard Worker }
224*d57664e9SAndroid Build Coastguard Worker }
225*d57664e9SAndroid Build Coastguard Worker if (begin != end) {
226*d57664e9SAndroid Build Coastguard Worker result->push_back(string(str, begin, end-begin));
227*d57664e9SAndroid Build Coastguard Worker }
228*d57664e9SAndroid Build Coastguard Worker }
229*d57664e9SAndroid Build Coastguard Worker
230*d57664e9SAndroid Build Coastguard Worker string
read_file(const string & filename)231*d57664e9SAndroid Build Coastguard Worker read_file(const string& filename)
232*d57664e9SAndroid Build Coastguard Worker {
233*d57664e9SAndroid Build Coastguard Worker FILE* file = fopen(filename.c_str(), "r");
234*d57664e9SAndroid Build Coastguard Worker if (file == NULL) {
235*d57664e9SAndroid Build Coastguard Worker return string();
236*d57664e9SAndroid Build Coastguard Worker }
237*d57664e9SAndroid Build Coastguard Worker
238*d57664e9SAndroid Build Coastguard Worker fseek(file, 0, SEEK_END);
239*d57664e9SAndroid Build Coastguard Worker int size = ftell(file);
240*d57664e9SAndroid Build Coastguard Worker fseek(file, 0, SEEK_SET);
241*d57664e9SAndroid Build Coastguard Worker
242*d57664e9SAndroid Build Coastguard Worker char* buf = (char*)malloc(size);
243*d57664e9SAndroid Build Coastguard Worker if ((size_t) size != fread(buf, 1, size, file)) {
244*d57664e9SAndroid Build Coastguard Worker free(buf);
245*d57664e9SAndroid Build Coastguard Worker fclose(file);
246*d57664e9SAndroid Build Coastguard Worker return string();
247*d57664e9SAndroid Build Coastguard Worker }
248*d57664e9SAndroid Build Coastguard Worker
249*d57664e9SAndroid Build Coastguard Worker string result(buf, size);
250*d57664e9SAndroid Build Coastguard Worker
251*d57664e9SAndroid Build Coastguard Worker free(buf);
252*d57664e9SAndroid Build Coastguard Worker fclose(file);
253*d57664e9SAndroid Build Coastguard Worker
254*d57664e9SAndroid Build Coastguard Worker return result;
255*d57664e9SAndroid Build Coastguard Worker }
256*d57664e9SAndroid Build Coastguard Worker
257*d57664e9SAndroid Build Coastguard Worker bool
is_executable(const string & filename)258*d57664e9SAndroid Build Coastguard Worker is_executable(const string& filename)
259*d57664e9SAndroid Build Coastguard Worker {
260*d57664e9SAndroid Build Coastguard Worker int err;
261*d57664e9SAndroid Build Coastguard Worker struct stat st;
262*d57664e9SAndroid Build Coastguard Worker
263*d57664e9SAndroid Build Coastguard Worker err = stat(filename.c_str(), &st);
264*d57664e9SAndroid Build Coastguard Worker if (err != 0) {
265*d57664e9SAndroid Build Coastguard Worker return false;
266*d57664e9SAndroid Build Coastguard Worker }
267*d57664e9SAndroid Build Coastguard Worker
268*d57664e9SAndroid Build Coastguard Worker return (st.st_mode & S_IXUSR) != 0;
269*d57664e9SAndroid Build Coastguard Worker }
270*d57664e9SAndroid Build Coastguard Worker
271*d57664e9SAndroid Build Coastguard Worker string
dirname(const string & filename)272*d57664e9SAndroid Build Coastguard Worker dirname(const string& filename)
273*d57664e9SAndroid Build Coastguard Worker {
274*d57664e9SAndroid Build Coastguard Worker size_t slash = filename.rfind('/');
275*d57664e9SAndroid Build Coastguard Worker if (slash == string::npos) {
276*d57664e9SAndroid Build Coastguard Worker return "";
277*d57664e9SAndroid Build Coastguard Worker } else if (slash == 0) {
278*d57664e9SAndroid Build Coastguard Worker return "/";
279*d57664e9SAndroid Build Coastguard Worker } else {
280*d57664e9SAndroid Build Coastguard Worker return string(filename, 0, slash);
281*d57664e9SAndroid Build Coastguard Worker }
282*d57664e9SAndroid Build Coastguard Worker }
283*d57664e9SAndroid Build Coastguard Worker
284*d57664e9SAndroid Build Coastguard Worker string
leafname(const string & filename)285*d57664e9SAndroid Build Coastguard Worker leafname(const string& filename)
286*d57664e9SAndroid Build Coastguard Worker {
287*d57664e9SAndroid Build Coastguard Worker size_t slash = filename.rfind('/');
288*d57664e9SAndroid Build Coastguard Worker if (slash == string::npos) {
289*d57664e9SAndroid Build Coastguard Worker return filename;
290*d57664e9SAndroid Build Coastguard Worker } else if (slash == filename.length() - 1) {
291*d57664e9SAndroid Build Coastguard Worker return "";
292*d57664e9SAndroid Build Coastguard Worker } else {
293*d57664e9SAndroid Build Coastguard Worker return string(filename, slash + 1);
294*d57664e9SAndroid Build Coastguard Worker }
295*d57664e9SAndroid Build Coastguard Worker }
296