1 /*
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
17 #define TRACE_TAG SYNC
18
19 #include "daemon/file_sync_service.h"
20
21 #include "sysdeps.h"
22
23 #include <dirent.h>
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <utime.h>
33
34 #include <memory>
35 #include <optional>
36 #include <span>
37 #include <string>
38 #include <variant>
39 #include <vector>
40
41 #include <android-base/file.h>
42 #include <android-base/macros.h>
43 #include <android-base/stringprintf.h>
44 #include <android-base/strings.h>
45
46 #include <adbd_fs.h>
47
48 // Needed for __android_log_security_bswrite.
49 #include <private/android_logger.h>
50
51 #if defined(__ANDROID__)
52 #include <linux/capability.h>
53 #include <selinux/android.h>
54 #include <sys/xattr.h>
55 #endif
56
57 #include "adb.h"
58 #include "adb_io.h"
59 #include "adb_trace.h"
60 #include "adb_utils.h"
61 #include "compression_utils.h"
62 #include "file_sync_protocol.h"
63 #include "security_log_tags.h"
64 #include "sysdeps/errno.h"
65
66 using android::base::borrowed_fd;
67 using android::base::Dirname;
68 using android::base::Realpath;
69 using android::base::StringPrintf;
70
71 // TODO(b/346842318): Delete this function once we no longer need compatibility with < V.
should_use_fs_config(const std::string & path)72 static bool should_use_fs_config([[maybe_unused]] const std::string& path) {
73 // adbd_fs_config comes from the system, which means that it could be old. Old versions of
74 // adbd_fs_config will rewrite the permissions unconditionally, which would prevent the host
75 // permissions from ever being used. We can't check getuid() == 0 here to defend against old
76 // versions of adbd_fs_config because we have tests that push files as root and expect them to
77 // have the host permissions. So if we are running on an old system, follow the logic from
78 // prior to https://r.android.com/2980341 i.e. leave behavior unchanged unless the system is
79 // updated as well.
80 #if defined(__ANDROID__)
81 if (android_get_device_api_level() < __ANDROID_API_V__) {
82 return !android::base::StartsWith(path, "/data/");
83 }
84 #endif
85 return true;
86 }
87
update_capabilities(const char * path,uint64_t capabilities)88 static bool update_capabilities(const char* path, uint64_t capabilities) {
89 #if defined(__ANDROID__)
90 if (capabilities == 0) {
91 // Ensure we clean up in case the capabilities weren't 0 in the past.
92 removexattr(path, XATTR_NAME_CAPS);
93 return true;
94 }
95
96 vfs_cap_data cap_data = {};
97 cap_data.magic_etc = VFS_CAP_REVISION_2 | VFS_CAP_FLAGS_EFFECTIVE;
98 cap_data.data[0].permitted = (capabilities & 0xffffffff);
99 cap_data.data[0].inheritable = 0;
100 cap_data.data[1].permitted = (capabilities >> 32);
101 cap_data.data[1].inheritable = 0;
102 return setxattr(path, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) != -1;
103 #else
104 UNUSED(path, capabilities);
105 return true;
106 #endif
107 }
108
secure_mkdirs(const std::string & path)109 static bool secure_mkdirs(const std::string& path) {
110 if (path[0] != '/') return false;
111
112 std::vector<std::string> path_components = android::base::Split(path, "/");
113 std::string partial_path;
114 for (const auto& path_component : path_components) {
115 uid_t uid = -1;
116 gid_t gid = -1;
117 mode_t mode = 0775;
118 uint64_t capabilities = 0;
119
120 if (path_component.empty()) {
121 continue;
122 }
123
124 if (partial_path.empty() || partial_path.back() != OS_PATH_SEPARATOR) {
125 partial_path += OS_PATH_SEPARATOR;
126 }
127 partial_path += path_component;
128
129 if (should_use_fs_config(partial_path)) {
130 adbd_fs_config(partial_path.c_str(), true, nullptr, &uid, &gid, &mode, &capabilities);
131 }
132 if (adb_mkdir(partial_path.c_str(), mode) == -1) {
133 if (errno != EEXIST) {
134 return false;
135 }
136 } else {
137 if (chown(partial_path.c_str(), uid, gid) == -1) return false;
138
139 #if defined(__ANDROID__)
140 // Not all filesystems support setting SELinux labels. http://b/23530370.
141 selinux_android_restorecon(partial_path.c_str(), 0);
142 #endif
143
144 if (!update_capabilities(partial_path.c_str(), capabilities)) return false;
145 }
146 }
147 return true;
148 }
149
do_lstat_v1(int s,const char * path)150 static bool do_lstat_v1(int s, const char* path) {
151 syncmsg msg = {};
152 msg.stat_v1.id = ID_LSTAT_V1;
153
154 struct stat st = {};
155 lstat(path, &st);
156 msg.stat_v1.mode = st.st_mode;
157 msg.stat_v1.size = st.st_size;
158 msg.stat_v1.mtime = st.st_mtime;
159 return WriteFdExactly(s, &msg.stat_v1, sizeof(msg.stat_v1));
160 }
161
do_stat_v2(int s,uint32_t id,const char * path)162 static bool do_stat_v2(int s, uint32_t id, const char* path) {
163 syncmsg msg = {};
164 msg.stat_v2.id = id;
165
166 decltype(&stat) stat_fn;
167 if (id == ID_STAT_V2) {
168 stat_fn = stat;
169 } else {
170 stat_fn = lstat;
171 }
172
173 struct stat st = {};
174 int rc = stat_fn(path, &st);
175 if (rc == -1) {
176 msg.stat_v2.error = errno_to_wire(errno);
177 } else {
178 msg.stat_v2.dev = st.st_dev;
179 msg.stat_v2.ino = st.st_ino;
180 msg.stat_v2.mode = st.st_mode;
181 msg.stat_v2.nlink = st.st_nlink;
182 msg.stat_v2.uid = st.st_uid;
183 msg.stat_v2.gid = st.st_gid;
184 msg.stat_v2.size = st.st_size;
185 msg.stat_v2.atime = st.st_atime;
186 msg.stat_v2.mtime = st.st_mtime;
187 msg.stat_v2.ctime = st.st_ctime;
188 }
189
190 return WriteFdExactly(s, &msg.stat_v2, sizeof(msg.stat_v2));
191 }
192
193 template <bool v2>
do_list(int s,const char * path)194 static bool do_list(int s, const char* path) {
195 dirent* de;
196
197 using MessageType =
198 std::conditional_t<v2, decltype(syncmsg::dent_v2), decltype(syncmsg::dent_v1)>;
199 MessageType msg;
200 uint32_t msg_id;
201 if constexpr (v2) {
202 msg_id = ID_DENT_V2;
203 } else {
204 msg_id = ID_DENT_V1;
205 }
206
207 std::unique_ptr<DIR, int(*)(DIR*)> d(opendir(path), closedir);
208 if (!d) goto done;
209
210 while ((de = readdir(d.get()))) {
211 memset(&msg, 0, sizeof(msg));
212 msg.id = msg_id;
213
214 std::string filename(StringPrintf("%s/%s", path, de->d_name));
215
216 struct stat st;
217 if (lstat(filename.c_str(), &st) == 0) {
218 msg.mode = st.st_mode;
219 msg.size = st.st_size;
220 msg.mtime = st.st_mtime;
221
222 if constexpr (v2) {
223 msg.dev = st.st_dev;
224 msg.ino = st.st_ino;
225 msg.nlink = st.st_nlink;
226 msg.uid = st.st_uid;
227 msg.gid = st.st_gid;
228 msg.atime = st.st_atime;
229 msg.ctime = st.st_ctime;
230 }
231 } else {
232 if constexpr (v2) {
233 msg.error = errno;
234 } else {
235 continue;
236 }
237 }
238
239 size_t d_name_length = strlen(de->d_name);
240 msg.namelen = d_name_length;
241
242 if (!WriteFdExactly(s, &msg, sizeof(msg)) ||
243 !WriteFdExactly(s, de->d_name, d_name_length)) {
244 return false;
245 }
246 }
247
248 done:
249 memset(&msg, 0, sizeof(msg));
250 msg.id = ID_DONE;
251 return WriteFdExactly(s, &msg, sizeof(msg));
252 }
253
do_list_v1(int s,const char * path)254 static bool do_list_v1(int s, const char* path) {
255 return do_list<false>(s, path);
256 }
257
do_list_v2(int s,const char * path)258 static bool do_list_v2(int s, const char* path) {
259 return do_list<true>(s, path);
260 }
261
262 // Make sure that SendFail from adb_io.cpp isn't accidentally used in this file.
263 #pragma GCC poison SendFail
264
SendSyncFail(borrowed_fd fd,const std::string & reason)265 static bool SendSyncFail(borrowed_fd fd, const std::string& reason) {
266 D("sync: failure: %s", reason.c_str());
267
268 syncmsg msg;
269 msg.data.id = ID_FAIL;
270 msg.data.size = reason.size();
271 return WriteFdExactly(fd, &msg.data, sizeof(msg.data)) && WriteFdExactly(fd, reason);
272 }
273
SendSyncFailErrno(borrowed_fd fd,const std::string & reason)274 static bool SendSyncFailErrno(borrowed_fd fd, const std::string& reason) {
275 return SendSyncFail(fd, StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
276 }
277
handle_send_file_data(borrowed_fd s,unique_fd fd,uint32_t * timestamp,CompressionType compression)278 static bool handle_send_file_data(borrowed_fd s, unique_fd fd, uint32_t* timestamp,
279 CompressionType compression) {
280 syncmsg msg;
281 Block buffer(SYNC_DATA_MAX);
282 std::span<char> buffer_span(buffer.data(), buffer.size());
283 std::variant<std::monostate, NullDecoder, BrotliDecoder, LZ4Decoder, ZstdDecoder>
284 decoder_storage;
285 Decoder* decoder = nullptr;
286
287 switch (compression) {
288 case CompressionType::None:
289 decoder = &decoder_storage.emplace<NullDecoder>(buffer_span);
290 break;
291
292 case CompressionType::Brotli:
293 decoder = &decoder_storage.emplace<BrotliDecoder>(buffer_span);
294 break;
295
296 case CompressionType::LZ4:
297 decoder = &decoder_storage.emplace<LZ4Decoder>(buffer_span);
298 break;
299
300 case CompressionType::Zstd:
301 decoder = &decoder_storage.emplace<ZstdDecoder>(buffer_span);
302 break;
303
304 case CompressionType::Any:
305 LOG(FATAL) << "unexpected CompressionType::Any";
306 }
307
308 while (true) {
309 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
310
311 if (msg.data.id == ID_DONE) {
312 *timestamp = msg.data.size;
313 decoder->Finish();
314 } else if (msg.data.id == ID_DATA) {
315 Block block(msg.data.size);
316 if (!ReadFdExactly(s, block.data(), msg.data.size)) return false;
317 decoder->Append(std::move(block));
318 } else {
319 SendSyncFail(s, "invalid data message");
320 return false;
321 }
322
323 while (true) {
324 std::span<char> output;
325 DecodeResult result = decoder->Decode(&output);
326 if (result == DecodeResult::Error) {
327 SendSyncFail(s, "decompress failed");
328 return false;
329 }
330
331 // fd is -1 if the client is pushing with --dry-run.
332 if (fd != -1) {
333 if (!WriteFdExactly(fd, output.data(), output.size())) {
334 SendSyncFailErrno(s, "write failed");
335 return false;
336 }
337 }
338
339 if (result == DecodeResult::NeedInput) {
340 break;
341 } else if (result == DecodeResult::MoreOutput) {
342 continue;
343 } else if (result == DecodeResult::Done) {
344 return true;
345 } else {
346 LOG(FATAL) << "invalid DecodeResult: " << static_cast<int>(result);
347 }
348 }
349 }
350
351 __builtin_unreachable();
352 }
353
handle_send_file(borrowed_fd s,const char * path,uint32_t * timestamp,uid_t uid,gid_t gid,uint64_t capabilities,mode_t mode,CompressionType compression,bool dry_run,std::vector<char> & buffer,bool do_unlink)354 static bool handle_send_file(borrowed_fd s, const char* path, uint32_t* timestamp, uid_t uid,
355 gid_t gid, uint64_t capabilities, mode_t mode,
356 CompressionType compression, bool dry_run, std::vector<char>& buffer,
357 bool do_unlink) {
358 syncmsg msg;
359 unique_fd fd;
360
361 if (!dry_run) {
362 __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path);
363 fd.reset(adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode));
364
365 if (fd < 0 && errno == ENOENT) {
366 if (!secure_mkdirs(Dirname(path))) {
367 SendSyncFailErrno(s, "secure_mkdirs() failed");
368 goto fail;
369 }
370 fd.reset(adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode));
371 }
372 if (fd < 0 && errno == EEXIST) {
373 fd.reset(adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode));
374 }
375 if (fd < 0) {
376 SendSyncFailErrno(s, "couldn't create file");
377 goto fail;
378 } else {
379 if (fchown(fd.get(), uid, gid) == -1) {
380 struct stat st;
381 std::string real_path;
382
383 // Only return failure if parent directory does not have S_ISGID bit set,
384 // if S_ISGID is set then file will inherit groupid from directory.
385 if (!Realpath(path, &real_path) || lstat(Dirname(real_path).c_str(), &st) == -1 ||
386 (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) == 0)) {
387 SendSyncFailErrno(s, StringPrintf("fchown() failed uid: %d gid: %d", uid, gid));
388 goto fail;
389 }
390 }
391
392 #if defined(__ANDROID__)
393 // Not all filesystems support setting SELinux labels. http://b/23530370.
394 selinux_android_restorecon(path, 0);
395 #endif
396
397 // fchown clears the setuid bit - restore it if present.
398 // Ignore the result of calling fchmod. It's not supported
399 // by all filesystems, so we don't check for success. b/12441485
400 fchmod(fd.get(), mode);
401 }
402
403 int rc = posix_fadvise(fd.get(), 0, 0,
404 POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED);
405 if (rc != 0) {
406 D("[ Failed to fadvise: %s ]", strerror(rc));
407 }
408 }
409
410 if (!handle_send_file_data(s, std::move(fd), timestamp, compression)) {
411 goto fail;
412 }
413
414 if (!update_capabilities(path, capabilities)) {
415 SendSyncFailErrno(s, "update_capabilities failed");
416 goto fail;
417 }
418
419 msg.status.id = ID_OKAY;
420 msg.status.msglen = 0;
421 return WriteFdExactly(s, &msg.status, sizeof(msg.status));
422
423 fail:
424 // If there's a problem on the device, we'll send an ID_FAIL message and
425 // close the socket. Unfortunately the kernel will sometimes throw that
426 // data away if the other end keeps writing without reading (which is
427 // the case with old versions of adb). To maintain compatibility, keep
428 // reading and throwing away ID_DATA packets until the other side notices
429 // that we've reported an error.
430 while (true) {
431 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) break;
432
433 if (msg.data.id == ID_DONE) {
434 break;
435 } else if (msg.data.id != ID_DATA) {
436 char id[5];
437 memcpy(id, &msg.data.id, sizeof(msg.data.id));
438 id[4] = '\0';
439 D("handle_send_fail received unexpected id '%s' during failure", id);
440 break;
441 }
442
443 if (msg.data.size > buffer.size()) {
444 D("handle_send_fail received oversized packet of length '%u' during failure",
445 msg.data.size);
446 break;
447 }
448
449 if (!ReadFdExactly(s, &buffer[0], msg.data.size)) break;
450 }
451
452 if (do_unlink) adb_unlink(path);
453 return false;
454 }
455
456 #if defined(_WIN32)
457 extern bool handle_send_link(int s, const std::string& path,
458 uint32_t* timestamp, std::vector<char>& buffer)
459 __attribute__((error("no symlinks on Windows")));
460 #else
handle_send_link(int s,const std::string & path,uint32_t * timestamp,bool dry_run,std::vector<char> & buffer)461 static bool handle_send_link(int s, const std::string& path, uint32_t* timestamp, bool dry_run,
462 std::vector<char>& buffer) {
463 syncmsg msg;
464
465 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
466
467 if (msg.data.id != ID_DATA) {
468 SendSyncFail(s, "invalid data message: expected ID_DATA");
469 return false;
470 }
471
472 unsigned int len = msg.data.size;
473 if (len > buffer.size()) { // TODO: resize buffer?
474 SendSyncFail(s, "oversize data message");
475 return false;
476 }
477 if (!ReadFdExactly(s, &buffer[0], len)) return false;
478
479 std::string buf_link;
480 if (!dry_run) {
481 if (!android::base::Readlink(path, &buf_link) || (buf_link != &buffer[0])) {
482 adb_unlink(path.c_str());
483 auto ret = symlink(&buffer[0], path.c_str());
484 if (ret && errno == ENOENT) {
485 if (!secure_mkdirs(Dirname(path))) {
486 SendSyncFailErrno(s, "secure_mkdirs failed");
487 return false;
488 }
489 ret = symlink(&buffer[0], path.c_str());
490 }
491 if (ret) {
492 SendSyncFailErrno(s, "symlink failed");
493 return false;
494 }
495 }
496 }
497
498 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
499
500 if (msg.data.id == ID_DONE) {
501 *timestamp = msg.data.size;
502 msg.status.id = ID_OKAY;
503 msg.status.msglen = 0;
504 if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
505 } else {
506 SendSyncFail(s, "invalid data message: expected ID_DONE");
507 return false;
508 }
509
510 return true;
511 }
512 #endif
513
send_impl(int s,const std::string & path,mode_t mode,CompressionType compression,bool dry_run,std::vector<char> & buffer)514 static bool send_impl(int s, const std::string& path, mode_t mode, CompressionType compression,
515 bool dry_run, std::vector<char>& buffer) {
516 // Don't delete files before copying if they are not "regular" or symlinks.
517 struct stat st;
518 bool do_unlink = false;
519 if (!dry_run) {
520 do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) ||
521 (S_ISLNK(st.st_mode) && !S_ISLNK(mode));
522 }
523 if (do_unlink) {
524 adb_unlink(path.c_str());
525 }
526
527 bool result;
528 uint32_t timestamp;
529 if (S_ISLNK(mode)) {
530 result = handle_send_link(s, path, ×tamp, dry_run, buffer);
531 } else {
532 // Copy user permission bits to "group" and "other" permissions.
533 mode &= 0777;
534 mode |= ((mode >> 3) & 0070);
535 mode |= ((mode >> 3) & 0007);
536
537 uid_t uid = -1;
538 gid_t gid = -1;
539 uint64_t capabilities = 0;
540 if (!dry_run && should_use_fs_config(path)) {
541 adbd_fs_config(path.c_str(), false, nullptr, &uid, &gid, &mode, &capabilities);
542 }
543
544 result = handle_send_file(s, path.c_str(), ×tamp, uid, gid, capabilities, mode,
545 compression, dry_run, buffer, do_unlink);
546 }
547
548 if (!result) {
549 return false;
550 }
551
552 struct timeval tv[2];
553 tv[0].tv_sec = timestamp;
554 tv[0].tv_usec = 0;
555 tv[1].tv_sec = timestamp;
556 tv[1].tv_usec = 0;
557 lutimes(path.c_str(), tv);
558 return true;
559 }
560
do_send_v1(int s,const std::string & spec,std::vector<char> & buffer)561 static bool do_send_v1(int s, const std::string& spec, std::vector<char>& buffer) {
562 // 'spec' is of the form "/some/path,0755". Break it up.
563 size_t comma = spec.find_last_of(',');
564 if (comma == std::string::npos) {
565 SendSyncFail(s, "missing , in ID_SEND_V1");
566 return false;
567 }
568
569 std::string path = spec.substr(0, comma);
570
571 errno = 0;
572 mode_t mode = strtoul(spec.substr(comma + 1).c_str(), nullptr, 0);
573 if (errno != 0) {
574 SendSyncFail(s, "bad mode");
575 return false;
576 }
577
578 return send_impl(s, path, mode, CompressionType::None, false, buffer);
579 }
580
do_send_v2(int s,const std::string & path,std::vector<char> & buffer)581 static bool do_send_v2(int s, const std::string& path, std::vector<char>& buffer) {
582 // Read the setup packet.
583 syncmsg msg;
584 int rc = ReadFdExactly(s, &msg.send_v2_setup, sizeof(msg.send_v2_setup));
585 if (rc == 0) {
586 LOG(ERROR) << "failed to read send_v2 setup packet: EOF";
587 return false;
588 } else if (rc < 0) {
589 PLOG(ERROR) << "failed to read send_v2 setup packet";
590 }
591
592 bool dry_run = false;
593 std::optional<CompressionType> compression;
594
595 uint32_t orig_flags = msg.send_v2_setup.flags;
596 if (msg.send_v2_setup.flags & kSyncFlagBrotli) {
597 msg.send_v2_setup.flags &= ~kSyncFlagBrotli;
598 if (compression) {
599 SendSyncFail(s, StringPrintf("multiple compression flags received: %d", orig_flags));
600 return false;
601 }
602 compression = CompressionType::Brotli;
603 }
604 if (msg.send_v2_setup.flags & kSyncFlagLZ4) {
605 msg.send_v2_setup.flags &= ~kSyncFlagLZ4;
606 if (compression) {
607 SendSyncFail(s, StringPrintf("multiple compression flags received: %d", orig_flags));
608 return false;
609 }
610 compression = CompressionType::LZ4;
611 }
612 if (msg.send_v2_setup.flags & kSyncFlagZstd) {
613 msg.send_v2_setup.flags &= ~kSyncFlagZstd;
614 if (compression) {
615 SendSyncFail(s, StringPrintf("multiple compression flags received: %d", orig_flags));
616 return false;
617 }
618 compression = CompressionType::Zstd;
619 }
620 if (msg.send_v2_setup.flags & kSyncFlagDryRun) {
621 msg.send_v2_setup.flags &= ~kSyncFlagDryRun;
622 dry_run = true;
623 }
624
625 if (msg.send_v2_setup.flags) {
626 SendSyncFail(s, StringPrintf("unknown flags: %d", msg.send_v2_setup.flags));
627 return false;
628 }
629
630 errno = 0;
631 return send_impl(s, path, msg.send_v2_setup.mode, compression.value_or(CompressionType::None),
632 dry_run, buffer);
633 }
634
recv_impl(borrowed_fd s,const char * path,CompressionType compression,std::vector<char> & buffer)635 static bool recv_impl(borrowed_fd s, const char* path, CompressionType compression,
636 std::vector<char>& buffer) {
637 __android_log_security_bswrite(SEC_TAG_ADB_RECV_FILE, path);
638
639 unique_fd fd(adb_open(path, O_RDONLY | O_CLOEXEC));
640 if (fd < 0) {
641 SendSyncFailErrno(s, "open failed");
642 return false;
643 }
644
645 int rc = posix_fadvise(fd.get(), 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
646 if (rc != 0) {
647 D("[ Failed to fadvise: %s ]", strerror(rc));
648 }
649
650 syncmsg msg;
651 msg.data.id = ID_DATA;
652
653 std::variant<std::monostate, NullEncoder, BrotliEncoder, LZ4Encoder, ZstdEncoder>
654 encoder_storage;
655 Encoder* encoder;
656
657 switch (compression) {
658 case CompressionType::None:
659 encoder = &encoder_storage.emplace<NullEncoder>(SYNC_DATA_MAX);
660 break;
661
662 case CompressionType::Brotli:
663 encoder = &encoder_storage.emplace<BrotliEncoder>(SYNC_DATA_MAX);
664 break;
665
666 case CompressionType::LZ4:
667 encoder = &encoder_storage.emplace<LZ4Encoder>(SYNC_DATA_MAX);
668 break;
669
670 case CompressionType::Zstd:
671 encoder = &encoder_storage.emplace<ZstdEncoder>(SYNC_DATA_MAX);
672 break;
673
674 case CompressionType::Any:
675 LOG(FATAL) << "unexpected CompressionType::Any";
676 }
677
678 bool sending = true;
679 while (sending) {
680 Block input(SYNC_DATA_MAX);
681 int r = adb_read(fd.get(), input.data(), input.size());
682 if (r < 0) {
683 SendSyncFailErrno(s, "read failed");
684 return false;
685 }
686
687 if (r == 0) {
688 encoder->Finish();
689 } else {
690 input.resize(r);
691 encoder->Append(std::move(input));
692 }
693
694 while (true) {
695 Block output;
696 EncodeResult result = encoder->Encode(&output);
697 if (result == EncodeResult::Error) {
698 SendSyncFailErrno(s, "compress failed");
699 return false;
700 }
701
702 if (!output.empty()) {
703 msg.data.size = output.size();
704 if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) ||
705 !WriteFdExactly(s, output.data(), output.size())) {
706 return false;
707 }
708 }
709
710 if (result == EncodeResult::Done) {
711 sending = false;
712 break;
713 } else if (result == EncodeResult::NeedInput) {
714 break;
715 } else if (result == EncodeResult::MoreOutput) {
716 continue;
717 }
718 }
719 }
720
721 msg.data.id = ID_DONE;
722 msg.data.size = 0;
723 return WriteFdExactly(s, &msg.data, sizeof(msg.data));
724 }
725
do_recv_v1(borrowed_fd s,const char * path,std::vector<char> & buffer)726 static bool do_recv_v1(borrowed_fd s, const char* path, std::vector<char>& buffer) {
727 return recv_impl(s, path, CompressionType::None, buffer);
728 }
729
do_recv_v2(borrowed_fd s,const char * path,std::vector<char> & buffer)730 static bool do_recv_v2(borrowed_fd s, const char* path, std::vector<char>& buffer) {
731 syncmsg msg;
732 // Read the setup packet.
733 int rc = ReadFdExactly(s, &msg.recv_v2_setup, sizeof(msg.recv_v2_setup));
734 if (rc == 0) {
735 LOG(ERROR) << "failed to read recv_v2 setup packet: EOF";
736 return false;
737 } else if (rc < 0) {
738 PLOG(ERROR) << "failed to read recv_v2 setup packet";
739 }
740
741 std::optional<CompressionType> compression;
742 uint32_t orig_flags = msg.recv_v2_setup.flags;
743 if (msg.recv_v2_setup.flags & kSyncFlagBrotli) {
744 msg.recv_v2_setup.flags &= ~kSyncFlagBrotli;
745 if (compression) {
746 SendSyncFail(s, StringPrintf("multiple compression flags received: %d", orig_flags));
747 return false;
748 }
749 compression = CompressionType::Brotli;
750 }
751 if (msg.recv_v2_setup.flags & kSyncFlagLZ4) {
752 msg.recv_v2_setup.flags &= ~kSyncFlagLZ4;
753 if (compression) {
754 SendSyncFail(s, StringPrintf("multiple compression flags received: %d", orig_flags));
755 return false;
756 }
757 compression = CompressionType::LZ4;
758 }
759 if (msg.recv_v2_setup.flags & kSyncFlagZstd) {
760 msg.recv_v2_setup.flags &= ~kSyncFlagZstd;
761 if (compression) {
762 SendSyncFail(s, StringPrintf("multiple compression flags received: %d", orig_flags));
763 return false;
764 }
765 compression = CompressionType::Zstd;
766 }
767
768 if (msg.recv_v2_setup.flags) {
769 SendSyncFail(s, StringPrintf("unknown flags: %d", msg.recv_v2_setup.flags));
770 return false;
771 }
772
773 return recv_impl(s, path, compression.value_or(CompressionType::None), buffer);
774 }
775
sync_id_to_name(uint32_t id)776 static const char* sync_id_to_name(uint32_t id) {
777 switch (id) {
778 case ID_LSTAT_V1:
779 return "lstat_v1";
780 case ID_LSTAT_V2:
781 return "lstat_v2";
782 case ID_STAT_V2:
783 return "stat_v2";
784 case ID_LIST_V1:
785 return "list_v1";
786 case ID_LIST_V2:
787 return "list_v2";
788 case ID_SEND_V1:
789 return "send_v1";
790 case ID_SEND_V2:
791 return "send_v2";
792 case ID_RECV_V1:
793 return "recv_v1";
794 case ID_RECV_V2:
795 return "recv_v2";
796 case ID_QUIT:
797 return "quit";
798 default:
799 return "???";
800 }
801 }
802
handle_sync_command(int fd,std::vector<char> & buffer)803 static bool handle_sync_command(int fd, std::vector<char>& buffer) {
804 D("sync: waiting for request");
805
806 SyncRequest request;
807 if (!ReadFdExactly(fd, &request, sizeof(request))) {
808 SendSyncFail(fd, "command read failure");
809 return false;
810 }
811 size_t path_length = request.path_length;
812 if (path_length > 1024) {
813 SendSyncFail(fd, "path too long");
814 return false;
815 }
816 char name[1025];
817 if (!ReadFdExactly(fd, name, path_length)) {
818 SendSyncFail(fd, "filename read failure");
819 return false;
820 }
821 name[path_length] = 0;
822
823 std::string id_name = sync_id_to_name(request.id);
824
825 D("sync: %s('%s')", id_name.c_str(), name);
826 switch (request.id) {
827 case ID_LSTAT_V1:
828 if (!do_lstat_v1(fd, name)) return false;
829 break;
830 case ID_LSTAT_V2:
831 case ID_STAT_V2:
832 if (!do_stat_v2(fd, request.id, name)) return false;
833 break;
834 case ID_LIST_V1:
835 if (!do_list_v1(fd, name)) return false;
836 break;
837 case ID_LIST_V2:
838 if (!do_list_v2(fd, name)) return false;
839 break;
840 case ID_SEND_V1:
841 if (!do_send_v1(fd, name, buffer)) return false;
842 break;
843 case ID_SEND_V2:
844 if (!do_send_v2(fd, name, buffer)) return false;
845 break;
846 case ID_RECV_V1:
847 if (!do_recv_v1(fd, name, buffer)) return false;
848 break;
849 case ID_RECV_V2:
850 if (!do_recv_v2(fd, name, buffer)) return false;
851 break;
852 case ID_QUIT:
853 return false;
854 default:
855 SendSyncFail(fd, StringPrintf("unknown command %08x", request.id));
856 return false;
857 }
858
859 return true;
860 }
861
file_sync_service(unique_fd fd)862 void file_sync_service(unique_fd fd) {
863 std::vector<char> buffer(SYNC_DATA_MAX);
864
865 while (handle_sync_command(fd.get(), buffer)) {
866 }
867
868 D("sync: done");
869 }
870