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, &timestamp, 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(), &timestamp, 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