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