1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/test_file_util.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string>
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
namespace file_util {
namespace {
// Deny |permission| on the file |path|.
bool DenyFilePermission(const FilePath& path, mode_t permission) {
struct stat stat_buf;
if (stat(path.value().c_str(), &stat_buf) != 0)
return false;
stat_buf.st_mode &= ~permission;
int rv = HANDLE_EINTR(chmod(path.value().c_str(), stat_buf.st_mode));
return rv == 0;
}
} // namespace
bool DieFileDie(const FilePath& file, bool recurse) {
// There is no need to workaround Windows problems on POSIX.
// Just pass-through.
return file_util::Delete(file, recurse);
}
// Mostly a verbatim copy of CopyDirectory
bool CopyRecursiveDirNoCache(const FilePath& source_dir,
const FilePath& dest_dir) {
char top_dir[PATH_MAX];
if (base::strlcpy(top_dir, source_dir.value().c_str(),
arraysize(top_dir)) >= arraysize(top_dir)) {
return false;
}
// This function does not properly handle destinations within the source
FilePath real_to_path = dest_dir;
if (PathExists(real_to_path)) {
if (!AbsolutePath(&real_to_path))
return false;
} else {
real_to_path = real_to_path.DirName();
if (!AbsolutePath(&real_to_path))
return false;
}
if (real_to_path.value().compare(0, source_dir.value().size(),
source_dir.value()) == 0)
return false;
bool success = true;
FileEnumerator::FileType traverse_type =
static_cast<FileEnumerator::FileType>(FileEnumerator::FILES |
FileEnumerator::SHOW_SYM_LINKS | FileEnumerator::DIRECTORIES);
FileEnumerator traversal(source_dir, true, traverse_type);
// dest_dir may not exist yet, start the loop with dest_dir
FileEnumerator::FindInfo info;
FilePath current = source_dir;
if (stat(source_dir.value().c_str(), &info.stat) < 0) {
DLOG(ERROR) << "CopyRecursiveDirNoCache() couldn't stat source directory: "
<< source_dir.value() << " errno = " << errno;
success = false;
}
while (success && !current.empty()) {
// |current| is the source path, including source_dir, so paste
// the suffix after source_dir onto dest_dir to create the target_path.
std::string suffix(¤t.value().c_str()[source_dir.value().size()]);
// Strip the leading '/' (if any).
if (!suffix.empty()) {
DCHECK_EQ('/', suffix[0]);
suffix.erase(0, 1);
}
const FilePath target_path = dest_dir.Append(suffix);
if (S_ISDIR(info.stat.st_mode)) {
if (mkdir(target_path.value().c_str(), info.stat.st_mode & 01777) != 0 &&
errno != EEXIST) {
DLOG(ERROR) << "CopyRecursiveDirNoCache() couldn't create directory: "
<< target_path.value() << " errno = " << errno;
success = false;
}
} else if (S_ISREG(info.stat.st_mode)) {
if (CopyFile(current, target_path)) {
success = EvictFileFromSystemCache(target_path);
DCHECK(success);
} else {
DLOG(ERROR) << "CopyRecursiveDirNoCache() couldn't create file: "
<< target_path.value();
success = false;
}
} else {
DLOG(WARNING) << "CopyRecursiveDirNoCache() skipping non-regular file: "
<< current.value();
}
current = traversal.Next();
traversal.GetFindInfo(&info);
}
return success;
}
#if !defined(OS_LINUX) && !defined(OS_MACOSX)
bool EvictFileFromSystemCache(const FilePath& file) {
// There doesn't seem to be a POSIX way to cool the disk cache.
NOTIMPLEMENTED();
return false;
}
#endif
std::wstring FilePathAsWString(const FilePath& path) {
return UTF8ToWide(path.value());
}
FilePath WStringAsFilePath(const std::wstring& path) {
return FilePath(WideToUTF8(path));
}
bool MakeFileUnreadable(const FilePath& path) {
return DenyFilePermission(path, S_IRUSR | S_IRGRP | S_IROTH);
}
bool MakeFileUnwritable(const FilePath& path) {
return DenyFilePermission(path, S_IWUSR | S_IWGRP | S_IWOTH);
}
} // namespace file_util
|