summaryrefslogtreecommitdiff
path: root/base/files
diff options
context:
space:
mode:
authorLuis Hector Chavez <lhchavez@google.com>2016-07-15 16:23:21 -0700
committerTreehugger Robot <treehugger-gerrit@google.com>2016-07-27 16:41:28 +0000
commit0c4f26a46430b8c503c65f5cae1d2b6876d53e30 (patch)
treefb97dc88b72d681efeb9cfa1b8693a6183180ad9 /base/files
parent0cfccb799ce68cc66d389e6885f8d73f95ee5c4f (diff)
downloadlibchrome-0c4f26a46430b8c503c65f5cae1d2b6876d53e30.tar.gz
libchrome: Uprev the library to r405848 from Chromium
Pulled the latest and greatest version of libchrome from Chromium. The merge was done against r405848 which corresponds to git commit 909e5d3ecab27bb09cc570c1c215d0221bd6fe53 of Jul 15, 2016 Notable changes are: - base::Bind() now explicitly disallows captures in lambdas (which was never allowed in the style guide). - base::ListValue::iterator now exposes std::unique_ptr<base::Value> instead of raw base::Value*. BUG: 29104761 TEST: All tests in libchrome_test pass on dragonboard-eng build Change-Id: I94b285a3be074efa30c4e71ae93c8f2a99fb0b87
Diffstat (limited to 'base/files')
-rw-r--r--base/files/file.h13
-rw-r--r--base/files/file_path.cc10
-rw-r--r--base/files/file_path_watcher_fsevents.cc63
-rw-r--r--base/files/file_path_watcher_fsevents.h10
-rw-r--r--base/files/file_path_watcher_linux.cc2
-rw-r--r--base/files/file_path_watcher_unittest.cc15
-rw-r--r--base/files/file_util.h6
-rw-r--r--base/files/file_util_posix.cc21
-rw-r--r--base/files/important_file_writer_unittest.cc6
-rw-r--r--base/files/scoped_file.cc12
10 files changed, 101 insertions, 57 deletions
diff --git a/base/files/file.h b/base/files/file.h
index 7ab5ca5859..ae2bd1b61b 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -13,7 +13,7 @@
#include "base/files/file_path.h"
#include "base/files/file_tracing.h"
#include "base/files/scoped_file.h"
-#include "base/move.h"
+#include "base/macros.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -29,10 +29,13 @@
namespace base {
#if defined(OS_WIN)
-typedef HANDLE PlatformFile;
+using PlatformFile = HANDLE;
+
+const PlatformFile kInvalidPlatformFile = INVALID_HANDLE_VALUE;
#elif defined(OS_POSIX)
-typedef int PlatformFile;
+using PlatformFile = int;
+const PlatformFile kInvalidPlatformFile = -1;
#if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL)
typedef struct stat stat_wrapper_t;
#else
@@ -51,8 +54,6 @@ typedef struct stat64 stat_wrapper_t;
// to the OS is not considered const, even if there is no apparent change to
// member variables.
class BASE_EXPORT File {
- MOVE_ONLY_TYPE_FOR_CPP_03(File)
-
public:
// FLAG_(OPEN|CREATE).* are mutually exclusive. You should specify exactly one
// of the five (possibly combining with other flags) when opening or creating
@@ -331,6 +332,8 @@ class BASE_EXPORT File {
Error error_details_;
bool created_;
bool async_;
+
+ DISALLOW_COPY_AND_ASSIGN(File);
};
} // namespace base
diff --git a/base/files/file_path.cc b/base/files/file_path.cc
index 4adfa279dc..29f12a80aa 100644
--- a/base/files/file_path.cc
+++ b/base/files/file_path.cc
@@ -539,7 +539,7 @@ bool FilePath::IsAbsolute() const {
bool FilePath::EndsWithSeparator() const {
if (empty())
return false;
- return IsSeparator(path_[path_.size() - 1]);
+ return IsSeparator(path_.back());
}
FilePath FilePath::AsEndingWithSeparator() const {
@@ -695,6 +695,10 @@ bool FilePath::ReadFromPickle(PickleIterator* iter) {
int FilePath::CompareIgnoreCase(StringPieceType string1,
StringPieceType string2) {
+ static decltype(::CharUpperW)* const char_upper_api =
+ reinterpret_cast<decltype(::CharUpperW)*>(
+ ::GetProcAddress(::GetModuleHandle(L"user32.dll"), "CharUpperW"));
+ CHECK(char_upper_api);
// Perform character-wise upper case comparison rather than using the
// fully Unicode-aware CompareString(). For details see:
// http://blogs.msdn.com/michkap/archive/2005/10/17/481600.aspx
@@ -704,9 +708,9 @@ int FilePath::CompareIgnoreCase(StringPieceType string1,
StringPieceType::const_iterator string2end = string2.end();
for ( ; i1 != string1end && i2 != string2end; ++i1, ++i2) {
wchar_t c1 =
- (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i1, 0)));
+ (wchar_t)LOWORD(char_upper_api((LPWSTR)(DWORD_PTR)MAKELONG(*i1, 0)));
wchar_t c2 =
- (wchar_t)LOWORD(::CharUpperW((LPWSTR)(DWORD_PTR)MAKELONG(*i2, 0)));
+ (wchar_t)LOWORD(char_upper_api((LPWSTR)(DWORD_PTR)MAKELONG(*i2, 0)));
if (c1 < c2)
return -1;
if (c1 > c2)
diff --git a/base/files/file_path_watcher_fsevents.cc b/base/files/file_path_watcher_fsevents.cc
index 824e3d8ad6..e9d25080e7 100644
--- a/base/files/file_path_watcher_fsevents.cc
+++ b/base/files/file_path_watcher_fsevents.cc
@@ -4,16 +4,18 @@
#include "base/files/file_path_watcher_fsevents.h"
+#include <dispatch/dispatch.h>
+
#include <list>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
-#include "base/mac/libdispatch_task_runner.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
namespace base {
@@ -23,19 +25,6 @@ namespace {
// The latency parameter passed to FSEventsStreamCreate().
const CFAbsoluteTime kEventLatencySeconds = 0.3;
-class FSEventsTaskRunner : public mac::LibDispatchTaskRunner {
- public:
- FSEventsTaskRunner()
- : mac::LibDispatchTaskRunner("org.chromium.FilePathWatcherFSEvents") {
- }
-
- protected:
- ~FSEventsTaskRunner() override {}
-};
-
-static LazyInstance<FSEventsTaskRunner>::Leaky g_task_runner =
- LAZY_INSTANCE_INITIALIZER;
-
// Resolve any symlinks in the path.
FilePath ResolvePath(const FilePath& path) {
const unsigned kMaxLinksToResolve = 255;
@@ -79,7 +68,12 @@ FilePath ResolvePath(const FilePath& path) {
} // namespace
-FilePathWatcherFSEvents::FilePathWatcherFSEvents() : fsevent_stream_(NULL) {
+FilePathWatcherFSEvents::FilePathWatcherFSEvents()
+ : queue_(dispatch_queue_create(
+ base::StringPrintf(
+ "org.chromium.base.FilePathWatcher.%p", this).c_str(),
+ DISPATCH_QUEUE_SERIAL)),
+ fsevent_stream_(nullptr) {
}
bool FilePathWatcherFSEvents::Watch(const FilePath& path,
@@ -98,9 +92,14 @@ bool FilePathWatcherFSEvents::Watch(const FilePath& path,
callback_ = callback;
FSEventStreamEventId start_event = FSEventsGetCurrentEventId();
- g_task_runner.Get().PostTask(
- FROM_HERE, Bind(&FilePathWatcherFSEvents::StartEventStream, this,
- start_event, path));
+ // The block runtime would implicitly capture the reference, not the object
+ // it's referencing. Copy the path into a local, so that the value is
+ // captured by the block's scope.
+ const FilePath path_copy(path);
+
+ dispatch_async(queue_, ^{
+ StartEventStream(start_event, path_copy);
+ });
return true;
}
@@ -108,10 +107,12 @@ void FilePathWatcherFSEvents::Cancel() {
set_cancelled();
callback_.Reset();
- // Switch to the dispatch queue thread to tear down the event stream.
- g_task_runner.Get().PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::CancelOnMessageLoopThread, this));
+ // Switch to the dispatch queue to tear down the event stream. As the queue
+ // is owned by this object, and this method is called from the destructor,
+ // execute the block synchronously.
+ dispatch_sync(queue_, ^{
+ CancelOnMessageLoopThread();
+ });
}
// static
@@ -124,8 +125,6 @@ void FilePathWatcherFSEvents::FSEventsCallback(
const FSEventStreamEventId event_ids[]) {
FilePathWatcherFSEvents* watcher =
reinterpret_cast<FilePathWatcherFSEvents*>(event_watcher);
- DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
-
bool root_changed = watcher->ResolveTargetPath();
std::vector<FilePath> paths;
FSEventStreamEventId root_change_at = FSEventStreamGetLatestEventId(stream);
@@ -144,10 +143,9 @@ void FilePathWatcherFSEvents::FSEventsCallback(
if (root_changed) {
// Resetting the event stream from within the callback fails (FSEvents spews
// bad file descriptor errors), so post a task to do the reset.
- g_task_runner.Get().PostTask(
- FROM_HERE,
- Bind(&FilePathWatcherFSEvents::UpdateEventStream, watcher,
- root_change_at));
+ dispatch_async(watcher->queue_, ^{
+ watcher->UpdateEventStream(root_change_at);
+ });
}
watcher->OnFilePathsChanged(paths);
@@ -165,7 +163,6 @@ FilePathWatcherFSEvents::~FilePathWatcherFSEvents() {
void FilePathWatcherFSEvents::OnFilePathsChanged(
const std::vector<FilePath>& paths) {
- DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
DCHECK(!resolved_target_.empty());
task_runner()->PostTask(
FROM_HERE, Bind(&FilePathWatcherFSEvents::DispatchEvents, this, paths,
@@ -194,7 +191,6 @@ void FilePathWatcherFSEvents::CancelOnMessageLoopThread() {
// For all other implementations, the "message loop thread" is the IO thread,
// as returned by task_runner(). This implementation, however, needs to
// cancel pending work on the Dispatch Queue thread.
- DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
if (fsevent_stream_) {
DestroyEventStream();
@@ -205,8 +201,6 @@ void FilePathWatcherFSEvents::CancelOnMessageLoopThread() {
void FilePathWatcherFSEvents::UpdateEventStream(
FSEventStreamEventId start_event) {
- DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
-
// It can happen that the watcher gets canceled while tasks that call this
// function are still in flight, so abort if this situation is detected.
if (resolved_target_.empty())
@@ -237,8 +231,7 @@ void FilePathWatcherFSEvents::UpdateEventStream(
start_event,
kEventLatencySeconds,
kFSEventStreamCreateFlagWatchRoot);
- FSEventStreamSetDispatchQueue(fsevent_stream_,
- g_task_runner.Get().GetDispatchQueue());
+ FSEventStreamSetDispatchQueue(fsevent_stream_, queue_);
if (!FSEventStreamStart(fsevent_stream_)) {
task_runner()->PostTask(
@@ -247,7 +240,6 @@ void FilePathWatcherFSEvents::UpdateEventStream(
}
bool FilePathWatcherFSEvents::ResolveTargetPath() {
- DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
FilePath resolved = ResolvePath(target_).StripTrailingSeparators();
bool changed = resolved != resolved_target_;
resolved_target_ = resolved;
@@ -274,7 +266,6 @@ void FilePathWatcherFSEvents::DestroyEventStream() {
void FilePathWatcherFSEvents::StartEventStream(FSEventStreamEventId start_event,
const FilePath& path) {
- DCHECK(g_task_runner.Get().RunsTasksOnCurrentThread());
DCHECK(resolved_target_.empty());
target_ = path;
diff --git a/base/files/file_path_watcher_fsevents.h b/base/files/file_path_watcher_fsevents.h
index 1ebe4636e4..cfbe020b51 100644
--- a/base/files/file_path_watcher_fsevents.h
+++ b/base/files/file_path_watcher_fsevents.h
@@ -12,6 +12,7 @@
#include "base/files/file_path.h"
#include "base/files/file_path_watcher.h"
+#include "base/mac/scoped_dispatch_object.h"
#include "base/macros.h"
namespace base {
@@ -76,16 +77,19 @@ class FilePathWatcherFSEvents : public FilePathWatcher::PlatformDelegate {
// (Only accessed from the message_loop() thread.)
FilePathWatcher::Callback callback_;
+ // The dispatch queue on which the the event stream is scheduled.
+ ScopedDispatchObject<dispatch_queue_t> queue_;
+
// Target path to watch (passed to callback).
- // (Only accessed from the libdispatch thread.)
+ // (Only accessed from the libdispatch queue.)
FilePath target_;
// Target path with all symbolic links resolved.
- // (Only accessed from the libdispatch thread.)
+ // (Only accessed from the libdispatch queue.)
FilePath resolved_target_;
// Backend stream we receive event callbacks from (strong reference).
- // (Only accessed from the libdispatch thread.)
+ // (Only accessed from the libdispatch queue.)
FSEventStreamRef fsevent_stream_;
DISALLOW_COPY_AND_ASSIGN(FilePathWatcherFSEvents);
diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc
index ae293fe86a..87bddd3dea 100644
--- a/base/files/file_path_watcher_linux.cc
+++ b/base/files/file_path_watcher_linux.cc
@@ -677,7 +677,7 @@ bool FilePathWatcherImpl::HasValidWatchVector() const {
if (watches_[i].subdir.empty())
return false;
}
- return watches_[watches_.size() - 1].subdir.empty();
+ return watches_.back().subdir.empty();
}
} // namespace
diff --git a/base/files/file_path_watcher_unittest.cc b/base/files/file_path_watcher_unittest.cc
index c85a50a42c..a40e4858b4 100644
--- a/base/files/file_path_watcher_unittest.cc
+++ b/base/files/file_path_watcher_unittest.cc
@@ -196,7 +196,11 @@ class FilePathWatcherTest : public testing::Test {
bool WaitForEvents() WARN_UNUSED_RESULT {
collector_->Reset();
- loop_.Run();
+ // Make sure we timeout if we don't get notified.
+ loop_.PostDelayedTask(FROM_HERE,
+ MessageLoop::QuitWhenIdleClosure(),
+ TestTimeouts::action_timeout());
+ RunLoop().Run();
return collector_->Success();
}
@@ -215,7 +219,8 @@ bool FilePathWatcherTest::SetupWatch(const FilePath& target,
FilePathWatcher* watcher,
TestDelegateBase* delegate,
bool recursive_watch) {
- base::WaitableEvent completion(false, false);
+ base::WaitableEvent completion(WaitableEvent::ResetPolicy::AUTOMATIC,
+ WaitableEvent::InitialState::NOT_SIGNALED);
bool result;
file_thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(SetupWatchCallback, target, watcher, delegate,
@@ -889,9 +894,9 @@ TEST_F(FilePathWatcherTest, DirAttributesChanged) {
// We should not get notified in this case as it hasn't affected our ability
// to access the file.
ASSERT_TRUE(ChangeFilePermissions(test_dir1, Read, false));
- loop_.PostDelayedTask(FROM_HERE,
- MessageLoop::QuitWhenIdleClosure(),
- TestTimeouts::tiny_timeout());
+ loop_.task_runner()->PostDelayedTask(FROM_HERE,
+ MessageLoop::QuitWhenIdleClosure(),
+ TestTimeouts::tiny_timeout());
ASSERT_FALSE(WaitForEvents());
ASSERT_TRUE(ChangeFilePermissions(test_dir1, Read, true));
diff --git a/base/files/file_util.h b/base/files/file_util.h
index 8fd9fffeb3..420dcaee61 100644
--- a/base/files/file_util.h
+++ b/base/files/file_util.h
@@ -37,6 +37,7 @@
namespace base {
+class Environment;
class Time;
//-----------------------------------------------------------------------------
@@ -199,6 +200,11 @@ BASE_EXPORT bool GetPosixFilePermissions(const FilePath& path, int* mode);
// the permission of a file which the symlink points to.
BASE_EXPORT bool SetPosixFilePermissions(const FilePath& path, int mode);
+// Returns true iff |executable| can be found in any directory specified by the
+// environment variable in |env|.
+BASE_EXPORT bool ExecutableExistsInPath(Environment* env,
+ const FilePath::StringType& executable);
+
#endif // OS_POSIX
// Returns true if the given directory is empty
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 599759a1c6..85a1b41d46 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -22,6 +22,7 @@
#include <time.h>
#include <unistd.h>
+#include "base/environment.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/scoped_file.h"
@@ -30,6 +31,7 @@
#include "base/memory/singleton.h"
#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
@@ -455,6 +457,25 @@ bool SetPosixFilePermissions(const FilePath& path,
return true;
}
+bool ExecutableExistsInPath(Environment* env,
+ const FilePath::StringType& executable) {
+ std::string path;
+ if (!env->GetVar("PATH", &path)) {
+ LOG(ERROR) << "No $PATH variable. Assuming no " << executable << ".";
+ return false;
+ }
+
+ for (const StringPiece& cur_path :
+ SplitStringPiece(path, ":", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) {
+ FilePath file(cur_path);
+ int permissions;
+ if (GetPosixFilePermissions(file.Append(executable), &permissions) &&
+ (permissions & FILE_PERMISSION_EXECUTE_BY_USER))
+ return true;
+ }
+ return false;
+}
+
#if !defined(OS_MACOSX)
// This is implemented in file_util_mac.mm for Mac.
bool GetTempDir(FilePath* path) {
diff --git a/base/files/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc
index ba1d4d3f93..43e051ebcf 100644
--- a/base/files/important_file_writer_unittest.cc
+++ b/base/files/important_file_writer_unittest.cc
@@ -157,7 +157,7 @@ TEST_F(ImportantFileWriterTest, ScheduleWrite) {
ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
TimeDelta::FromMilliseconds(100));
- MessageLoop::current()->Run();
+ RunLoop().Run();
EXPECT_FALSE(writer.HasPendingWrite());
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("foo", GetFileContent(writer.path()));
@@ -173,7 +173,7 @@ TEST_F(ImportantFileWriterTest, DoScheduledWrite) {
ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
TimeDelta::FromMilliseconds(100));
- MessageLoop::current()->Run();
+ RunLoop().Run();
EXPECT_FALSE(writer.HasPendingWrite());
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("foo", GetFileContent(writer.path()));
@@ -190,7 +190,7 @@ TEST_F(ImportantFileWriterTest, BatchingWrites) {
ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, MessageLoop::QuitWhenIdleClosure(),
TimeDelta::FromMilliseconds(100));
- MessageLoop::current()->Run();
+ RunLoop().Run();
ASSERT_TRUE(PathExists(writer.path()));
EXPECT_EQ("baz", GetFileContent(writer.path()));
}
diff --git a/base/files/scoped_file.cc b/base/files/scoped_file.cc
index 8971280776..8ce45b8ba3 100644
--- a/base/files/scoped_file.cc
+++ b/base/files/scoped_file.cc
@@ -8,8 +8,10 @@
#include "build/build_config.h"
#if defined(OS_POSIX)
+#include <errno.h>
#include <unistd.h>
+#include "base/debug/alias.h"
#include "base/posix/eintr_wrapper.h"
#endif
@@ -27,7 +29,15 @@ void ScopedFDCloseTraits::Free(int fd) {
// Chrome relies on being able to "drop" such access.
// It's especially problematic on Linux with the setuid sandbox, where
// a single open directory would bypass the entire security model.
- PCHECK(0 == IGNORE_EINTR(close(fd)));
+ int ret = IGNORE_EINTR(close(fd));
+
+ // TODO(davidben): Remove this once it's been determined whether
+ // https://crbug.com/603354 is caused by EBADF or a network filesystem
+ // returning some other error.
+ int close_errno = errno;
+ base::debug::Alias(&close_errno);
+
+ PCHECK(0 == ret);
}
#endif // OS_POSIX