1// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "policy/resilient_policy_util.h"
6
7#include <algorithm>
8
9#include <base/files/file_enumerator.h>
10#include <base/files/file_util.h>
11#include <base/strings/string_number_conversions.h>
12#include <base/strings/string_util.h>
13
14namespace policy {
15
16std::map<int, base::FilePath> GetSortedResilientPolicyFilePaths(
17    const base::FilePath& default_policy_path) {
18  std::map<int, base::FilePath> sorted_policy_file_paths;
19  base::FilePath directory = default_policy_path.DirName();
20  if (!base::PathExists(directory))
21    return sorted_policy_file_paths;
22
23  // Iterate the list of files in the folder, identifying the policy files based
24  // on the name. Store in the map the absolute paths.
25  const std::string default_policy_file_name =
26      default_policy_path.BaseName().value();
27  base::FileEnumerator file_iter(directory, false, base::FileEnumerator::FILES);
28  for (base::FilePath child_file = file_iter.Next(); !child_file.empty();
29       child_file = file_iter.Next()) {
30    int index;
31    if (ParseResilientPolicyFilePath(child_file, default_policy_path, &index)) {
32      sorted_policy_file_paths[index] = child_file;
33    }
34  }
35
36  return sorted_policy_file_paths;
37}
38
39bool ParseResilientPolicyFilePath(const base::FilePath& policy_path,
40                                  const base::FilePath& default_policy_path,
41                                  int* index_out) {
42  if (!base::StartsWith(policy_path.value(), default_policy_path.value(),
43                        base::CompareCase::SENSITIVE)) {
44    return false;
45  }
46
47  if (policy_path == default_policy_path) {
48    *index_out = 0;
49    return true;
50  }
51
52  const std::string extension =
53      policy_path.value().substr(default_policy_path.value().size());
54  if (extension.empty() || extension[0] != '.' ||
55      !base::StringToInt(extension.substr(1), index_out) || *index_out <= 0) {
56    return false;
57  }
58
59  return true;
60}
61
62base::FilePath GetResilientPolicyFilePathForIndex(
63    const base::FilePath& default_policy_path,
64    int index) {
65  if (index == 0)
66    return default_policy_path;
67  return base::FilePath(default_policy_path.value() + "." +
68                        std::to_string(index));
69}
70
71}  // namespace policy
72