blob: 14c26cb60632847f33bc2b9be9e81007ce3d9e87 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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 Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG SYNC
Dan Albert33134262015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20#include "file_sync_service.h"
21
Dan Albert76649012015-02-24 15:51:19 -080022#include <dirent.h>
23#include <errno.h>
Elliott Hughes32c60b42016-06-07 17:18:25 -070024#include <linux/xattr.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <stdio.h>
Dan Albert76649012015-02-24 15:51:19 -080026#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080027#include <string.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028#include <sys/stat.h>
29#include <sys/types.h>
Elliott Hughes32c60b42016-06-07 17:18:25 -070030#include <sys/xattr.h>
Liang Cheng20d33f42014-01-02 18:27:51 -080031#include <unistd.h>
Dan Albert76649012015-02-24 15:51:19 -080032#include <utime.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080034#include "adb.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080035#include "adb_io.h"
Josh Gao45b6fc82015-11-04 14:51:23 -080036#include "adb_utils.h"
Dan Albert76649012015-02-24 15:51:19 -080037#include "private/android_filesystem_config.h"
Rubin Xud61a25c2016-01-11 10:23:47 +000038#include "security_log_tags.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039
Elliott Hughes4f713192015-12-04 22:00:26 -080040#include <android-base/stringprintf.h>
41#include <android-base/strings.h>
Elliott Hughes32c60b42016-06-07 17:18:25 -070042#include <log/log.h>
43#include <selinux/android.h>
Elliott Hughes5c742702015-07-30 17:42:01 -070044
45static bool should_use_fs_config(const std::string& path) {
Elliott Hughesec7a6672015-03-16 21:58:32 +000046 // TODO: use fs_config to configure permissions on /data.
Elliott Hughes5c742702015-07-30 17:42:01 -070047 return android::base::StartsWith(path, "/system/") ||
48 android::base::StartsWith(path, "/vendor/") ||
49 android::base::StartsWith(path, "/oem/");
Daniel Rosenberg686bce62014-06-30 20:29:40 -070050}
51
Elliott Hughes32c60b42016-06-07 17:18:25 -070052static bool update_capabilities(const char* path, uint64_t capabilities) {
53 if (capabilities == 0) {
54 // Ensure we clean up in case the capabilities weren't 0 in the past.
55 removexattr(path, XATTR_NAME_CAPS);
56 return true;
57 }
58
59 vfs_cap_data cap_data = {};
60 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
61 cap_data.data[0].permitted = (capabilities & 0xffffffff);
62 cap_data.data[0].inheritable = 0;
63 cap_data.data[1].permitted = (capabilities >> 32);
64 cap_data.data[1].inheritable = 0;
65 return setxattr(path, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) != -1;
66}
67
Alex Vallée47d67c92015-05-06 16:26:00 -040068static bool secure_mkdirs(const std::string& path) {
Nick Kralevich72917832014-01-17 16:16:42 -080069 uid_t uid = -1;
70 gid_t gid = -1;
Liang Cheng20d33f42014-01-02 18:27:51 -080071 unsigned int mode = 0775;
Elliott Hughes32c60b42016-06-07 17:18:25 -070072 uint64_t capabilities = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080073
Alex Vallée47d67c92015-05-06 16:26:00 -040074 if (path[0] != '/') return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080075
Elliott Hughes5c742702015-07-30 17:42:01 -070076 std::vector<std::string> path_components = android::base::Split(path, "/");
Elliott Hughes5c742702015-07-30 17:42:01 -070077 std::string partial_path;
Elliott Hughes65fe2512015-10-07 15:59:35 -070078 for (const auto& path_component : path_components) {
Elliott Hughes5c742702015-07-30 17:42:01 -070079 if (partial_path.back() != OS_PATH_SEPARATOR) partial_path += OS_PATH_SEPARATOR;
80 partial_path += path_component;
81
82 if (should_use_fs_config(partial_path)) {
Elliott Hughes32c60b42016-06-07 17:18:25 -070083 fs_config(partial_path.c_str(), 1, nullptr, &uid, &gid, &mode, &capabilities);
Liang Cheng20d33f42014-01-02 18:27:51 -080084 }
Elliott Hughes5c742702015-07-30 17:42:01 -070085 if (adb_mkdir(partial_path.c_str(), mode) == -1) {
Alex Vallée47d67c92015-05-06 16:26:00 -040086 if (errno != EEXIST) {
87 return false;
Liang Cheng20d33f42014-01-02 18:27:51 -080088 }
Alex Vallée47d67c92015-05-06 16:26:00 -040089 } else {
Elliott Hughes32c60b42016-06-07 17:18:25 -070090 if (chown(partial_path.c_str(), uid, gid) == -1) return false;
91
Elliott Hughes38344402015-08-25 16:33:50 -070092 // Not all filesystems support setting SELinux labels. http://b/23530370.
Elliott Hughes5c742702015-07-30 17:42:01 -070093 selinux_android_restorecon(partial_path.c_str(), 0);
Elliott Hughes32c60b42016-06-07 17:18:25 -070094
95 if (!update_capabilities(partial_path.c_str(), capabilities)) return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080097 }
Alex Vallée47d67c92015-05-06 16:26:00 -040098 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080099}
100
Elliott Hughesaa245492015-08-03 10:38:08 -0700101static bool do_stat(int s, const char* path) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 syncmsg msg;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 msg.stat.id = ID_STAT;
104
Elliott Hughes32c60b42016-06-07 17:18:25 -0700105 struct stat st = {};
Elliott Hughesaa245492015-08-03 10:38:08 -0700106 // TODO: add a way to report that the stat failed!
107 lstat(path, &st);
Elliott Hughesf4465202015-08-24 14:27:03 -0700108 msg.stat.mode = st.st_mode;
109 msg.stat.size = st.st_size;
110 msg.stat.time = st.st_mtime;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800111
Elliott Hughesaa245492015-08-03 10:38:08 -0700112 return WriteFdExactly(s, &msg.stat, sizeof(msg.stat));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113}
114
Elliott Hughesaa245492015-08-03 10:38:08 -0700115static bool do_list(int s, const char* path) {
116 dirent* de;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800117
Elliott Hughes5c742702015-07-30 17:42:01 -0700118 syncmsg msg;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119 msg.dent.id = ID_DENT;
120
Elliott Hughes5c742702015-07-30 17:42:01 -0700121 std::unique_ptr<DIR, int(*)(DIR*)> d(opendir(path), closedir);
122 if (!d) goto done;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800123
Elliott Hughes5c742702015-07-30 17:42:01 -0700124 while ((de = readdir(d.get()))) {
Elliott Hughesaa245492015-08-03 10:38:08 -0700125 std::string filename(android::base::StringPrintf("%s/%s", path, de->d_name));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126
Elliott Hughesaa245492015-08-03 10:38:08 -0700127 struct stat st;
128 if (lstat(filename.c_str(), &st) == 0) {
129 size_t d_name_length = strlen(de->d_name);
Elliott Hughesf4465202015-08-24 14:27:03 -0700130 msg.dent.mode = st.st_mode;
131 msg.dent.size = st.st_size;
132 msg.dent.time = st.st_mtime;
133 msg.dent.namelen = d_name_length;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800134
Elliott Hughesaa245492015-08-03 10:38:08 -0700135 if (!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
136 !WriteFdExactly(s, de->d_name, d_name_length)) {
137 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800138 }
139 }
140 }
141
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800142done:
143 msg.dent.id = ID_DONE;
144 msg.dent.mode = 0;
145 msg.dent.size = 0;
146 msg.dent.time = 0;
147 msg.dent.namelen = 0;
Elliott Hughesaa245492015-08-03 10:38:08 -0700148 return WriteFdExactly(s, &msg.dent, sizeof(msg.dent));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800149}
150
Josh Gao6ad06b92016-01-28 16:21:12 -0800151// Make sure that SendFail from adb_io.cpp isn't accidentally used in this file.
152#pragma GCC poison SendFail
153
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700154static bool SendSyncFail(int fd, const std::string& reason) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700155 D("sync: failure: %s", reason.c_str());
Elliott Hughesaa245492015-08-03 10:38:08 -0700156
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157 syncmsg msg;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800158 msg.data.id = ID_FAIL;
Elliott Hughesf4465202015-08-24 14:27:03 -0700159 msg.data.size = reason.size();
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700160 return WriteFdExactly(fd, &msg.data, sizeof(msg.data)) && WriteFdExactly(fd, reason);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800161}
162
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700163static bool SendSyncFailErrno(int fd, const std::string& reason) {
164 return SendSyncFail(fd, android::base::StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165}
166
Elliott Hughes32c60b42016-06-07 17:18:25 -0700167static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, uint64_t capabilities,
168 mode_t mode, std::vector<char>& buffer, bool do_unlink) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 syncmsg msg;
170 unsigned int timestamp = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800171
Rubin Xud61a25c2016-01-11 10:23:47 +0000172 __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path);
173
Elliott Hughesaa245492015-08-03 10:38:08 -0700174 int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700175 if (fd < 0 && errno == ENOENT) {
Josh Gao45b6fc82015-11-04 14:51:23 -0800176 if (!secure_mkdirs(adb_dirname(path))) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700177 SendSyncFailErrno(s, "secure_mkdirs failed");
178 goto fail;
Liang Cheng20d33f42014-01-02 18:27:51 -0800179 }
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700180 fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800181 }
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700182 if (fd < 0 && errno == EEXIST) {
Nick Kralevichfe8d7f42014-07-18 20:57:35 -0700183 fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800184 }
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700185 if (fd < 0) {
186 SendSyncFailErrno(s, "couldn't create file");
187 goto fail;
Liang Cheng20d33f42014-01-02 18:27:51 -0800188 } else {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700189 if (fchown(fd, uid, gid) == -1) {
190 SendSyncFailErrno(s, "fchown failed");
191 goto fail;
Liang Cheng20d33f42014-01-02 18:27:51 -0800192 }
Nick Kralevich72917832014-01-17 16:16:42 -0800193
Elliott Hughes38344402015-08-25 16:33:50 -0700194 // Not all filesystems support setting SELinux labels. http://b/23530370.
195 selinux_android_restorecon(path, 0);
Elliott Hughes0adc0972015-08-25 13:14:07 -0700196
197 // fchown clears the setuid bit - restore it if present.
198 // Ignore the result of calling fchmod. It's not supported
Elliott Hughes32c60b42016-06-07 17:18:25 -0700199 // by all filesystems, so we don't check for success. b/12441485
Nick Kralevich72917832014-01-17 16:16:42 -0800200 fchmod(fd, mode);
Elliott Hughes32c60b42016-06-07 17:18:25 -0700201
202 if (!update_capabilities(path, capabilities)) {
203 SendSyncFailErrno(s, "update_capabilities failed");
204 goto fail;
205 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206 }
207
Elliott Hughesaa245492015-08-03 10:38:08 -0700208 while (true) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700209 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700211 if (msg.data.id != ID_DATA) {
212 if (msg.data.id == ID_DONE) {
Elliott Hughesf4465202015-08-24 14:27:03 -0700213 timestamp = msg.data.size;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800214 break;
215 }
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700216 SendSyncFail(s, "invalid data message");
Josh Gao20a96c72016-02-19 14:33:14 -0800217 goto abort;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218 }
Josh Gao20a96c72016-02-19 14:33:14 -0800219
220 if (msg.data.size > buffer.size()) { // TODO: resize buffer?
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700221 SendSyncFail(s, "oversize data message");
Josh Gao20a96c72016-02-19 14:33:14 -0800222 goto abort;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800223 }
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700224
Josh Gao20a96c72016-02-19 14:33:14 -0800225 if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800226
Josh Gao20a96c72016-02-19 14:33:14 -0800227 if (!WriteFdExactly(fd, &buffer[0], msg.data.size)) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700228 SendSyncFailErrno(s, "write failed");
229 goto fail;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800230 }
231 }
232
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700233 adb_close(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700235 utimbuf u;
236 u.actime = timestamp;
237 u.modtime = timestamp;
238 utime(path, &u);
239
240 msg.status.id = ID_OKAY;
241 msg.status.msglen = 0;
242 return WriteFdExactly(s, &msg.status, sizeof(msg.status));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800243
244fail:
Josh Gao20a96c72016-02-19 14:33:14 -0800245 // If there's a problem on the device, we'll send an ID_FAIL message and
246 // close the socket. Unfortunately the kernel will sometimes throw that
247 // data away if the other end keeps writing without reading (which is
248 // the case with old versions of adb). To maintain compatibility, keep
249 // reading and throwing away ID_DATA packets until the other side notices
250 // that we've reported an error.
251 while (true) {
252 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
253
254 if (msg.data.id == ID_DONE) {
255 goto abort;
256 } else if (msg.data.id != ID_DATA) {
257 char id[5];
258 memcpy(id, &msg.data.id, sizeof(msg.data.id));
259 id[4] = '\0';
260 D("handle_send_fail received unexpected id '%s' during failure", id);
261 goto abort;
262 }
263
264 if (msg.data.size > buffer.size()) {
265 D("handle_send_fail received oversized packet of length '%u' during failure",
266 msg.data.size);
267 goto abort;
268 }
269
270 if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort;
271 }
272
273abort:
Elliott Hughesaa245492015-08-03 10:38:08 -0700274 if (fd >= 0) adb_close(fd);
JP Abgrall55b6c842014-03-07 17:31:25 -0800275 if (do_unlink) adb_unlink(path);
Elliott Hughesaa245492015-08-03 10:38:08 -0700276 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277}
278
Elliott Hughes0a049b12015-01-12 14:26:36 -0800279#if defined(_WIN32)
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700280extern bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) __attribute__((error("no symlinks on Windows")));
Elliott Hughes0a049b12015-01-12 14:26:36 -0800281#else
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700282static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800283 syncmsg msg;
284 unsigned int len;
285 int ret;
286
Elliott Hughesaa245492015-08-03 10:38:08 -0700287 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288
Elliott Hughesaa245492015-08-03 10:38:08 -0700289 if (msg.data.id != ID_DATA) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700290 SendSyncFail(s, "invalid data message: expected ID_DATA");
Elliott Hughesaa245492015-08-03 10:38:08 -0700291 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 }
293
Elliott Hughesf4465202015-08-24 14:27:03 -0700294 len = msg.data.size;
Elliott Hughesaa245492015-08-03 10:38:08 -0700295 if (len > buffer.size()) { // TODO: resize buffer?
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700296 SendSyncFail(s, "oversize data message");
Elliott Hughesaa245492015-08-03 10:38:08 -0700297 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800298 }
Elliott Hughesaa245492015-08-03 10:38:08 -0700299 if (!ReadFdExactly(s, &buffer[0], len)) return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700301 ret = symlink(&buffer[0], path.c_str());
Elliott Hughesaa245492015-08-03 10:38:08 -0700302 if (ret && errno == ENOENT) {
Josh Gao45b6fc82015-11-04 14:51:23 -0800303 if (!secure_mkdirs(adb_dirname(path))) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700304 SendSyncFailErrno(s, "secure_mkdirs failed");
Elliott Hughesaa245492015-08-03 10:38:08 -0700305 return false;
Liang Cheng20d33f42014-01-02 18:27:51 -0800306 }
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700307 ret = symlink(&buffer[0], path.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800308 }
Elliott Hughesaa245492015-08-03 10:38:08 -0700309 if (ret) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700310 SendSyncFailErrno(s, "symlink failed");
Elliott Hughesaa245492015-08-03 10:38:08 -0700311 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800312 }
313
Elliott Hughesaa245492015-08-03 10:38:08 -0700314 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315
Elliott Hughesaa245492015-08-03 10:38:08 -0700316 if (msg.data.id == ID_DONE) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800317 msg.status.id = ID_OKAY;
318 msg.status.msglen = 0;
Elliott Hughesaa245492015-08-03 10:38:08 -0700319 if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800320 } else {
Josh Gao6ad06b92016-01-28 16:21:12 -0800321 SendSyncFail(s, "invalid data message: expected ID_DONE");
Elliott Hughesaa245492015-08-03 10:38:08 -0700322 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800323 }
324
Elliott Hughesaa245492015-08-03 10:38:08 -0700325 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800326}
Elliott Hughes0a049b12015-01-12 14:26:36 -0800327#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800328
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700329static bool do_send(int s, const std::string& spec, std::vector<char>& buffer) {
330 // 'spec' is of the form "/some/path,0755". Break it up.
331 size_t comma = spec.find_last_of(',');
332 if (comma == std::string::npos) {
Josh Gao6ad06b92016-01-28 16:21:12 -0800333 SendSyncFail(s, "missing , in ID_SEND");
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700334 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800335 }
336
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700337 std::string path = spec.substr(0, comma);
338
339 errno = 0;
340 mode_t mode = strtoul(spec.substr(comma + 1).c_str(), nullptr, 0);
341 if (errno != 0) {
Josh Gao6ad06b92016-01-28 16:21:12 -0800342 SendSyncFail(s, "bad mode");
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700343 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800344 }
345
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700346 // Don't delete files before copying if they are not "regular" or symlinks.
347 struct stat st;
348 bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
349 if (do_unlink) {
350 adb_unlink(path.c_str());
351 }
352
353 if (S_ISLNK(mode)) {
354 return handle_send_link(s, path.c_str(), buffer);
355 }
356
357 // Copy user permission bits to "group" and "other" permissions.
358 mode &= 0777;
359 mode |= ((mode >> 3) & 0070);
360 mode |= ((mode >> 3) & 0007);
361
Elliott Hughes0a049b12015-01-12 14:26:36 -0800362 uid_t uid = -1;
363 gid_t gid = -1;
Elliott Hughes32c60b42016-06-07 17:18:25 -0700364 uint64_t capabilities = 0;
Elliott Hughesec7a6672015-03-16 21:58:32 +0000365 if (should_use_fs_config(path)) {
Elliott Hughes7baecbe2015-08-25 11:09:04 -0700366 unsigned int broken_api_hack = mode;
Elliott Hughes32c60b42016-06-07 17:18:25 -0700367 fs_config(path.c_str(), 0, nullptr, &uid, &gid, &broken_api_hack, &capabilities);
Elliott Hughes56bf3092015-08-25 11:01:39 -0700368 mode = broken_api_hack;
Elliott Hughes0a049b12015-01-12 14:26:36 -0800369 }
Elliott Hughes32c60b42016-06-07 17:18:25 -0700370 return handle_send_file(s, path.c_str(), uid, gid, capabilities, mode, buffer, do_unlink);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371}
372
Elliott Hughesaa245492015-08-03 10:38:08 -0700373static bool do_recv(int s, const char* path, std::vector<char>& buffer) {
Rubin Xud61a25c2016-01-11 10:23:47 +0000374 __android_log_security_bswrite(SEC_TAG_ADB_RECV_FILE, path);
375
Elliott Hughesaa245492015-08-03 10:38:08 -0700376 int fd = adb_open(path, O_RDONLY | O_CLOEXEC);
377 if (fd < 0) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700378 SendSyncFailErrno(s, "open failed");
379 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380 }
381
Elliott Hughesaa245492015-08-03 10:38:08 -0700382 syncmsg msg;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800383 msg.data.id = ID_DATA;
Elliott Hughesaa245492015-08-03 10:38:08 -0700384 while (true) {
385 int r = adb_read(fd, &buffer[0], buffer.size());
386 if (r <= 0) {
387 if (r == 0) break;
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700388 SendSyncFailErrno(s, "read failed");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800389 adb_close(fd);
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700390 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800391 }
Elliott Hughesf4465202015-08-24 14:27:03 -0700392 msg.data.size = r;
Elliott Hughesaa245492015-08-03 10:38:08 -0700393 if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || !WriteFdExactly(s, &buffer[0], r)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800394 adb_close(fd);
Elliott Hughesaa245492015-08-03 10:38:08 -0700395 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800396 }
397 }
398
399 adb_close(fd);
400
401 msg.data.id = ID_DONE;
402 msg.data.size = 0;
Elliott Hughesaa245492015-08-03 10:38:08 -0700403 return WriteFdExactly(s, &msg.data, sizeof(msg.data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800404}
405
Elliott Hughesaa245492015-08-03 10:38:08 -0700406static bool handle_sync_command(int fd, std::vector<char>& buffer) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700407 D("sync: waiting for request");
Elliott Hughesaa245492015-08-03 10:38:08 -0700408
409 SyncRequest request;
410 if (!ReadFdExactly(fd, &request, sizeof(request))) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700411 SendSyncFail(fd, "command read failure");
Elliott Hughesaa245492015-08-03 10:38:08 -0700412 return false;
413 }
Elliott Hughesf4465202015-08-24 14:27:03 -0700414 size_t path_length = request.path_length;
Elliott Hughesaa245492015-08-03 10:38:08 -0700415 if (path_length > 1024) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700416 SendSyncFail(fd, "path too long");
Elliott Hughesaa245492015-08-03 10:38:08 -0700417 return false;
418 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800419 char name[1025];
Elliott Hughesaa245492015-08-03 10:38:08 -0700420 if (!ReadFdExactly(fd, name, path_length)) {
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700421 SendSyncFail(fd, "filename read failure");
Elliott Hughesaa245492015-08-03 10:38:08 -0700422 return false;
423 }
424 name[path_length] = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425
Elliott Hughesaa245492015-08-03 10:38:08 -0700426 const char* id = reinterpret_cast<const char*>(&request.id);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700427 D("sync: '%.4s' '%s'", id, name);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428
Elliott Hughesaa245492015-08-03 10:38:08 -0700429 switch (request.id) {
430 case ID_STAT:
431 if (!do_stat(fd, name)) return false;
432 break;
433 case ID_LIST:
434 if (!do_list(fd, name)) return false;
435 break;
436 case ID_SEND:
437 if (!do_send(fd, name, buffer)) return false;
438 break;
439 case ID_RECV:
440 if (!do_recv(fd, name, buffer)) return false;
441 break;
442 case ID_QUIT:
443 return false;
444 default:
Elliott Hughesfdd4e582015-08-24 19:30:46 -0700445 SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
Elliott Hughesaa245492015-08-03 10:38:08 -0700446 id, request.id));
447 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800448 }
449
Elliott Hughesaa245492015-08-03 10:38:08 -0700450 return true;
451}
452
453void file_sync_service(int fd, void* cookie) {
454 std::vector<char> buffer(SYNC_DATA_MAX);
455
456 while (handle_sync_command(fd, buffer)) {
457 }
458
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700459 D("sync: done");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800460 adb_close(fd);
461}