duplicate_tree_detector.cc revision 868fa2fe829687343ffae624259930155e16dbd8
1// Copyright (c) 2011 The Chromium 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
6#include "chrome/installer/util/duplicate_tree_detector.h"
7
8#include "base/file_util.h"
9#include "base/files/file_enumerator.h"
10#include "base/logging.h"
11
12namespace installer {
13
14bool IsIdenticalFileHierarchy(const base::FilePath& src_path,
15                              const base::FilePath& dest_path) {
16  base::PlatformFileInfo src_info;
17  base::PlatformFileInfo dest_info;
18
19  bool is_identical = false;
20  if (file_util::GetFileInfo(src_path, &src_info) &&
21      file_util::GetFileInfo(dest_path, &dest_info)) {
22    // Both paths exist, check the types:
23    if (!src_info.is_directory && !dest_info.is_directory) {
24      // Two files are "identical" if the file sizes are equivalent.
25      is_identical = src_info.size == dest_info.size;
26#ifndef NDEBUG
27      // For Debug builds, also check last modification time (to make sure
28      // version dir DLLs are replaced on over-install even if the tested change
29      // doesn't happen to change a given DLL's size).
30      if (is_identical)
31        is_identical = (src_info.last_modified == dest_info.last_modified);
32#endif
33    } else if (src_info.is_directory && dest_info.is_directory) {
34      // Two directories are "identical" if dest_path contains entries that are
35      // "identical" to all the entries in src_path.
36      is_identical = true;
37
38      base::FileEnumerator path_enum(src_path, false /* not recursive */,
39          base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
40      for (base::FilePath path = path_enum.Next();
41           is_identical && !path.empty();
42           path = path_enum.Next()) {
43        is_identical =
44            IsIdenticalFileHierarchy(path, dest_path.Append(path.BaseName()));
45      }
46    } else {
47      // The two paths are of different types, so they cannot be identical.
48      DCHECK(!is_identical);
49    }
50  }
51
52  return is_identical;
53}
54
55}  // namespace installer
56