OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/linux_util.h" | 5 #include "base/linux_util.h" |
6 | 6 |
| 7 #include <dirent.h> |
| 8 #include <errno.h> |
7 #include <stdlib.h> | 9 #include <stdlib.h> |
| 10 #include <sys/stat.h> |
| 11 #include <sys/types.h> |
| 12 #include <unistd.h> |
8 | 13 |
9 #include <vector> | 14 #include <vector> |
10 | 15 |
11 #include "base/command_line.h" | 16 #include "base/command_line.h" |
12 #include "base/lock.h" | 17 #include "base/lock.h" |
13 #include "base/process_util.h" | 18 #include "base/process_util.h" |
14 #include "base/singleton.h" | 19 #include "base/singleton.h" |
15 #include "base/string_util.h" | 20 #include "base/string_util.h" |
16 | 21 |
17 namespace { | 22 namespace { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 DCHECK(state_ == STATE_CHECK_STARTED); | 90 DCHECK(state_ == STATE_CHECK_STARTED); |
86 state_ = STATE_CHECK_FINISHED; | 91 state_ = STATE_CHECK_FINISHED; |
87 } | 92 } |
88 | 93 |
89 private: | 94 private: |
90 Lock lock_; | 95 Lock lock_; |
91 LinuxDistroState state_; | 96 LinuxDistroState state_; |
92 }; | 97 }; |
93 #endif // if defined(OS_LINUX) | 98 #endif // if defined(OS_LINUX) |
94 | 99 |
| 100 // expected prefix of the target of the /proc/self/fd/%d link for a socket |
| 101 static const char kSocketLinkPrefix[] = "socket:["; |
| 102 |
| 103 // Parse a symlink in /proc/pid/fd/$x and return the inode number of the |
| 104 // socket. |
| 105 // inode_out: (output) set to the inode number on success |
| 106 // path: e.g. /proc/1234/fd/5 (must be a UNIX domain socket descriptor) |
| 107 // log: if true, log messages about failure details |
| 108 bool ProcPathGetInode(ino_t* inode_out, const char* path, bool log = false) { |
| 109 DCHECK(inode_out); |
| 110 DCHECK(path); |
| 111 |
| 112 char buf[256]; |
| 113 const ssize_t n = readlink(path, buf, sizeof(buf) - 1); |
| 114 if (n == -1) { |
| 115 if (log) { |
| 116 LOG(WARNING) << "Failed to read the inode number for a socket from /proc" |
| 117 "(" << errno << ")"; |
| 118 } |
| 119 return false; |
| 120 } |
| 121 buf[n] = 0; |
| 122 |
| 123 if (memcmp(kSocketLinkPrefix, buf, sizeof(kSocketLinkPrefix) - 1)) { |
| 124 if (log) { |
| 125 LOG(WARNING) << "The descriptor passed from the crashing process wasn't a" |
| 126 " UNIX domain socket."; |
| 127 } |
| 128 return false; |
| 129 } |
| 130 |
| 131 char *endptr; |
| 132 const unsigned long long int inode_ul = |
| 133 strtoull(buf + sizeof(kSocketLinkPrefix) - 1, &endptr, 10); |
| 134 if (*endptr != ']') |
| 135 return false; |
| 136 |
| 137 if (inode_ul == ULLONG_MAX) { |
| 138 if (log) { |
| 139 LOG(WARNING) << "Failed to parse a socket's inode number: the number was " |
| 140 "too large. Please report this bug: " << buf; |
| 141 } |
| 142 return false; |
| 143 } |
| 144 |
| 145 *inode_out = inode_ul; |
| 146 return true; |
| 147 } |
| 148 |
95 } // anonymous namespace | 149 } // anonymous namespace |
96 | 150 |
97 namespace base { | 151 namespace base { |
98 | 152 |
99 uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride) { | 153 uint8_t* BGRAToRGBA(const uint8_t* pixels, int width, int height, int stride) { |
100 if (stride == 0) | 154 if (stride == 0) |
101 stride = width * 4; | 155 stride = width * 4; |
102 | 156 |
103 uint8_t* new_pixels = static_cast<uint8_t*>(malloc(height * stride)); | 157 uint8_t* new_pixels = static_cast<uint8_t*>(malloc(height * stride)); |
104 | 158 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 case DESKTOP_ENVIRONMENT_KDE4: | 256 case DESKTOP_ENVIRONMENT_KDE4: |
203 return "KDE4"; | 257 return "KDE4"; |
204 } | 258 } |
205 return NULL; | 259 return NULL; |
206 } | 260 } |
207 | 261 |
208 const char* GetDesktopEnvironmentName(EnvironmentVariableGetter* env) { | 262 const char* GetDesktopEnvironmentName(EnvironmentVariableGetter* env) { |
209 return GetDesktopEnvironmentName(GetDesktopEnvironment(env)); | 263 return GetDesktopEnvironmentName(GetDesktopEnvironment(env)); |
210 } | 264 } |
211 | 265 |
| 266 bool FileDescriptorGetInode(ino_t* inode_out, int fd) { |
| 267 DCHECK(inode_out); |
| 268 |
| 269 struct stat buf; |
| 270 if (fstat(fd, &buf) < 0) |
| 271 return false; |
| 272 |
| 273 if (!S_ISSOCK(buf.st_mode)) |
| 274 return false; |
| 275 |
| 276 *inode_out = buf.st_ino; |
| 277 return true; |
| 278 } |
| 279 |
| 280 bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) { |
| 281 DCHECK(pid_out); |
| 282 bool already_found = false; |
| 283 |
| 284 DIR* proc = opendir("/proc"); |
| 285 if (!proc) { |
| 286 LOG(WARNING) << "Cannot open /proc"; |
| 287 return false; |
| 288 } |
| 289 |
| 290 std::vector<pid_t> pids; |
| 291 |
| 292 struct dirent* dent; |
| 293 while ((dent = readdir(proc))) { |
| 294 char *endptr; |
| 295 const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10); |
| 296 if (pid_ul == ULONG_MAX || *endptr) |
| 297 continue; |
| 298 pids.push_back(pid_ul); |
| 299 } |
| 300 closedir(proc); |
| 301 |
| 302 for (std::vector<pid_t>::const_iterator |
| 303 i = pids.begin(); i != pids.end(); ++i) { |
| 304 const pid_t current_pid = *i; |
| 305 char buf[256]; |
| 306 snprintf(buf, sizeof(buf), "/proc/%d/fd", current_pid); |
| 307 DIR* fd = opendir(buf); |
| 308 if (!fd) |
| 309 continue; |
| 310 |
| 311 while ((dent = readdir(fd))) { |
| 312 if (snprintf(buf, sizeof(buf), "/proc/%d/fd/%s", current_pid, |
| 313 dent->d_name) >= static_cast<int>(sizeof(buf))) { |
| 314 continue; |
| 315 } |
| 316 |
| 317 ino_t fd_inode; |
| 318 if (ProcPathGetInode(&fd_inode, buf)) { |
| 319 if (fd_inode == socket_inode) { |
| 320 if (already_found) { |
| 321 closedir(fd); |
| 322 return false; |
| 323 } |
| 324 |
| 325 already_found = true; |
| 326 *pid_out = current_pid; |
| 327 break; |
| 328 } |
| 329 } |
| 330 } |
| 331 |
| 332 closedir(fd); |
| 333 } |
| 334 |
| 335 return already_found; |
| 336 } |
| 337 |
212 } // namespace base | 338 } // namespace base |
OLD | NEW |