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