xref: /aosp_15_r20/frameworks/base/tools/bit/util.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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