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