diff options
author | gspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-03 17:37:54 +0000 |
---|---|---|
committer | gspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-03 17:37:54 +0000 |
commit | 723571af3c1a86aa14a68bce2511f3dad399287f (patch) | |
tree | c77043d78d5eb7eb1437071561fce7c8ad9b4a5d | |
parent | 0868ee7ae6d7fbb63ab85dfeafa34d724f9a1b45 (diff) | |
download | chromium_src-723571af3c1a86aa14a68bce2511f3dad399287f.zip chromium_src-723571af3c1a86aa14a68bce2511f3dad399287f.tar.gz chromium_src-723571af3c1a86aa14a68bce2511f3dad399287f.tar.bz2 |
Start using file_util symlink code, now that it's available.
In CL http://codereview.chromium.org/5349007
I added some base API for manipulating symlinks (since I needed it for some ChromeOS code and noticed that other places could use it too), and this just starts using that API.
BUG=none
TEST=Ran ui_tests, passed trybots.
Review URL: http://codereview.chromium.org/5286010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68181 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/base_paths_linux.cc | 8 | ||||
-rw-r--r-- | base/command_line.cc | 11 | ||||
-rw-r--r-- | base/file_util_posix.cc | 5 | ||||
-rw-r--r-- | base/process_util_linux.cc | 7 | ||||
-rw-r--r-- | chrome/browser/process_singleton_linux.cc | 97 | ||||
-rw-r--r-- | chrome/common/logging_chrome.cc | 12 |
6 files changed, 59 insertions, 81 deletions
diff --git a/base/base_paths_linux.cc b/base/base_paths_linux.cc index 24f86b4..bdf540c 100644 --- a/base/base_paths_linux.cc +++ b/base/base_paths_linux.cc @@ -37,14 +37,12 @@ bool PathProviderPosix(int key, FilePath* result) { case base::FILE_EXE: case base::FILE_MODULE: { // TODO(evanm): is this correct? #if defined(OS_LINUX) - char bin_dir[PATH_MAX + 1]; - int bin_dir_size = readlink(kSelfExe, bin_dir, PATH_MAX); - if (bin_dir_size < 0 || bin_dir_size > PATH_MAX) { + FilePath bin_dir; + if (!file_util::ReadSymbolicLink(FilePath(kSelfExe), &bin_dir)) { NOTREACHED() << "Unable to resolve " << kSelfExe << "."; return false; } - bin_dir[bin_dir_size] = 0; - *result = FilePath(bin_dir); + *result = bin_dir; return true; #elif defined(OS_FREEBSD) int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; diff --git a/base/command_line.cc b/base/command_line.cc index b335e7c..427bed4 100644 --- a/base/command_line.cc +++ b/base/command_line.cc @@ -19,6 +19,7 @@ #include <algorithm> #include "base/file_path.h" +#include "base/file_util.h" #include "base/logging.h" #include "base/singleton.h" #include "base/string_split.h" @@ -237,13 +238,11 @@ void CommandLine::SetProcTitle() { // show up as "exe" in process listings. Read the symlink /proc/self/exe and // use the path it points at for our process title. Note that this is only for // display purposes and has no TOCTTOU security implications. - char buffer[PATH_MAX]; - // Note: readlink() does not append a null byte to terminate the string. - ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer)); - DCHECK(length <= static_cast<ssize_t>(sizeof(buffer))); - if (length > 0) { + FilePath target; + FilePath self_exe("/proc/self/exe"); + if (file_util::ReadSymbolicLink(self_exe, &target)) { have_argv0 = true; - title.assign(buffer, length); + title = target.value(); // If the binary has since been deleted, Linux appends " (deleted)" to the // symlink target. Remove it, since this is not really part of our name. const std::string kDeletedSuffix = " (deleted)"; diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc index e71051e..92527c8 100644 --- a/base/file_util_posix.cc +++ b/base/file_util_posix.cc @@ -388,11 +388,12 @@ bool ReadSymbolicLink(const FilePath& symlink_path, char buf[PATH_MAX]; ssize_t count = ::readlink(symlink_path.value().c_str(), buf, arraysize(buf)); - if (count <= 0) + if (count <= 0) { + target_path->clear(); return false; + } *target_path = FilePath(FilePath::StringType(buf, count)); - return true; } diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc index 6138c07..4627aa5 100644 --- a/base/process_util_linux.cc +++ b/base/process_util_linux.cc @@ -111,13 +111,12 @@ FilePath GetProcessExecutablePath(ProcessHandle process) { FilePath stat_file("/proc"); stat_file = stat_file.Append(base::IntToString(process)); stat_file = stat_file.Append("exe"); - char exename[2048]; - ssize_t len = readlink(stat_file.value().c_str(), exename, sizeof(exename)); - if (len < 1) { + FilePath exe_name; + if (!file_util::ReadSymbolicLink(stat_file, &exe_name)) { // No such process. Happens frequently in e.g. TerminateAllChromeProcesses return FilePath(); } - return FilePath(std::string(exename, len)); + return exe_name; } ProcessIterator::ProcessIterator(const ProcessFilter* filter) diff --git a/chrome/browser/process_singleton_linux.cc b/chrome/browser/process_singleton_linux.cc index dcf2281..8418ee9 100644 --- a/chrome/browser/process_singleton_linux.cc +++ b/chrome/browser/process_singleton_linux.cc @@ -60,6 +60,7 @@ #include "base/command_line.h" #include "base/eintr_wrapper.h" #include "base/file_path.h" +#include "base/file_util.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/path_service.h" @@ -229,43 +230,29 @@ void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { SetupSockAddr(path, addr); } -// Read a symbolic link, return empty string if given path is not a -// symbol link. This version does not interpret the errno, leaving -// the caller to do so. -bool ReadLinkSilent(const std::string& path, std::string* output) { - char buf[PATH_MAX]; - ssize_t len = readlink(path.c_str(), buf, PATH_MAX); - if (len >= 0) { - output->assign(buf, len); - return true; - } - output->clear(); - return false; -} - // Read a symbolic link, return empty string if given path is not a symbol link. -std::string ReadLink(const std::string& path) { - std::string target; - if (!ReadLinkSilent(path, &target)) { +FilePath ReadLink(const FilePath& path) { + FilePath target; + if (!file_util::ReadSymbolicLink(path, &target)) { // The only errno that should occur is ENOENT. if (errno != 0 && errno != ENOENT) - PLOG(ERROR) << "readlink(" << path << ") failed"; + PLOG(ERROR) << "readlink(" << path.value() << ") failed"; } return target; } // Unlink a path. Return true on success. -bool UnlinkPath(const std::string& path) { - int rv = unlink(path.c_str()); +bool UnlinkPath(const FilePath& path) { + int rv = unlink(path.value().c_str()); if (rv < 0 && errno != ENOENT) - PLOG(ERROR) << "Failed to unlink " << path; + PLOG(ERROR) << "Failed to unlink " << path.value(); return rv == 0; } // Create a symlink. Returns true on success. -bool SymlinkPath(const std::string& target, const std::string& path) { - if (symlink(target.c_str(), path.c_str()) < 0) { +bool SymlinkPath(const FilePath& target, const FilePath& path) { + if (!file_util::CreateSymbolicLink(target, path)) { // Double check the value in case symlink suceeded but we got an incorrect // failure due to NFS packet loss & retry. int saved_errno = errno; @@ -273,7 +260,7 @@ bool SymlinkPath(const std::string& target, const std::string& path) { // If we failed to create the lock, most likely another instance won the // startup race. errno = saved_errno; - PLOG(ERROR) << "Failed to create " << path; + PLOG(ERROR) << "Failed to create " << path.value(); return false; } } @@ -282,10 +269,10 @@ bool SymlinkPath(const std::string& target, const std::string& path) { // Extract the hostname and pid from the lock symlink. // Returns true if the lock existed. -bool ParseLockPath(const std::string& path, +bool ParseLockPath(const FilePath& path, std::string* hostname, int* pid) { - std::string real_path = ReadLink(path); + std::string real_path = ReadLink(path).value(); if (real_path.empty()) return false; @@ -350,13 +337,13 @@ bool IsSameChromeInstance(pid_t pid) { // If the process is part of the same chrome instance, unlink the lock file and // return true without killing it. // If the process is on a different host, return false. -bool KillProcessByLockPath(const std::string& path) { +bool KillProcessByLockPath(const FilePath& path) { std::string hostname; int pid; ParseLockPath(path, &hostname, &pid); if (!hostname.empty() && hostname != net::GetHostName()) { - DisplayProfileInUseError(path, hostname, pid); + DisplayProfileInUseError(path.value(), hostname, pid); return false; } UnlinkPath(path); @@ -374,7 +361,7 @@ bool KillProcessByLockPath(const std::string& path) { return true; } - LOG(ERROR) << "Failed to extract pid from path: " << path; + LOG(ERROR) << "Failed to extract pid from path: " << path.value(); return true; } @@ -402,21 +389,21 @@ std::string GenerateCookie() { return base::Uint64ToString(base::RandUint64()); } -bool CheckCookie(const FilePath& path, const std::string& cookie) { - return (cookie == ReadLink(path.value())); +bool CheckCookie(const FilePath& path, const FilePath& cookie) { + return (cookie == ReadLink(path)); } bool ConnectSocket(ScopedSocket* socket, const FilePath& socket_path, const FilePath& cookie_path) { - std::string socket_target; - if (ReadLinkSilent(socket_path.value(), &socket_target)) { + FilePath socket_target; + if (file_util::ReadSymbolicLink(socket_path, &socket_target)) { // It's a symlink. Read the cookie. - std::string cookie = ReadLink(cookie_path.value()); + FilePath cookie = ReadLink(cookie_path); if (cookie.empty()) return false; - FilePath remote_cookie = FilePath(socket_target).DirName(). - Append(chrome::kSingletonCookieFilename); + FilePath remote_cookie = socket_target.DirName(). + Append(chrome::kSingletonCookieFilename); // Verify the cookie before connecting. if (!CheckCookie(remote_cookie, cookie)) return false; @@ -794,14 +781,14 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( std::string hostname; int pid; - if (!ParseLockPath(lock_path_.value(), &hostname, &pid)) { + if (!ParseLockPath(lock_path_, &hostname, &pid)) { // No lockfile exists. return PROCESS_NONE; } if (hostname.empty()) { // Invalid lockfile. - UnlinkPath(lock_path_.value()); + UnlinkPath(lock_path_); return PROCESS_NONE; } @@ -813,20 +800,20 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( if (!IsChromeProcess(pid)) { // Orphaned lockfile (no process with pid, or non-chrome process.) - UnlinkPath(lock_path_.value()); + UnlinkPath(lock_path_); return PROCESS_NONE; } if (IsSameChromeInstance(pid)) { // Orphaned lockfile (pid is part of same chrome instance we are, even // though we haven't tried to create a lockfile yet). - UnlinkPath(lock_path_.value()); + UnlinkPath(lock_path_); return PROCESS_NONE; } if (retries == timeout_seconds) { // Retries failed. Kill the unresponsive chrome process and continue. - if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value())) + if (!kill_unresponsive || !KillProcessByLockPath(lock_path_)) return PROFILE_IN_USE; return PROCESS_NONE; } @@ -857,7 +844,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( // Send the message if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { // Try to kill the other process, because it might have been dead. - if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value())) + if (!kill_unresponsive || !KillProcessByLockPath(lock_path_)) return PROFILE_IN_USE; return PROCESS_NONE; } @@ -873,7 +860,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( // Failed to read ACK, the other process might have been frozen. if (len <= 0) { - if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value())) + if (!kill_unresponsive || !KillProcessByLockPath(lock_path_)) return PROFILE_IN_USE; return PROCESS_NONE; } @@ -928,15 +915,15 @@ bool ProcessSingleton::Create() { // The symlink lock is pointed to the hostname and process id, so other // processes can find it out. - std::string symlink_content = StringPrintf( + FilePath symlink_content(StringPrintf( "%s%c%u", net::GetHostName().c_str(), kLockDelimiter, - base::GetCurrentProcId()); + base::GetCurrentProcId())); // Create symbol link before binding the socket, to ensure only one instance // can have the socket open. - if (!SymlinkPath(symlink_content, lock_path_.value())) { + if (!SymlinkPath(symlink_content, lock_path_)) { // If we failed to create the lock, most likely another instance won the // startup race. return false; @@ -952,14 +939,14 @@ bool ProcessSingleton::Create() { // Setup the socket symlink and the two cookies. FilePath socket_target_path = socket_dir_.path().Append(chrome::kSingletonSocketFilename); - std::string cookie = GenerateCookie(); + FilePath cookie(GenerateCookie()); FilePath remote_cookie_path = socket_dir_.path().Append(chrome::kSingletonCookieFilename); - UnlinkPath(socket_path_.value()); - UnlinkPath(cookie_path_.value()); - if (!SymlinkPath(socket_target_path.value(), socket_path_.value()) || - !SymlinkPath(cookie, cookie_path_.value()) || - !SymlinkPath(cookie, remote_cookie_path.value())) { + UnlinkPath(socket_path_); + UnlinkPath(cookie_path_); + if (!SymlinkPath(socket_target_path, socket_path_) || + !SymlinkPath(cookie, cookie_path_) || + !SymlinkPath(cookie, remote_cookie_path)) { // We've already locked things, so we can't have lost the startup race, // but something doesn't like us. LOG(ERROR) << "Failed to create symlinks."; @@ -992,7 +979,7 @@ bool ProcessSingleton::Create() { } void ProcessSingleton::Cleanup() { - UnlinkPath(socket_path_.value()); - UnlinkPath(cookie_path_.value()); - UnlinkPath(lock_path_.value()); + UnlinkPath(socket_path_); + UnlinkPath(cookie_path_); + UnlinkPath(lock_path_); } diff --git a/chrome/common/logging_chrome.cc b/chrome/common/logging_chrome.cc index 196c581..e5d442c 100644 --- a/chrome/common/logging_chrome.cc +++ b/chrome/common/logging_chrome.cc @@ -164,23 +164,17 @@ FilePath SetUpSymlinkIfNeeded(const FilePath& symlink_path, bool new_log) { target_path = GenerateTimestampedName(symlink_path, base::Time::Now()); // We don't care if the unlink fails; we're going to continue anyway. - if (unlink(symlink_path.value().c_str()) == -1) { + if (::unlink(symlink_path.value().c_str()) == -1) { if (symlink_exists) // only warn if we might expect it to succeed. PLOG(WARNING) << "Unable to unlink " << symlink_path.value(); } - if (symlink(target_path.value().c_str(), - symlink_path.value().c_str()) == -1) { + if (!file_util::CreateSymbolicLink(target_path, symlink_path)) { PLOG(ERROR) << "Unable to create symlink " << symlink_path.value() << " pointing at " << target_path.value(); } } else { - char buf[PATH_MAX]; - ssize_t count = readlink(symlink_path.value().c_str(), buf, arraysize(buf)); - if (count > 0) { - target_path = FilePath(FilePath::StringType(buf, count)); - } else { + if (!file_util::ReadSymbolicLink(symlink_path, &target_path)) PLOG(ERROR) << "Unable to read symlink " << symlink_path.value(); - } } return target_path; } |