android init -- LoadPropertyInfoFromFile 源码分析

概述:

代码路径: system/core/init/property_service.cpp
用处:
加载属性的se信息

代码

// 从文件中读取属性信息
/** 文件内容格式
ro.product.cpu.abi       u:object_r:build_prop:s0 exact string
ro.product.cpu.abilist   u:object_r:build_prop:s0 exact string
ro.product.cpu.abilist32 u:object_r:build_prop:s0 exact string
ro.product.cpu.abilist64 u:object_r:build_prop:s0 exact string
*/

void CreateSerializedPropertyInfo() {
    auto property_infos = std::vector<PropertyInfoEntry>();
    if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
        if (!LoadPropertyInfoFromFile("/system/etc/selinux/plat_property_contexts",
                                      &property_infos)) {
            return;
        }
        ...
    }
}

// PropertyInfoEntry 结构体 

struct PropertyInfoEntry {
  PropertyInfoEntry() {}
  template <typename T, typename U, typename V>
  PropertyInfoEntry(T&& name, U&& context, V&& type, bool exact_match)
      : name(std::forward<T>(name)),
        context(std::forward<U>(context)),
        type(std::forward<V>(type)),
        exact_match(exact_match) {}
  std::string name;
  std::string context;
  std::string type;
  bool exact_match;
};

LoadPropertyInfoFromFile

bool LoadPropertyInfoFromFile(const std::string& filename,
                              std::vector<PropertyInfoEntry>* property_infos) {
    auto file_contents = std::string();
    // 将文件内容读取到字符串中,
    // 参考连接:https://blog.csdn.net/u014023550/article/details/129063608
    if (!ReadFileToString(filename, &file_contents)) {
        PLOG(ERROR) << "Could not read properties from '" << filename << "'";
        return false;
    }

    auto errors = std::vector<std::string>{};
    bool require_prefix_or_exact = SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__;
    ParsePropertyInfoFile(file_contents, require_prefix_or_exact, property_infos, &errors);
    // Individual parsing errors are reported but do not cause a failed boot, which is what
    // returning false would do here.
    for (const auto& error : errors) {
        LOG(ERROR) << "Could not read line from '" << filename << "': " << error;
    }

    return true;
}

ParsePropertyInfoFile

将字符串分隔成一行一行的字符串,在将每一行的信息放入到PropertyInfoEntry 结构体中。

void ParsePropertyInfoFile(const std::string& file_contents, bool require_prefix_or_exact,
                           std::vector<PropertyInfoEntry>* property_infos,
                           std::vector<std::string>* errors) {
  // Do not clear property_infos to allow this function to be called on multiple files, with
  // their results concatenated.
  errors->clear();
  for (const auto& line : Split(file_contents, "\n")) {
    auto trimmed_line = Trim(line);
    // 过滤空行和注释行
    if (trimmed_line.empty() || StartsWith(trimmed_line, "#")) {
      continue;
    }

    auto property_info_entry = PropertyInfoEntry{};
    auto parse_error = std::string{};
    if (!ParsePropertyInfoLine(trimmed_line, require_prefix_or_exact, &property_info_entry,
                               &parse_error)) {
      errors->emplace_back(parse_error);
      continue;
    }

    property_infos->emplace_back(property_info_entry);
  }
}

ParsePropertyInfoLine
通过 SpaceTokenizer 挨个读取对应信息

bool ParsePropertyInfoLine(const std::string& line, bool require_prefix_or_exact,
                           PropertyInfoEntry* out, std::string* error) {
  auto tokenizer = SpaceTokenizer(line);

  auto property = tokenizer.GetNext();
  if (property.empty()) {
    *error = "Did not find a property entry in '" + line + "'";
    return false;
  }

  auto context = tokenizer.GetNext();
  if (context.empty()) {
    *error = "Did not find a context entry in '" + line + "'";
    return false;
  }

  // It is not an error to not find exact_match or a type, as older files will not contain them.
  auto match_operation = tokenizer.GetNext();
  // We reformat type to be space deliminated regardless of the input whitespace for easier storage
  // and subsequent parsing.
  auto type_strings = std::vector<std::string>{};
  auto type = tokenizer.GetNext();
  while (!type.empty()) {
    type_strings.emplace_back(type);
    type = tokenizer.GetNext();
  }

  bool exact_match = false;
  if (match_operation == "exact") {
    exact_match = true;
  } else if (match_operation != "prefix" && match_operation != "" && require_prefix_or_exact) {
    *error = "Match operation '" + match_operation +
             "' is not valid: must be either 'prefix' or 'exact'";
    return false;
  }

  if (!type_strings.empty() && !IsTypeValid(type_strings)) {
    *error = "Type '" + Join(type_strings, " ") + "' is not valid";
    return false;
  }

  *out = {property, context, Join(type_strings, " "), exact_match};
  return true;
}

**SpaceTokenizer **

class SpaceTokenizer {
 public:
  SpaceTokenizer(const std::string& string)
      : string_(string), it_(string_.begin()), end_(string_.end()) {}

  // 获取字符串中的单词,然后跳过空白符
  std::string GetNext() {
    auto next = std::string();
	
	// 获取单词
    while (it_ != end_ && !isspace(*it_)) {
      next.push_back(*it_++);
    }

	// 跳过空白符
    while (it_ != end_ && isspace(*it_)) {
      it_++;
    }
    return next;
  }

  std::string GetRemaining() { return std::string(it_, end_); }

 private:
  std::string string_;
  std::string::const_iterator it_;
  std::string::const_iterator end_;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值