Home | History | Annotate | Download | only in bit
      1 /*
      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 
     26 FileInfo::FileInfo()
     27 {
     28     memset(this, 0, sizeof(FileInfo));
     29 }
     30 
     31 FileInfo::FileInfo(const FileInfo& that)
     32 {
     33     memcpy(this, &that, sizeof(FileInfo));
     34 }
     35 
     36 FileInfo::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 
     50 bool
     51 FileInfo::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 
     59 bool
     60 FileInfo::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 
     68 FileInfo::~FileInfo()
     69 {
     70 }
     71 
     72 TrackedFile::TrackedFile()
     73     :filename(),
     74      fileInfo()
     75 {
     76 }
     77 
     78 TrackedFile::TrackedFile(const TrackedFile& that)
     79 {
     80     filename = that.filename;
     81     fileInfo = that.fileInfo;
     82 }
     83 
     84 TrackedFile::TrackedFile(const string& file)
     85     :filename(file),
     86      fileInfo(file)
     87 {
     88 }
     89 
     90 TrackedFile::~TrackedFile()
     91 {
     92 }
     93 
     94 bool
     95 TrackedFile::HasChanged() const
     96 {
     97     FileInfo updated(filename);
     98     return !updated.exists || fileInfo != updated;
     99 }
    100 
    101 void
    102 get_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 
    127 bool
    128 directory_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 
    148 string
    149 escape_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 
    163 string
    164 escape_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 
    174 static bool
    175 spacechr(char c)
    176 {
    177     return c == ' ' || c == '\t' || c == '\n' || c == '\r';
    178 }
    179 
    180 string
    181 trim(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 
    195 bool
    196 starts_with(const string& str, const string& prefix)
    197 {
    198     return str.compare(0, prefix.length(), prefix) == 0;
    199 }
    200 
    201 bool
    202 ends_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 
    211 void
    212 split_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 
    231 string
    232 read_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 
    255