blob: 5a3b401e6e0e3ad0714cbffcc0a08711556bb173 [file] [log] [blame]
Elliott Hughes38104452015-04-17 13:57:15 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yabin Cui19bec5b2015-09-22 15:52:57 -070017#define TRACE_TAG ADB
Elliott Hughes88b4c852015-04-30 17:32:03 -070018
Elliott Hughes38104452015-04-17 13:57:15 -070019#include "adb_utils.h"
Josh Gaoea7457b2016-08-30 15:39:25 -070020#include "adb_unique_fd.h"
Elliott Hughes38104452015-04-17 13:57:15 -070021
Spencer Low939d0002015-08-01 17:29:23 -070022#include <libgen.h>
Elliott Hughes7cf35752015-04-17 17:03:59 -070023#include <stdlib.h>
Elliott Hughes38104452015-04-17 13:57:15 -070024#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
27
Elliott Hughes88b4c852015-04-30 17:32:03 -070028#include <algorithm>
Josh Gaoe7daf572016-09-21 12:37:10 -070029#include <mutex>
Josh Gao62ff9d42016-08-30 15:23:35 -070030#include <vector>
Elliott Hughes88b4c852015-04-30 17:32:03 -070031
Elliott Hughesf55ead92015-12-04 22:00:26 -080032#include <android-base/logging.h>
David Pursell19d0c232016-04-07 11:25:48 -070033#include <android-base/parseint.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080034#include <android-base/stringprintf.h>
35#include <android-base/strings.h>
Elliott Hughes88b4c852015-04-30 17:32:03 -070036
Josh Gao1eef4782015-11-20 15:37:31 -080037#include "adb.h"
Elliott Hughes88b4c852015-04-30 17:32:03 -070038#include "adb_trace.h"
Elliott Hughesdf5bb432015-04-19 13:17:01 -070039#include "sysdeps.h"
40
Yurii Zubrytskyic0889ab2016-05-25 15:17:10 -070041#ifdef _WIN32
42# ifndef WIN32_LEAN_AND_MEAN
43# define WIN32_LEAN_AND_MEAN
44# endif
45# include "windows.h"
46# include "shlobj.h"
Josh Gao62ff9d42016-08-30 15:23:35 -070047#else
48#include <pwd.h>
Yurii Zubrytskyic0889ab2016-05-25 15:17:10 -070049#endif
50
Spencer Low939d0002015-08-01 17:29:23 -070051
Josh Gao1eef4782015-11-20 15:37:31 -080052#if defined(_WIN32)
53constexpr char kNullFileName[] = "NUL";
54#else
55constexpr char kNullFileName[] = "/dev/null";
56#endif
57
58void close_stdin() {
59 int fd = unix_open(kNullFileName, O_RDONLY);
60 if (fd == -1) {
61 fatal_errno("failed to open %s", kNullFileName);
62 }
63
64 if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
65 fatal_errno("failed to redirect stdin to %s", kNullFileName);
66 }
67 unix_close(fd);
68}
69
Elliott Hughes7cf35752015-04-17 17:03:59 -070070bool getcwd(std::string* s) {
71 char* cwd = getcwd(nullptr, 0);
72 if (cwd != nullptr) *s = cwd;
73 free(cwd);
74 return (cwd != nullptr);
75}
76
Elliott Hughes38104452015-04-17 13:57:15 -070077bool directory_exists(const std::string& path) {
78 struct stat sb;
79 return lstat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode);
80}
81
Elliott Hughes38104452015-04-17 13:57:15 -070082std::string escape_arg(const std::string& s) {
Elliott Hughes48db87f2015-04-17 20:50:11 -070083 std::string result = s;
Elliott Hughes38104452015-04-17 13:57:15 -070084
Elliott Hughesde52ce22015-05-15 12:06:00 -070085 // Escape any ' in the string (before we single-quote the whole thing).
86 // The correct way to do this for the shell is to replace ' with '\'' --- that is,
87 // close the existing single-quoted string, escape a single single-quote, and start
88 // a new single-quoted string. Like the C preprocessor, the shell will concatenate
89 // these pieces into one string.
90 for (size_t i = 0; i < s.size(); ++i) {
91 if (s[i] == '\'') {
92 result.insert(i, "'\\'");
93 i += 2;
94 }
Elliott Hughes38104452015-04-17 13:57:15 -070095 }
Elliott Hughes48db87f2015-04-17 20:50:11 -070096
97 // Prefix and suffix the whole string with '.
98 result.insert(result.begin(), '\'');
99 result.push_back('\'');
Elliott Hughes38104452015-04-17 13:57:15 -0700100 return result;
101}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700102
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700103std::string adb_basename(const std::string& path) {
Josh Gaoe7daf572016-09-21 12:37:10 -0700104 static std::mutex& basename_lock = *new std::mutex();
105
Josh Gaof462e0b2015-11-03 18:52:35 -0800106 // Copy path because basename may modify the string passed in.
107 std::string result(path);
108
109 // Use lock because basename() may write to a process global and return a
110 // pointer to that. Note that this locking strategy only works if all other
Josh Gaoe7daf572016-09-21 12:37:10 -0700111 // callers to basename in the process also grab this same lock.
112 std::lock_guard<std::mutex> lock(basename_lock);
Josh Gaof462e0b2015-11-03 18:52:35 -0800113
114 // Note that if std::string uses copy-on-write strings, &str[0] will cause
115 // the copy to be made, so there is no chance of us accidentally writing to
116 // the storage for 'path'.
117 char* name = basename(&result[0]);
118
119 // In case dirname returned a pointer to a process global, copy that string
120 // before leaving the lock.
121 result.assign(name);
122
Josh Gaof462e0b2015-11-03 18:52:35 -0800123 return result;
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700124}
125
Spencer Low939d0002015-08-01 17:29:23 -0700126std::string adb_dirname(const std::string& path) {
Josh Gaoe7daf572016-09-21 12:37:10 -0700127 static std::mutex& dirname_lock = *new std::mutex();
128
Spencer Low939d0002015-08-01 17:29:23 -0700129 // Copy path because dirname may modify the string passed in.
Josh Gaof462e0b2015-11-03 18:52:35 -0800130 std::string result(path);
Spencer Low939d0002015-08-01 17:29:23 -0700131
132 // Use lock because dirname() may write to a process global and return a
133 // pointer to that. Note that this locking strategy only works if all other
134 // callers to dirname in the process also grab this same lock.
Josh Gaoe7daf572016-09-21 12:37:10 -0700135 std::lock_guard<std::mutex> lock(dirname_lock);
Spencer Low939d0002015-08-01 17:29:23 -0700136
137 // Note that if std::string uses copy-on-write strings, &str[0] will cause
138 // the copy to be made, so there is no chance of us accidentally writing to
139 // the storage for 'path'.
Josh Gaof462e0b2015-11-03 18:52:35 -0800140 char* parent = dirname(&result[0]);
Spencer Low939d0002015-08-01 17:29:23 -0700141
142 // In case dirname returned a pointer to a process global, copy that string
143 // before leaving the lock.
Josh Gaof462e0b2015-11-03 18:52:35 -0800144 result.assign(parent);
Spencer Low939d0002015-08-01 17:29:23 -0700145
Spencer Low939d0002015-08-01 17:29:23 -0700146 return result;
Alex Valléee9163152015-05-06 17:22:25 -0400147}
148
Spencer Low1ec9ceb2016-02-10 15:03:50 -0800149// Given a relative or absolute filepath, create the directory hierarchy
Spencer Low939d0002015-08-01 17:29:23 -0700150// as needed. Returns true if the hierarchy is/was setup.
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700151bool mkdirs(const std::string& path) {
Spencer Low939d0002015-08-01 17:29:23 -0700152 // TODO: all the callers do unlink && mkdirs && adb_creat ---
153 // that's probably the operation we should expose.
154
155 // Implementation Notes:
156 //
157 // Pros:
158 // - Uses dirname, so does not need to deal with OS_PATH_SEPARATOR.
159 // - On Windows, uses mingw dirname which accepts '/' and '\\', drive letters
160 // (C:\foo), UNC paths (\\server\share\dir\dir\file), and Unicode (when
161 // combined with our adb_mkdir() which takes UTF-8).
162 // - Is optimistic wrt thinking that a deep directory hierarchy will exist.
163 // So it does as few stat()s as possible before doing mkdir()s.
164 // Cons:
165 // - Recursive, so it uses stack space relative to number of directory
166 // components.
167
Josh Gao49726bc2016-02-26 13:26:55 -0800168 // If path points to a symlink to a directory, that's fine.
169 struct stat sb;
170 if (stat(path.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) {
Spencer Low939d0002015-08-01 17:29:23 -0700171 return true;
172 }
173
Spencer Low1ec9ceb2016-02-10 15:03:50 -0800174 const std::string parent(adb_dirname(path));
175
Spencer Low939d0002015-08-01 17:29:23 -0700176 // If dirname returned the same path as what we passed in, don't go recursive.
177 // This can happen on Windows when walking up the directory hierarchy and not
178 // finding anything that already exists (unlike POSIX that will eventually
179 // find . or /).
180 if (parent == path) {
181 errno = ENOENT;
182 return false;
183 }
184
Josh Gaofe1a6122015-11-04 14:51:23 -0800185 // Recursively make parent directories of 'path'.
Spencer Low939d0002015-08-01 17:29:23 -0700186 if (!mkdirs(parent)) {
187 return false;
188 }
189
Josh Gaofe1a6122015-11-04 14:51:23 -0800190 // Now that the parent directory hierarchy of 'path' has been ensured,
Spencer Low1ec9ceb2016-02-10 15:03:50 -0800191 // create path itself.
Josh Gaofe1a6122015-11-04 14:51:23 -0800192 if (adb_mkdir(path, 0775) == -1) {
Spencer Low939d0002015-08-01 17:29:23 -0700193 const int saved_errno = errno;
Spencer Low1ec9ceb2016-02-10 15:03:50 -0800194 // If someone else created the directory, that is ok.
195 if (directory_exists(path)) {
Spencer Low939d0002015-08-01 17:29:23 -0700196 return true;
197 }
Spencer Low1ec9ceb2016-02-10 15:03:50 -0800198 // There might be a pre-existing file at 'path', or there might have been some other error.
Spencer Low939d0002015-08-01 17:29:23 -0700199 errno = saved_errno;
200 return false;
201 }
202
203 return true;
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700204}
205
Yabin Cui19bec5b2015-09-22 15:52:57 -0700206std::string dump_hex(const void* data, size_t byte_count) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700207 byte_count = std::min(byte_count, size_t(16));
208
209 const uint8_t* p = reinterpret_cast<const uint8_t*>(data);
210
211 std::string line;
212 for (size_t i = 0; i < byte_count; ++i) {
213 android::base::StringAppendF(&line, "%02x", p[i]);
214 }
215 line.push_back(' ');
216
217 for (size_t i = 0; i < byte_count; ++i) {
Spencer Low28bc2cb2015-11-07 18:51:54 -0800218 int ch = p[i];
219 line.push_back(isprint(ch) ? ch : '.');
Elliott Hughes88b4c852015-04-30 17:32:03 -0700220 }
221
Yabin Cui19bec5b2015-09-22 15:52:57 -0700222 return line;
Elliott Hughes88b4c852015-04-30 17:32:03 -0700223}
Elliott Hughes09ccf1f2015-07-18 12:21:30 -0700224
Elliott Hughesb628cb12015-08-03 10:38:08 -0700225std::string perror_str(const char* msg) {
226 return android::base::StringPrintf("%s: %s", msg, strerror(errno));
227}
Yabin Cui5fc22312015-10-06 15:10:05 -0700228
229#if !defined(_WIN32)
Josh Gaoe7388122016-02-16 17:34:53 -0800230// Windows version provided in sysdeps_win32.cpp
Yabin Cui5fc22312015-10-06 15:10:05 -0700231bool set_file_block_mode(int fd, bool block) {
232 int flags = fcntl(fd, F_GETFL, 0);
233 if (flags == -1) {
234 PLOG(ERROR) << "failed to fcntl(F_GETFL) for fd " << fd;
235 return false;
236 }
237 flags = block ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
238 if (fcntl(fd, F_SETFL, flags) != 0) {
239 PLOG(ERROR) << "failed to fcntl(F_SETFL) for fd " << fd << ", flags " << flags;
240 return false;
241 }
242 return true;
243}
244#endif
David Pursell19d0c232016-04-07 11:25:48 -0700245
246bool forward_targets_are_valid(const std::string& source, const std::string& dest,
247 std::string* error) {
248 if (android::base::StartsWith(source, "tcp:")) {
249 // The source port may be 0 to allow the system to select an open port.
250 int port;
251 if (!android::base::ParseInt(&source[4], &port) || port < 0) {
252 *error = android::base::StringPrintf("Invalid source port: '%s'", &source[4]);
253 return false;
254 }
255 }
256
257 if (android::base::StartsWith(dest, "tcp:")) {
258 // The destination port must be > 0.
259 int port;
260 if (!android::base::ParseInt(&dest[4], &port) || port <= 0) {
261 *error = android::base::StringPrintf("Invalid destination port: '%s'", &dest[4]);
262 return false;
263 }
264 }
265
266 return true;
267}
Yurii Zubrytskyicc3a8952016-05-27 11:07:40 -0700268
Josh Gao62ff9d42016-08-30 15:23:35 -0700269std::string adb_get_homedir_path() {
Yurii Zubrytskyic0889ab2016-05-25 15:17:10 -0700270#ifdef _WIN32
Yurii Zubrytskyic0889ab2016-05-25 15:17:10 -0700271 WCHAR path[MAX_PATH];
272 const HRESULT hr = SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path);
273 if (FAILED(hr)) {
274 D("SHGetFolderPathW failed: %s", android::base::SystemErrorCodeToString(hr).c_str());
275 return {};
276 }
277 std::string home_str;
278 if (!android::base::WideToUTF8(path, &home_str)) {
279 return {};
280 }
281 return home_str;
282#else
283 if (const char* const home = getenv("HOME")) {
284 return home;
285 }
Josh Gao62ff9d42016-08-30 15:23:35 -0700286
287 struct passwd pwent;
288 struct passwd* result;
289 int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
290 std::vector<char> buf(pwent_max);
291 int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
292 if (rc == 0 && result) {
293 return result->pw_dir;
294 }
295
296 LOG(FATAL) << "failed to get user home directory";
Yurii Zubrytskyic0889ab2016-05-25 15:17:10 -0700297 return {};
298#endif
299}
Josh Gao62ff9d42016-08-30 15:23:35 -0700300
301std::string adb_get_android_dir_path() {
302 std::string user_dir = adb_get_homedir_path();
303 std::string android_dir = user_dir + OS_PATH_SEPARATOR + ".android";
304 struct stat buf;
305 if (stat(android_dir.c_str(), &buf) == -1) {
306 if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
307 PLOG(FATAL) << "Cannot mkdir '" << android_dir << "'";
308 }
309 }
310 return android_dir;
311}
Josh Gaoea7457b2016-08-30 15:39:25 -0700312
313void AdbCloser::Close(int fd) {
314 adb_close(fd);
315}