blob: 1d668bc18099a9e6329bc826e4260b2995fc5f5b [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dan Albertb302d122015-02-24 15:51:19 -080017#include <dirent.h>
18#include <errno.h>
Spencer Low803451e2015-05-13 00:02:55 -070019#include <inttypes.h>
Dan Albertb302d122015-02-24 15:51:19 -080020#include <limits.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080021#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080024#include <sys/stat.h>
25#include <sys/time.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080026#include <sys/types.h>
Dan Albertb302d122015-02-24 15:51:19 -080027#include <time.h>
Elliott Hughesdde00be2015-09-27 12:55:37 -070028#include <unistd.h>
Greg Hackmann8b689142014-05-06 08:48:18 -070029#include <utime.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080030
Elliott Hughes4e7848d2015-08-24 14:49:43 -070031#include <memory>
Elliott Hughes6c73bfc2015-10-27 13:40:35 -070032#include <vector>
Elliott Hughes4e7848d2015-08-24 14:49:43 -070033
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080034#include "sysdeps.h"
Dan Albertb302d122015-02-24 15:51:19 -080035
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080036#include "adb.h"
37#include "adb_client.h"
Dan Albert66a91b02015-02-24 21:26:58 -080038#include "adb_io.h"
Alex Valléee9163152015-05-06 17:22:25 -040039#include "adb_utils.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080040#include "file_sync_service.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080041
Elliott Hughesdde00be2015-09-27 12:55:37 -070042#include <base/file.h>
Elliott Hughesb628cb12015-08-03 10:38:08 -070043#include <base/strings.h>
Elliott Hughesd189cfb2015-07-30 17:42:01 -070044#include <base/stringprintf.h>
45
Elliott Hughesb628cb12015-08-03 10:38:08 -070046struct syncsendbuf {
47 unsigned id;
48 unsigned size;
49 char data[SYNC_DATA_MAX];
50};
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080051
Elliott Hughesb628cb12015-08-03 10:38:08 -070052static long long NOW() {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080053 struct timeval tv;
54 gettimeofday(&tv, 0);
Elliott Hughesb628cb12015-08-03 10:38:08 -070055 return ((long long) tv.tv_usec) + 1000000LL * ((long long) tv.tv_sec);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080056}
57
Spencer Low803451e2015-05-13 00:02:55 -070058static void print_transfer_progress(uint64_t bytes_current,
59 uint64_t bytes_total) {
Mark Lindner9f9d1452014-03-11 17:55:59 -070060 if (bytes_total == 0) return;
61
Spencer Low803451e2015-05-13 00:02:55 -070062 fprintf(stderr, "\rTransferring: %" PRIu64 "/%" PRIu64 " (%d%%)",
63 bytes_current, bytes_total,
Mark Lindner9f9d1452014-03-11 17:55:59 -070064 (int) (bytes_current * 100 / bytes_total));
65
66 if (bytes_current == bytes_total) {
67 fputc('\n', stderr);
68 }
69
70 fflush(stderr);
71}
72
Elliott Hughesb628cb12015-08-03 10:38:08 -070073class SyncConnection {
74 public:
75 SyncConnection() : total_bytes(0), start_time_(NOW()) {
76 max = SYNC_DATA_MAX; // TODO: decide at runtime.
77
78 std::string error;
79 fd = adb_connect("sync:", &error);
80 if (fd < 0) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -070081 fprintf(stderr, "adb: error: %s\n", error.c_str());
Elliott Hughesb628cb12015-08-03 10:38:08 -070082 }
83 }
84
85 ~SyncConnection() {
86 if (!IsValid()) return;
87
88 SendQuit();
89 ShowTransferRate();
90 adb_close(fd);
91 }
92
93 bool IsValid() { return fd >= 0; }
94
Elliott Hughesdde00be2015-09-27 12:55:37 -070095 bool SendRequest(int id, const char* path_and_mode) {
96 size_t path_length = strlen(path_and_mode);
97 if (path_length > 1024) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -070098 fprintf(stderr, "adb: SendRequest failed: path too long: %zu\n", path_length);
Elliott Hughesdde00be2015-09-27 12:55:37 -070099 errno = ENAMETOOLONG;
100 return false;
101 }
102
103 // Sending header and payload in a single write makes a noticeable
104 // difference to "adb sync" performance.
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700105 std::vector<char> buf(sizeof(SyncRequest) + path_length);
106 SyncRequest* req = reinterpret_cast<SyncRequest*>(&buf[0]);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700107 req->id = id;
108 req->path_length = path_length;
109 char* data = reinterpret_cast<char*>(req + 1);
110 memcpy(data, path_and_mode, path_length);
111
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700112 return WriteFdExactly(fd, &buf[0], buf.size());
Elliott Hughesdde00be2015-09-27 12:55:37 -0700113 }
114
115 // Sending header, payload, and footer in a single write makes a huge
116 // difference to "adb sync" performance.
117 bool SendSmallFile(const char* path_and_mode,
118 const char* data, size_t data_length,
119 unsigned mtime) {
120 size_t path_length = strlen(path_and_mode);
121 if (path_length > 1024) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700122 fprintf(stderr, "adb: SendSmallFile failed: path too long: %zu\n", path_length);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700123 errno = ENAMETOOLONG;
124 return false;
125 }
126
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700127 std::vector<char> buf(sizeof(SyncRequest) + path_length +
Elliott Hughesdde00be2015-09-27 12:55:37 -0700128 sizeof(SyncRequest) + data_length +
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700129 sizeof(SyncRequest));
130 char* p = &buf[0];
Elliott Hughesdde00be2015-09-27 12:55:37 -0700131
132 SyncRequest* req_send = reinterpret_cast<SyncRequest*>(p);
133 req_send->id = ID_SEND;
134 req_send->path_length = path_length;
135 p += sizeof(SyncRequest);
136 memcpy(p, path_and_mode, path_length);
137 p += path_length;
138
139 SyncRequest* req_data = reinterpret_cast<SyncRequest*>(p);
140 req_data->id = ID_DATA;
141 req_data->path_length = data_length;
142 p += sizeof(SyncRequest);
143 memcpy(p, data, data_length);
144 p += data_length;
145
146 SyncRequest* req_done = reinterpret_cast<SyncRequest*>(p);
147 req_done->id = ID_DONE;
148 req_done->path_length = mtime;
149 p += sizeof(SyncRequest);
150
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700151 if (!WriteFdExactly(fd, &buf[0], (p - &buf[0]))) return false;
Elliott Hughesdde00be2015-09-27 12:55:37 -0700152
153 total_bytes += data_length;
154 return true;
155 }
156
157 bool CopyDone(const char* from, const char* to) {
158 syncmsg msg;
159 if (!ReadFdExactly(fd, &msg.status, sizeof(msg.status))) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700160 fprintf(stderr, "adb: failed to copy '%s' to '%s': no ID_DONE: %s\n",
Elliott Hughesdde00be2015-09-27 12:55:37 -0700161 from, to, strerror(errno));
162 return false;
163 }
164 if (msg.status.id == ID_OKAY) {
165 return true;
166 }
167 if (msg.status.id != ID_FAIL) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700168 fprintf(stderr, "adb: failed to copy '%s' to '%s': unknown reason %d\n",
169 from, to, msg.status.id);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700170 return false;
171 }
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700172 return ReportCopyFailure(from, to, msg);
173 }
174
175 bool ReportCopyFailure(const char* from, const char* to, const syncmsg& msg) {
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700176 std::vector<char> buf(msg.status.msglen + 1);
177 if (!ReadFdExactly(fd, &buf[0], msg.status.msglen)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700178 fprintf(stderr, "adb: failed to copy '%s' to '%s'; failed to read reason (!): %s\n",
Elliott Hughesdde00be2015-09-27 12:55:37 -0700179 from, to, strerror(errno));
180 return false;
181 }
Elliott Hughes6c73bfc2015-10-27 13:40:35 -0700182 buf[msg.status.msglen] = 0;
183 fprintf(stderr, "adb: failed to copy '%s' to '%s': %s\n", from, to, &buf[0]);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700184 return false;
185 }
186
Elliott Hughesb628cb12015-08-03 10:38:08 -0700187 uint64_t total_bytes;
188
189 // TODO: add a char[max] buffer here, to replace syncsendbuf...
190 int fd;
191 size_t max;
192
193 private:
194 uint64_t start_time_;
195
196 void SendQuit() {
Elliott Hughesdde00be2015-09-27 12:55:37 -0700197 SendRequest(ID_QUIT, ""); // TODO: add a SendResponse?
Elliott Hughesb628cb12015-08-03 10:38:08 -0700198 }
199
200 void ShowTransferRate() {
201 uint64_t t = NOW() - start_time_;
202 if (total_bytes == 0 || t == 0) return;
203
204 fprintf(stderr, "%lld KB/s (%" PRId64 " bytes in %lld.%03llds)\n",
205 ((total_bytes * 1000000LL) / t) / 1024LL,
206 total_bytes, (t / 1000000LL), (t % 1000000LL) / 1000LL);
207 }
208};
209
210typedef void (*sync_ls_cb)(unsigned mode, unsigned size, unsigned time, const char* name, void* cookie);
211
Elliott Hughesdde00be2015-09-27 12:55:37 -0700212static bool sync_ls(SyncConnection& sc, const char* path, sync_ls_cb func, void* cookie) {
213 if (!sc.SendRequest(ID_LIST, path)) return false;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700214
215 while (true) {
216 syncmsg msg;
Elliott Hughesdde00be2015-09-27 12:55:37 -0700217 if (!ReadFdExactly(sc.fd, &msg.dent, sizeof(msg.dent))) return false;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700218
219 if (msg.dent.id == ID_DONE) return true;
220 if (msg.dent.id != ID_DENT) return false;
221
Elliott Hughes9e8e3552015-08-24 14:27:03 -0700222 size_t len = msg.dent.namelen;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700223 if (len > 256) return false; // TODO: resize buffer? continue?
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800224
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700225 char buf[257];
Elliott Hughesdde00be2015-09-27 12:55:37 -0700226 if (!ReadFdExactly(sc.fd, buf, len)) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800227 buf[len] = 0;
228
Elliott Hughes9e8e3552015-08-24 14:27:03 -0700229 func(msg.dent.mode, msg.dent.size, msg.dent.time, buf, cookie);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800230 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800231}
232
Elliott Hughesb628cb12015-08-03 10:38:08 -0700233static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
234 unsigned int* mode, unsigned int* size) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800235 syncmsg msg;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700236 if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) {
237 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800238 }
239
Elliott Hughes9e8e3552015-08-24 14:27:03 -0700240 if (timestamp) *timestamp = msg.stat.time;
241 if (mode) *mode = msg.stat.mode;
242 if (size) *size = msg.stat.size;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800243
Elliott Hughesb628cb12015-08-03 10:38:08 -0700244 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800245}
246
Elliott Hughesb628cb12015-08-03 10:38:08 -0700247static bool sync_stat(SyncConnection& sc, const char* path,
248 unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
Elliott Hughesdde00be2015-09-27 12:55:37 -0700249 return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800250}
251
Elliott Hughesdde00be2015-09-27 12:55:37 -0700252static bool SendLargeFile(SyncConnection& sc, const char* path_and_mode, const char* path,
253 unsigned mtime, bool show_progress) {
254 if (!sc.SendRequest(ID_SEND, path_and_mode)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700255 fprintf(stderr, "adb: failed to send ID_SEND message '%s': %s\n",
Elliott Hughesdde00be2015-09-27 12:55:37 -0700256 path_and_mode, strerror(errno));
257 return false;
258 }
259
Mark Lindner9f9d1452014-03-11 17:55:59 -0700260 unsigned long long size = 0;
Spencer Lowc1a31332015-08-28 01:07:30 -0700261 if (show_progress) {
262 // Determine local file size.
263 struct stat st;
264 if (stat(path, &st) == -1) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700265 fprintf(stderr, "adb: cannot stat '%s': %s\n", path, strerror(errno));
Spencer Lowc1a31332015-08-28 01:07:30 -0700266 return false;
267 }
268
269 size = st.st_size;
270 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800271
Elliott Hughesb628cb12015-08-03 10:38:08 -0700272 int lfd = adb_open(path, O_RDONLY);
273 if (lfd < 0) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700274 fprintf(stderr, "adb: cannot open '%s': %s\n", path, strerror(errno));
Spencer Lowc1a31332015-08-28 01:07:30 -0700275 return false;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700276 }
277
Elliott Hughesdde00be2015-09-27 12:55:37 -0700278 syncsendbuf sbuf;
279 sbuf.id = ID_DATA;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700280 while (true) {
Elliott Hughesdde00be2015-09-27 12:55:37 -0700281 int ret = adb_read(lfd, sbuf.data, sc.max);
Elliott Hughes0bd85872015-08-25 10:59:45 -0700282 if (ret <= 0) {
Spencer Lowc1a31332015-08-28 01:07:30 -0700283 if (ret < 0) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700284 fprintf(stderr, "adb: cannot read '%s': %s\n", path, strerror(errno));
Spencer Lowc1a31332015-08-28 01:07:30 -0700285 adb_close(lfd);
286 return false;
287 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800288 break;
289 }
290
Elliott Hughesdde00be2015-09-27 12:55:37 -0700291 sbuf.size = ret;
292 if (!WriteFdExactly(sc.fd, &sbuf, sizeof(unsigned) * 2 + ret)) {
Spencer Lowc1a31332015-08-28 01:07:30 -0700293 adb_close(lfd);
294 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800295 }
Elliott Hughesb628cb12015-08-03 10:38:08 -0700296 sc.total_bytes += ret;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700297
298 if (show_progress) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700299 print_transfer_progress(sc.total_bytes, size);
Mark Lindner9f9d1452014-03-11 17:55:59 -0700300 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800301 }
302
303 adb_close(lfd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800304
Elliott Hughesb628cb12015-08-03 10:38:08 -0700305 syncmsg msg;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800306 msg.data.id = ID_DONE;
Elliott Hughes9e8e3552015-08-24 14:27:03 -0700307 msg.data.size = mtime;
Elliott Hughesc5d51622015-09-03 11:06:00 -0700308 if (!WriteFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700309 fprintf(stderr, "adb: failed to send ID_DONE message for '%s': %s\n",
310 path, strerror(errno));
Elliott Hughesb628cb12015-08-03 10:38:08 -0700311 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800312 }
313
Elliott Hughesb628cb12015-08-03 10:38:08 -0700314 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800315}
316
Elliott Hughesdde00be2015-09-27 12:55:37 -0700317static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
318 unsigned mtime, mode_t mode, bool show_progress)
319{
320 std::string path_and_mode = android::base::StringPrintf("%s,%d", rpath, mode);
321
322 if (S_ISLNK(mode)) {
323#if !defined(_WIN32)
324 char buf[PATH_MAX];
325 ssize_t data_length = readlink(lpath, buf, PATH_MAX - 1);
326 if (data_length == -1) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700327 fprintf(stderr, "adb: readlink '%s' failed: %s\n", lpath, strerror(errno));
Elliott Hughesdde00be2015-09-27 12:55:37 -0700328 return false;
329 }
330 buf[data_length++] = '\0';
331
332 if (!sc.SendSmallFile(path_and_mode.c_str(), buf, data_length, mtime)) return false;
333 return sc.CopyDone(lpath, rpath);
334#endif
335 }
336
337 if (!S_ISREG(mode)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700338 fprintf(stderr, "adb: local file '%s' has unsupported mode: 0o%o\n", lpath, mode);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700339 return false;
340 }
341
342 struct stat st;
343 if (stat(lpath, &st) == -1) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700344 fprintf(stderr, "adb: failed to stat local file '%s': %s\n", lpath, strerror(errno));
Elliott Hughesdde00be2015-09-27 12:55:37 -0700345 return false;
346 }
347 if (st.st_size < SYNC_DATA_MAX) {
348 std::string data;
349 if (!android::base::ReadFileToString(lpath, &data)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700350 fprintf(stderr, "adb: failed to read all of '%s': %s\n", lpath, strerror(errno));
Elliott Hughesdde00be2015-09-27 12:55:37 -0700351 return false;
352 }
353 if (!sc.SendSmallFile(path_and_mode.c_str(), data.data(), data.size(), mtime)) return false;
354 } else {
355 if (!SendLargeFile(sc, path_and_mode.c_str(), lpath, mtime, show_progress)) return false;
356 }
357 return sc.CopyDone(lpath, rpath);
358}
359
360static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, bool show_progress) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700361 unsigned size = 0;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700362 if (show_progress) {
Elliott Hughesdde00be2015-09-27 12:55:37 -0700363 if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700364 }
365
Elliott Hughesdde00be2015-09-27 12:55:37 -0700366 if (!sc.SendRequest(ID_RECV, rpath)) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800367
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700368 adb_unlink(lpath);
369 mkdirs(lpath);
370 int lfd = adb_creat(lpath, 0644);
371 if (lfd < 0) {
372 fprintf(stderr, "adb: cannot create '%s': %s\n", lpath, strerror(errno));
373 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800374 }
375
Elliott Hughesb628cb12015-08-03 10:38:08 -0700376 while (true) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700377 syncmsg msg;
Elliott Hughesdde00be2015-09-27 12:55:37 -0700378 if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
Spencer Lowc1a31332015-08-28 01:07:30 -0700379 adb_close(lfd);
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700380 adb_unlink(lpath);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700381 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800382 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800383
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700384 if (msg.data.id == ID_DONE) break;
385
386 if (msg.data.id != ID_DATA) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800387 adb_close(lfd);
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700388 adb_unlink(lpath);
389 sc.ReportCopyFailure(rpath, lpath, msg);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700390 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800391 }
392
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700393 if (msg.data.size > sc.max) {
394 fprintf(stderr, "adb: msg.data.size too large: %u (max %zu)\n", msg.data.size, sc.max);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800395 adb_close(lfd);
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700396 adb_unlink(lpath);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700397 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800398 }
399
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700400 char buffer[SYNC_DATA_MAX];
401 if (!ReadFdExactly(sc.fd, buffer, msg.data.size)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800402 adb_close(lfd);
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700403 adb_unlink(lpath);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700404 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800405 }
406
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700407 if (!WriteFdExactly(lfd, buffer, msg.data.size)) {
408 fprintf(stderr, "adb: cannot write '%s': %s\n", lpath, strerror(errno));
409 adb_close(lfd);
410 adb_unlink(lpath);
411 return false;
412 }
413
414 sc.total_bytes += msg.data.size;
Mark Lindner9f9d1452014-03-11 17:55:59 -0700415
416 if (show_progress) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700417 print_transfer_progress(sc.total_bytes, size);
Mark Lindner9f9d1452014-03-11 17:55:59 -0700418 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800419 }
420
421 adb_close(lfd);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700422 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800423}
424
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800425static void do_sync_ls_cb(unsigned mode, unsigned size, unsigned time,
Elliott Hughesb628cb12015-08-03 10:38:08 -0700426 const char* name, void* /*cookie*/) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800427 printf("%08x %08x %08x %s\n", mode, size, time, name);
428}
429
Elliott Hughesb628cb12015-08-03 10:38:08 -0700430bool do_sync_ls(const char* path) {
431 SyncConnection sc;
432 if (!sc.IsValid()) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800433
Elliott Hughesdde00be2015-09-27 12:55:37 -0700434 return sync_ls(sc, path, do_sync_ls_cb, 0);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800435}
436
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800437struct copyinfo
438{
439 copyinfo *next;
440 const char *src;
441 const char *dst;
442 unsigned int time;
443 unsigned int mode;
Elliott Hughesdde00be2015-09-27 12:55:37 -0700444 uint64_t size;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800445 int flag;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800446};
447
Elliott Hughes712416a2015-05-05 18:26:10 -0700448static copyinfo* mkcopyinfo(const char* spath, const char* dpath, const char* name, int isdir) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800449 int slen = strlen(spath);
450 int dlen = strlen(dpath);
451 int nlen = strlen(name);
452 int ssize = slen + nlen + 2;
453 int dsize = dlen + nlen + 2;
454
Elliott Hughes712416a2015-05-05 18:26:10 -0700455 copyinfo *ci = reinterpret_cast<copyinfo*>(malloc(sizeof(copyinfo) + ssize + dsize));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800456 if(ci == 0) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700457 fprintf(stderr, "out of memory\n");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800458 abort();
459 }
460
461 ci->next = 0;
462 ci->time = 0;
463 ci->mode = 0;
464 ci->size = 0;
465 ci->flag = 0;
466 ci->src = (const char*)(ci + 1);
467 ci->dst = ci->src + ssize;
468 snprintf((char*) ci->src, ssize, isdir ? "%s%s/" : "%s%s", spath, name);
469 snprintf((char*) ci->dst, dsize, isdir ? "%s%s/" : "%s%s", dpath, name);
470
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800471 return ci;
472}
473
Elliott Hughesb628cb12015-08-03 10:38:08 -0700474static bool IsDotOrDotDot(const char* name) {
475 return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
476}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800477
Elliott Hughesb628cb12015-08-03 10:38:08 -0700478static int local_build_list(copyinfo** filelist, const char* lpath, const char* rpath) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800479 copyinfo *dirlist = 0;
480 copyinfo *ci, *next;
481
Elliott Hughesb628cb12015-08-03 10:38:08 -0700482 std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(lpath), closedir);
483 if (!dir) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700484 fprintf(stderr, "adb: cannot open '%s': %s\n", lpath, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800485 return -1;
486 }
487
Elliott Hughesb628cb12015-08-03 10:38:08 -0700488 dirent *de;
489 while ((de = readdir(dir.get()))) {
490 if (IsDotOrDotDot(de->d_name)) continue;
491
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800492 char stat_path[PATH_MAX];
Elliott Hughesb628cb12015-08-03 10:38:08 -0700493 if (strlen(lpath) + strlen(de->d_name) + 1 > sizeof(stat_path)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700494 fprintf(stderr, "adb: skipping long path '%s%s'\n", lpath, de->d_name);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800495 continue;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700496 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800497 strcpy(stat_path, lpath);
498 strcat(stat_path, de->d_name);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800499
Elliott Hughesb628cb12015-08-03 10:38:08 -0700500 struct stat st;
501 if (!lstat(stat_path, &st)) {
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700502 if (S_ISDIR(st.st_mode)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700503 ci = mkcopyinfo(lpath, rpath, de->d_name, 1);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700504 ci->next = dirlist;
505 dirlist = ci;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800506 } else {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700507 ci = mkcopyinfo(lpath, rpath, de->d_name, 0);
508 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700509 fprintf(stderr, "adb: skipping special file '%s'\n", ci->src);
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700510 free(ci);
511 } else {
512 ci->time = st.st_mtime;
513 ci->mode = st.st_mode;
514 ci->size = st.st_size;
515 ci->next = *filelist;
516 *filelist = ci;
517 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800518 }
Daniel Rosenberge9a1c9c2014-06-30 20:29:40 -0700519 } else {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700520 fprintf(stderr, "adb: cannot lstat '%s': %s\n",stat_path , strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800521 }
522 }
523
Elliott Hughesb628cb12015-08-03 10:38:08 -0700524 // Close this directory and recurse.
525 dir.reset();
526 for (ci = dirlist; ci != 0; ci = next) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800527 next = ci->next;
528 local_build_list(filelist, ci->src, ci->dst);
529 free(ci);
530 }
531
532 return 0;
533}
534
Elliott Hughesb628cb12015-08-03 10:38:08 -0700535static bool copy_local_dir_remote(SyncConnection& sc, const char* lpath, const char* rpath,
536 bool check_timestamps, bool list_only) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800537 copyinfo *filelist = 0;
538 copyinfo *ci, *next;
539 int pushed = 0;
540 int skipped = 0;
541
Elliott Hughesb628cb12015-08-03 10:38:08 -0700542 if ((lpath[0] == 0) || (rpath[0] == 0)) return false;
543 if (lpath[strlen(lpath) - 1] != '/') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800544 int tmplen = strlen(lpath)+2;
Dan Albertf30d73c2015-02-25 17:51:28 -0800545 char *tmp = reinterpret_cast<char*>(malloc(tmplen));
Elliott Hughesb628cb12015-08-03 10:38:08 -0700546 if(tmp == 0) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800547 snprintf(tmp, tmplen, "%s/",lpath);
548 lpath = tmp;
549 }
Elliott Hughesb628cb12015-08-03 10:38:08 -0700550 if (rpath[strlen(rpath) - 1] != '/') {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800551 int tmplen = strlen(rpath)+2;
Dan Albertf30d73c2015-02-25 17:51:28 -0800552 char *tmp = reinterpret_cast<char*>(malloc(tmplen));
Elliott Hughesb628cb12015-08-03 10:38:08 -0700553 if(tmp == 0) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800554 snprintf(tmp, tmplen, "%s/",rpath);
555 rpath = tmp;
556 }
557
Elliott Hughesb628cb12015-08-03 10:38:08 -0700558 if (local_build_list(&filelist, lpath, rpath)) {
559 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800560 }
561
Elliott Hughesb628cb12015-08-03 10:38:08 -0700562 if (check_timestamps) {
563 for (ci = filelist; ci != 0; ci = ci->next) {
Elliott Hughesdde00be2015-09-27 12:55:37 -0700564 if (!sc.SendRequest(ID_STAT, ci->dst)) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800565 }
566 for(ci = filelist; ci != 0; ci = ci->next) {
567 unsigned int timestamp, mode, size;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700568 if (!sync_finish_stat(sc, &timestamp, &mode, &size)) return false;
569 if (size == ci->size) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800570 /* for links, we cannot update the atime/mtime */
Elliott Hughesb628cb12015-08-03 10:38:08 -0700571 if ((S_ISREG(ci->mode & mode) && timestamp == ci->time) ||
572 (S_ISLNK(ci->mode & mode) && timestamp >= ci->time)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800573 ci->flag = 1;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700574 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800575 }
576 }
577 }
Elliott Hughesb628cb12015-08-03 10:38:08 -0700578 for (ci = filelist; ci != 0; ci = next) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800579 next = ci->next;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700580 if (ci->flag == 0) {
581 fprintf(stderr, "%spush: %s -> %s\n", list_only ? "would " : "", ci->src, ci->dst);
582 if (!list_only && !sync_send(sc, ci->src, ci->dst, ci->time, ci->mode, false)) {
583 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800584 }
585 pushed++;
586 } else {
587 skipped++;
588 }
589 free(ci);
590 }
591
Elliott Hughesb628cb12015-08-03 10:38:08 -0700592 fprintf(stderr, "%d file%s pushed. %d file%s skipped.\n",
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800593 pushed, (pushed == 1) ? "" : "s",
594 skipped, (skipped == 1) ? "" : "s");
595
Elliott Hughesb628cb12015-08-03 10:38:08 -0700596 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800597}
598
Elliott Hughesb628cb12015-08-03 10:38:08 -0700599bool do_sync_push(const char* lpath, const char* rpath, bool show_progress) {
600 SyncConnection sc;
601 if (!sc.IsValid()) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800602
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700603 struct stat st;
604 if (stat(lpath, &st)) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700605 fprintf(stderr, "adb: cannot stat '%s': %s\n", lpath, strerror(errno));
Elliott Hughesb628cb12015-08-03 10:38:08 -0700606 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800607 }
608
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700609 if (S_ISDIR(st.st_mode)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700610 return copy_local_dir_remote(sc, lpath, rpath, false, false);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800611 }
612
Elliott Hughesb628cb12015-08-03 10:38:08 -0700613 unsigned mode;
614 if (!sync_stat(sc, rpath, nullptr, &mode, nullptr)) return false;
615 std::string path_holder;
616 if (mode != 0 && S_ISDIR(mode)) {
617 // If we're copying a local file to a remote directory,
618 // we really want to copy to remote_dir + "/" + local_filename.
619 path_holder = android::base::StringPrintf("%s/%s", rpath, adb_basename(lpath).c_str());
620 rpath = path_holder.c_str();
621 }
622 return sync_send(sc, lpath, rpath, st.st_mtime, st.st_mode, show_progress);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800623}
624
625
Elliott Hughesfe7ff812015-04-17 09:47:42 -0700626struct sync_ls_build_list_cb_args {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800627 copyinfo **filelist;
628 copyinfo **dirlist;
629 const char *rpath;
630 const char *lpath;
Elliott Hughesfe7ff812015-04-17 09:47:42 -0700631};
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800632
Elliott Hughes712416a2015-05-05 18:26:10 -0700633static void sync_ls_build_list_cb(unsigned mode, unsigned size, unsigned time,
634 const char* name, void* cookie)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800635{
636 sync_ls_build_list_cb_args *args = (sync_ls_build_list_cb_args *)cookie;
637 copyinfo *ci;
638
639 if (S_ISDIR(mode)) {
640 copyinfo **dirlist = args->dirlist;
641
Elliott Hughesb628cb12015-08-03 10:38:08 -0700642 // Don't try recursing down "." or "..".
643 if (IsDotOrDotDot(name)) return;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800644
645 ci = mkcopyinfo(args->rpath, args->lpath, name, 1);
646 ci->next = *dirlist;
647 *dirlist = ci;
648 } else if (S_ISREG(mode) || S_ISLNK(mode)) {
649 copyinfo **filelist = args->filelist;
650
651 ci = mkcopyinfo(args->rpath, args->lpath, name, 0);
652 ci->time = time;
653 ci->mode = mode;
654 ci->size = size;
655 ci->next = *filelist;
656 *filelist = ci;
657 } else {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700658 fprintf(stderr, "adb: skipping special file '%s'\n", name);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800659 }
660}
661
Elliott Hughesdde00be2015-09-27 12:55:37 -0700662static bool remote_build_list(SyncConnection& sc, copyinfo **filelist,
Elliott Hughesb628cb12015-08-03 10:38:08 -0700663 const char *rpath, const char *lpath) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800664 copyinfo *dirlist = NULL;
665 sync_ls_build_list_cb_args args;
666
667 args.filelist = filelist;
668 args.dirlist = &dirlist;
669 args.rpath = rpath;
670 args.lpath = lpath;
671
Elliott Hughesb628cb12015-08-03 10:38:08 -0700672 // Put the files/dirs in rpath on the lists.
Elliott Hughesdde00be2015-09-27 12:55:37 -0700673 if (!sync_ls(sc, rpath, sync_ls_build_list_cb, (void *)&args)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700674 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800675 }
676
Elliott Hughesb628cb12015-08-03 10:38:08 -0700677 // Recurse into each directory we found.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800678 while (dirlist != NULL) {
679 copyinfo *next = dirlist->next;
Elliott Hughesdde00be2015-09-27 12:55:37 -0700680 if (!remote_build_list(sc, filelist, dirlist->src, dirlist->dst)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700681 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800682 }
683 free(dirlist);
684 dirlist = next;
685 }
686
Elliott Hughesb628cb12015-08-03 10:38:08 -0700687 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800688}
689
Dan Albertf30d73c2015-02-25 17:51:28 -0800690static int set_time_and_mode(const char *lpath, time_t time, unsigned int mode)
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700691{
Greg Hackmann8b689142014-05-06 08:48:18 -0700692 struct utimbuf times = { time, time };
693 int r1 = utime(lpath, &times);
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700694
695 /* use umask for permissions */
696 mode_t mask=umask(0000);
697 umask(mask);
698 int r2 = chmod(lpath, mode & ~mask);
699
700 return r1 ? : r2;
701}
702
Elliott Hughesb628cb12015-08-03 10:38:08 -0700703static bool copy_remote_dir_local(SyncConnection& sc, const char* rpath, const char* lpath,
704 int copy_attrs) {
705 // Make sure that both directory paths end in a slash.
706 std::string rpath_clean(rpath);
707 std::string lpath_clean(lpath);
708 if (rpath_clean.empty() || lpath_clean.empty()) return false;
709 if (rpath_clean.back() != '/') rpath_clean.push_back('/');
710 if (lpath_clean.back() != '/') lpath_clean.push_back('/');
Riley Andrewsc736a942014-12-12 13:12:36 -0800711
Elliott Hughesb628cb12015-08-03 10:38:08 -0700712 // Recursively build the list of files to copy.
713 fprintf(stderr, "pull: building file list...\n");
714 copyinfo* filelist = nullptr;
Elliott Hughesdde00be2015-09-27 12:55:37 -0700715 if (!remote_build_list(sc, &filelist, rpath_clean.c_str(), lpath_clean.c_str())) return false;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700716
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800717 int pulled = 0;
718 int skipped = 0;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700719 copyinfo* ci = filelist;
720 while (ci) {
721 copyinfo* next = ci->next;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800722 if (ci->flag == 0) {
723 fprintf(stderr, "pull: %s -> %s\n", ci->src, ci->dst);
Elliott Hughesdde00be2015-09-27 12:55:37 -0700724 if (!sync_recv(sc, ci->src, ci->dst, false)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700725 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800726 }
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700727
728 if (copy_attrs && set_time_and_mode(ci->dst, ci->time, ci->mode)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700729 return false;
Lajos Molnar4e23e3c2013-04-19 12:41:09 -0700730 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800731 pulled++;
732 } else {
733 skipped++;
734 }
735 free(ci);
Elliott Hughesb628cb12015-08-03 10:38:08 -0700736 ci = next;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800737 }
738
739 fprintf(stderr, "%d file%s pulled. %d file%s skipped.\n",
740 pulled, (pulled == 1) ? "" : "s",
741 skipped, (skipped == 1) ? "" : "s");
Elliott Hughesb628cb12015-08-03 10:38:08 -0700742 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800743}
744
Elliott Hughesb628cb12015-08-03 10:38:08 -0700745bool do_sync_pull(const char* rpath, const char* lpath, bool show_progress, int copy_attrs) {
746 SyncConnection sc;
747 if (!sc.IsValid()) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800748
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700749 unsigned mode, time;
Elliott Hughesb628cb12015-08-03 10:38:08 -0700750 if (!sync_stat(sc, rpath, &time, &mode, nullptr)) return false;
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700751 if (mode == 0) {
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700752 fprintf(stderr, "adb: remote object '%s' does not exist\n", rpath);
Elliott Hughesb628cb12015-08-03 10:38:08 -0700753 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800754 }
755
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700756 if (S_ISREG(mode) || S_ISLNK(mode) || S_ISCHR(mode) || S_ISBLK(mode)) {
757 std::string path_holder;
758 struct stat st;
759 if (stat(lpath, &st) == 0) {
760 if (S_ISDIR(st.st_mode)) {
761 // If we're copying a remote file to a local directory,
762 // we really want to copy to local_dir + "/" + basename(remote).
763 path_holder = android::base::StringPrintf("%s/%s", lpath, adb_basename(rpath).c_str());
764 lpath = path_holder.c_str();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800765 }
766 }
Elliott Hughesdde00be2015-09-27 12:55:37 -0700767 if (!sync_recv(sc, rpath, lpath, show_progress)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700768 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800769 } else {
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700770 if (copy_attrs && set_time_and_mode(lpath, time, mode)) {
Elliott Hughesb628cb12015-08-03 10:38:08 -0700771 return false;
Elliott Hughesd189cfb2015-07-30 17:42:01 -0700772 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800773 }
Elliott Hughesb628cb12015-08-03 10:38:08 -0700774 return true;
775 } else if (S_ISDIR(mode)) {
776 return copy_remote_dir_local(sc, rpath, lpath, copy_attrs);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800777 }
Elliott Hughesb628cb12015-08-03 10:38:08 -0700778
Elliott Hughese4ed32f2015-10-23 21:06:11 -0700779 fprintf(stderr, "adb: remote object '%s' not a file or directory\n", rpath);
Elliott Hughesb628cb12015-08-03 10:38:08 -0700780 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800781}
782
Elliott Hughesb628cb12015-08-03 10:38:08 -0700783bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only) {
Elliott Hughesc5a12b22015-04-21 10:17:07 -0700784 fprintf(stderr, "syncing %s...\n", rpath.c_str());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800785
Elliott Hughesb628cb12015-08-03 10:38:08 -0700786 SyncConnection sc;
787 if (!sc.IsValid()) return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800788
Elliott Hughesb628cb12015-08-03 10:38:08 -0700789 return copy_local_dir_remote(sc, lpath.c_str(), rpath.c_str(), true, list_only);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800790}